blob: 9d3c5d60e470b812cea40c05a5f8fa37cdb7a8ac [file] [log] [blame]
Pratikkumar Prajapati17e94902023-05-25 16:53:44 -07001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <arch/bert_storage.h>
4#include <console/console.h>
Pratikkumar Prajapati0dc607f2023-07-10 15:44:21 -07005#include <cpu/cpu.h>
6#include <cpu/intel/cpu_ids.h>
Pratikkumar Prajapati17e94902023-05-25 16:53:44 -07007#include <device/pci_ops.h>
8#include <intelblocks/crashlog.h>
9#include <intelblocks/pmc_ipc.h>
10#include <soc/crashlog.h>
11#include <soc/iomap.h>
12#include <soc/pci_devs.h>
13#include <string.h>
14
Pratikkumar Prajapati6cba9762023-07-10 17:16:11 -070015#define CRASHLOG_CONSUMED_MASK BIT(31)
16
Pratikkumar Prajapati17e94902023-05-25 16:53:44 -070017/* global crashLog info */
18static bool m_pmc_crashLog_support;
19static bool m_pmc_crashLog_present;
20static bool m_cpu_crashLog_support;
21static bool m_cpu_crashLog_present;
22static bool m_ioe_crashLog_support;
23static bool m_ioe_crashLog_present;
24static u32 m_pmc_crashLog_size;
25static u32 m_ioe_crashLog_size;
26static u32 m_cpu_crashLog_size;
27static u32 cpu_crash_version;
28static pmc_ipc_discovery_buf_t discovery_buf;
29static pmc_crashlog_desc_table_t descriptor_table;
30static tel_crashlog_devsc_cap_t cpu_cl_devsc_cap;
31static cpu_crashlog_discovery_table_t cpu_cl_disc_tab;
32
33u32 __weak cl_get_cpu_mb_int_addr(void)
34{
35 return CRASHLOG_MAILBOX_INTF_ADDRESS;
36}
37
38/* Get the SRAM BAR. */
39static uintptr_t get_sram_bar(pci_devfn_t sram_devfn)
40{
41 uintptr_t sram_bar;
42 const struct device *dev;
43 struct resource *res;
44
45 dev = pcidev_path_on_root(sram_devfn);
46 if (!dev) {
47 printk(BIOS_ERR, "device: 0x%x not found!\n", sram_devfn);
48 return 0;
49 }
50
51 res = probe_resource(dev, PCI_BASE_ADDRESS_0);
52 if (!res) {
53 printk(BIOS_ERR, "SOC SRAM device not found!\n");
54 return 0;
55 }
56
57 /* Get the base address of the resource */
58 sram_bar = res->base;
59
60 return sram_bar;
61}
62
63static void configure_sram(const struct device *sram_dev, u32 base_addr)
64{
65 pci_update_config16(sram_dev, PCI_COMMAND, ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY), 0);
66
67 /* Program BAR 0 and enable command register memory space decoding */
68 pci_write_config32(sram_dev, PCI_BASE_ADDRESS_0, base_addr);
69 pci_or_config16(sram_dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
70}
71
72void cl_get_pmc_sram_data(void)
73{
74 u32 *soc_pmc_dest = NULL, *ioe_pmc_dest = NULL;
75 u32 pmc_sram_base = cl_get_cpu_tmp_bar();
76 u32 ioe_sram_base = get_sram_bar(PCI_DEVFN_IOE_SRAM);
77 u32 pmc_crashLog_size = cl_get_pmc_record_size();
78 u32 ioe_crashLog_size = 0;
79
80 if (!pmc_sram_base) {
81 printk(BIOS_ERR, "PMC SRAM base not valid\n");
82 return;
83 }
84
85 if (!pmc_crashLog_size) {
86 printk(BIOS_ERR, "No PMC crashlog records\n");
87 return;
88 }
89
90 if (!ioe_sram_base) {
91 printk(BIOS_ERR, "IOE SRAM base not valid\n");
92 return;
93 }
94
95 configure_sram(PCI_DEV_IOE_SRAM, ioe_sram_base);
96
97 if (!cl_pmc_sram_has_mmio_access())
98 return;
99
100 if (!cl_ioe_sram_has_mmio_access())
101 return;
102
103 printk(BIOS_DEBUG, "PMC crashLog size : 0x%x\n", pmc_crashLog_size);
104
105 /* allocate memory for the PMC crash records to be copied */
106 unsigned long pmc_cl_cbmem_addr;
107
108 pmc_cl_cbmem_addr = (unsigned long) cbmem_add(CBMEM_ID_PMC_CRASHLOG,
109 pmc_crashLog_size);
110 if (!pmc_cl_cbmem_addr) {
111 printk(BIOS_ERR, "Unable to allocate CBMEM PMC crashLog entry.\n");
112 return;
113 }
114
115 memset((void *)pmc_cl_cbmem_addr, 0, pmc_crashLog_size);
116 soc_pmc_dest = (u32 *)(uintptr_t) pmc_cl_cbmem_addr;
117
118 bool pmc_sram = true;
119
120 /* process crashlog records for SOC PMC SRAM */
121 for (int i = 0; i < descriptor_table.numb_regions + 1; i++) {
122 printk(BIOS_DEBUG, "Region[0x%x].Tag=0x%x offset=0x%x, size=0x%x\n",
123 i,
124 descriptor_table.regions[i].bits.assign_tag,
125 descriptor_table.regions[i].bits.offset,
126 descriptor_table.regions[i].bits.size);
127
128 if (!descriptor_table.regions[i].bits.size)
129 continue;
130
131 if (descriptor_table.regions[i].bits.assign_tag ==
132 CRASHLOG_DESCRIPTOR_TABLE_TAG_SOC) {
133
134 if (cl_copy_data_from_sram(pmc_sram_base,
135 descriptor_table.regions[i].bits.offset,
136 descriptor_table.regions[i].bits.size,
137 soc_pmc_dest,
138 i,
139 pmc_sram)) {
140 soc_pmc_dest = (u32 *)((u32)soc_pmc_dest +
141 (descriptor_table.regions[i].bits.size
142 * sizeof(u32)));
143 } else {
144 pmc_crashLog_size -= descriptor_table.regions[i].bits.size *
145 sizeof(u32);
146 printk(BIOS_DEBUG, "PMC crashlog size adjusted to: 0x%x\n",
147 pmc_crashLog_size);
148 }
149 } else if (descriptor_table.regions[i].bits.assign_tag ==
150 CRASHLOG_DESCRIPTOR_TABLE_TAG_IOE) {
151 /*
152 * SOC PMC crashlog records contains information about IOE SRAM
153 * records as well. Calculate IOE records size while parsing SOC
154 * PME SRAM.
155 */
156 ioe_crashLog_size += descriptor_table.regions[i].bits.size * sizeof(u32);
157 }
158 }
159
160 pmc_crashLog_size -= ioe_crashLog_size;
161 update_new_pmc_crashlog_size(&pmc_crashLog_size);
162
163 if (ioe_crashLog_size)
164 m_ioe_crashLog_present = true;
165 else
166 goto pmc_send_re_arm_after_reset;
167
168 /* allocate memory for the IOE crashlog records to be copied */
169 unsigned long ioe_cl_cbmem_addr;
170
171 ioe_cl_cbmem_addr = (unsigned long) cbmem_add(CBMEM_ID_IOE_CRASHLOG,
172 ioe_crashLog_size);
173 if (!ioe_cl_cbmem_addr) {
174 printk(BIOS_ERR, "Unable to allocate CBMEM IOE crashLog entry.\n");
175 return;
176 }
177
178 memset((void *)ioe_cl_cbmem_addr, 0, ioe_crashLog_size);
179 ioe_pmc_dest = (u32 *)(uintptr_t) ioe_cl_cbmem_addr;
180
181 /* process crashlog records for IOE SRAM */
182 for (int i = 0; i < descriptor_table.numb_regions + 1; i++) {
183 printk(BIOS_DEBUG, "Region[0x%x].Tag=0x%x offset=0x%x, size=0x%x\n",
184 i,
185 descriptor_table.regions[i].bits.assign_tag,
186 descriptor_table.regions[i].bits.offset,
187 descriptor_table.regions[i].bits.size);
188
189 if (!descriptor_table.regions[i].bits.size)
190 continue;
191
192 if (descriptor_table.regions[i].bits.assign_tag ==
193 CRASHLOG_DESCRIPTOR_TABLE_TAG_IOE) {
194
195 if (cl_copy_data_from_sram(ioe_sram_base,
196 descriptor_table.regions[i].bits.offset,
197 descriptor_table.regions[i].bits.size,
198 ioe_pmc_dest,
199 i,
200 pmc_sram)) {
201 ioe_pmc_dest = (u32 *)((u32)ioe_pmc_dest +
202 (descriptor_table.regions[i].bits.size
203 * sizeof(u32)));
204 } else {
205
206 ioe_crashLog_size -= descriptor_table.regions[i].bits.size *
207 sizeof(u32);
208 printk(BIOS_DEBUG, "IOE crashlog size adjusted to: 0x%x\n",
209 ioe_crashLog_size);
210 }
211 }
212 }
213
214 update_new_ioe_crashlog_size(&ioe_crashLog_size);
215
216pmc_send_re_arm_after_reset:
217 /* when bit 7 of discov cmd resp is set -> bit 2 of size field */
218 cl_pmc_re_arm_after_reset();
219
220 /* Clear the SSRAM region after copying the error log */
221 cl_pmc_clear();
222}
223
224bool pmc_cl_discovery(void)
225{
226 u32 bar_addr = 0, desc_table_addr = 0;
227
228 const struct pmc_ipc_buffer req = { 0 };
229 struct pmc_ipc_buffer res;
230 uint32_t cmd_reg;
231 int r;
232
233 cmd_reg = pmc_make_ipc_cmd(PMC_IPC_CMD_CRASHLOG,
234 PMC_IPC_CMD_ID_CRASHLOG_DISCOVERY,
235 PMC_IPC_CMD_SIZE_SHIFT);
236 printk(BIOS_DEBUG, "cmd_reg from pmc_make_ipc_cmd %d in %s\n", cmd_reg, __func__);
237
238 r = pmc_send_ipc_cmd(cmd_reg, &req, &res);
239
240 if (r < 0) {
241 printk(BIOS_ERR, "pmc_send_ipc_cmd failed in %s\n", __func__);
242 return false;
243 }
244 discovery_buf.conv_val_64_bits = ((u64)res.buf[1] << 32) | res.buf[0];
245
246 if ((discovery_buf.conv_bits64.supported != 1) ||
247 (discovery_buf.conv_bits64.discov_mechanism == 0) ||
248 (discovery_buf.conv_bits64.crash_dis_sts == 1)) {
249 printk(BIOS_INFO, "PCH crashlog feature not supported.\n");
250 m_pmc_crashLog_support = false;
251 m_ioe_crashLog_support = false;
252 m_pmc_crashLog_size = 0;
253 m_ioe_crashLog_size = 0;
254 printk(BIOS_DEBUG, "discovery_buf supported: %d, mechanism: %d, CrashDisSts: %d\n",
255 discovery_buf.conv_bits64.supported,
256 discovery_buf.conv_bits64.discov_mechanism,
257 discovery_buf.conv_bits64.crash_dis_sts);
258 return false;
259 }
260
261 printk(BIOS_INFO, "PMC crashlog feature is supported.\n");
262 m_pmc_crashLog_support = true;
263
264 /* Program BAR 0 and enable command register memory space decoding */
265 bar_addr = get_sram_bar(PCI_DEVFN_SRAM);
266 if (bar_addr == 0) {
267 printk(BIOS_ERR, "PCH SRAM not available, crashlog feature can't be enabled.\n");
268 return false;
269 }
270
271 configure_sram(PCI_DEV_SRAM, bar_addr);
272
273 desc_table_addr = bar_addr + discovery_buf.conv_bits64.desc_tabl_offset;
274 m_pmc_crashLog_size = pmc_cl_gen_descriptor_table(desc_table_addr,
275 &descriptor_table);
276 printk(BIOS_DEBUG, "PMC CrashLog size in discovery mode: 0x%X\n",
277 m_pmc_crashLog_size);
278 m_pmc_crashLog_present = m_pmc_crashLog_size > 0;
279
280 return true;
281}
282
283u32 cl_get_cpu_bar_addr(void)
284{
285 u32 base_addr = 0;
286 if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR0) {
287 base_addr = pci_read_config32(PCI_DEV_TELEMETRY, PCI_BASE_ADDRESS_0) &
288 ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
289 } else if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR1) {
290 base_addr = pci_read_config32(PCI_DEV_TELEMETRY, PCI_BASE_ADDRESS_1) &
291 ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
292 } else {
293 printk(BIOS_ERR, "Invalid TEL_CFG_BAR value %d, discovery failure expected.\n",
294 cpu_cl_devsc_cap.discovery_data.fields.t_bir_q);
295 }
296
297 return base_addr;
298}
299
300u32 cl_get_cpu_tmp_bar(void)
301{
302 return get_sram_bar(PCI_DEVFN_SRAM);
303}
304
305bool cl_pmc_sram_has_mmio_access(void)
306{
307 if (pci_read_config16(PCI_DEV_SRAM, PCI_VENDOR_ID) == 0xFFFF) {
308 printk(BIOS_ERR, "PMC SSRAM PCI device disabled. Can be enabled in device tree.\n");
309 return false;
310 }
311
312 return true;
313}
314
315bool cl_ioe_sram_has_mmio_access(void)
316{
317 if (pci_read_config16(PCI_DEV_IOE_SRAM, PCI_VENDOR_ID) == 0xFFFF) {
318 printk(BIOS_ERR, "IOE SSRAM PCI device disabled. Can be enabled in device tree.\n");
319 return false;
320 }
321 return true;
322}
323
324static bool cpu_cl_get_capability(tel_crashlog_devsc_cap_t *cl_devsc_cap)
325{
326 cl_devsc_cap->cap_data.data = pci_read_config32(PCI_DEV_TELEMETRY,
327 TEL_DVSEC_OFFSET + TEL_DVSEC_PCIE_CAP_ID);
328 if (cl_devsc_cap->cap_data.fields.pcie_cap_id != TELEMETRY_EXTENDED_CAP_ID) {
329 printk(BIOS_DEBUG, "Read ID for Telemetry: 0x%x differs from expected: 0x%x\n",
330 cl_devsc_cap->cap_data.fields.pcie_cap_id, TELEMETRY_EXTENDED_CAP_ID);
331 return false;
332 }
333
334 /* walk through the entries until crashLog entry */
335 cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(PCI_DEV_TELEMETRY, TEL_DVSEV_ID);
336 int new_offset = 0;
337 while (cl_devsc_cap->devsc_data.fields.devsc_id != CRASHLOG_DVSEC_ID) {
338 if (cl_devsc_cap->cap_data.fields.next_cap_offset == 0
339 || cl_devsc_cap->cap_data.fields.next_cap_offset == 0xFFFF) {
340 printk(BIOS_DEBUG, "Read invalid pcie_cap_id value: 0x%x\n",
341 cl_devsc_cap->cap_data.fields.pcie_cap_id);
342 return false;
343 }
344 new_offset = cl_devsc_cap->cap_data.fields.next_cap_offset;
345 cl_devsc_cap->cap_data.data = pci_read_config32(PCI_DEV_TELEMETRY,
346 new_offset + TEL_DVSEC_PCIE_CAP_ID);
347 cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(PCI_DEV_TELEMETRY,
348 new_offset + TEL_DVSEV_ID);
349 }
350 cpu_crash_version = cl_devsc_cap->devsc_data.fields.devsc_ver;
351
352 cl_devsc_cap->discovery_data.data = pci_read_config32(PCI_DEV_TELEMETRY, new_offset
353 + TEL_DVSEV_DISCOVERY_TABLE_OFFSET);
354
355 return true;
356}
357
Pratikkumar Prajapati0dc607f2023-07-10 15:44:21 -0700358static u32 get_disc_table_offset(void)
359{
360 u32 offset = cpu_cl_devsc_cap.discovery_data.fields.discovery_table_offset;
361 if (cpu_get_cpuid() >= CPUID_METEORLAKE_B0) {
362 offset <<= 3;
363 printk(BIOS_DEBUG, "adjusted cpu discovery table offset: 0x%x\n", offset);
364 }
365
366 return offset;
367}
368
Pratikkumar Prajapati6cba9762023-07-10 17:16:11 -0700369static bool is_crashlog_data_valid(u32 dw0)
370{
371 return (dw0 != 0x0 && dw0 != INVALID_CRASHLOG_RECORD);
372}
373
Pratikkumar Prajapati17e94902023-05-25 16:53:44 -0700374static bool cpu_cl_gen_discovery_table(void)
375{
376 u32 bar_addr = 0, disc_tab_addr = 0;
377 bar_addr = cl_get_cpu_bar_addr();
378
379 if (!bar_addr)
380 return false;
381
Pratikkumar Prajapati0dc607f2023-07-10 15:44:21 -0700382 disc_tab_addr = bar_addr + get_disc_table_offset();
Pratikkumar Prajapati6cba9762023-07-10 17:16:11 -0700383
384 u32 dw0 = read32((u32 *)disc_tab_addr);
385 if (!is_crashlog_data_valid(dw0))
386 return false;
387
Pratikkumar Prajapati17e94902023-05-25 16:53:44 -0700388 memset(&cpu_cl_disc_tab, 0, sizeof(cpu_crashlog_discovery_table_t));
Pratikkumar Prajapati17e94902023-05-25 16:53:44 -0700389 cpu_cl_disc_tab.header.data = ((u64)read32((u32 *)disc_tab_addr) +
390 ((u64)read32((u32 *)(disc_tab_addr + 4)) << 32));
Pratikkumar Prajapati17e94902023-05-25 16:53:44 -0700391 printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer count: 0x%x\n",
392 cpu_cl_disc_tab.header.fields.count);
393
394 int cur_offset = 0;
395 for (int i = 0; i < cpu_cl_disc_tab.header.fields.count; i++) {
Pratikkumar Prajapati6cba9762023-07-10 17:16:11 -0700396 cur_offset = 8 + 24 * i;
397
398 dw0 = read32((u32 *)disc_tab_addr + cur_offset);
399 if (!is_crashlog_data_valid(dw0))
400 continue;
401
402 if (dw0 & CRASHLOG_CONSUMED_MASK) {
403 printk(BIOS_DEBUG, "cpu crashlog records already consumed."
404 "id: 0x%x dw0: 0x%x\n", i, dw0);
405 break;
406 }
407
Pratikkumar Prajapati17e94902023-05-25 16:53:44 -0700408 cpu_cl_disc_tab.buffers[i].data = ((u64)read32((u32 *)(disc_tab_addr +
409 cur_offset)) + ((u64)read32((u32 *)
410 (disc_tab_addr + cur_offset + 4)) << 32));
411 printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer: 0x%x size: "
412 "0x%x offset: 0x%x\n", i, cpu_cl_disc_tab.buffers[i].fields.size,
413 cpu_cl_disc_tab.buffers[i].fields.offset);
414 m_cpu_crashLog_size += cpu_cl_disc_tab.buffers[i].fields.size * sizeof(u32);
415 }
416
417 if (m_cpu_crashLog_size > 0)
418 m_cpu_crashLog_present = true;
419 else
420 m_cpu_crashLog_present = false;
421
422 return true;
423}
424
425bool cpu_cl_discovery(void)
426{
427 memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
428
429 if (!cpu_cl_get_capability(&cpu_cl_devsc_cap)) {
430 printk(BIOS_ERR, "CPU crashlog capability not found.\n");
431 m_cpu_crashLog_support = false;
432 return false;
433 }
434
435 m_cpu_crashLog_support = true;
436
437 if (!cpu_cl_gen_discovery_table()) {
438 printk(BIOS_ERR, "CPU crashlog discovery table not valid.\n");
439 m_cpu_crashLog_present = false;
440 return false;
441 }
442
443 return true;
444}
445
446void reset_discovery_buffers(void)
447{
448 memset(&discovery_buf, 0, sizeof(pmc_ipc_discovery_buf_t));
449 memset(&descriptor_table, 0, sizeof(pmc_crashlog_desc_table_t));
450 memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
451}
452
453int cl_get_total_data_size(void)
454{
455 printk(BIOS_DEBUG, "crashlog size:pmc-0x%x, ioe-pmc-0x%x cpu-0x%x\n",
456 m_pmc_crashLog_size, m_ioe_crashLog_size, m_cpu_crashLog_size);
457 return m_pmc_crashLog_size + m_cpu_crashLog_size + m_ioe_crashLog_size;
458}
459
460pmc_ipc_discovery_buf_t cl_get_pmc_discovery_buf(void)
461{
462 return discovery_buf;
463}
464
465pmc_crashlog_desc_table_t cl_get_pmc_descriptor_table(void)
466{
467 return descriptor_table;
468}
469
470int cl_get_pmc_record_size(void)
471{
472 return m_pmc_crashLog_size;
473}
474
475int cl_get_cpu_record_size(void)
476{
477 return m_cpu_crashLog_size;
478}
479
480int cl_get_ioe_record_size(void)
481{
482 return m_ioe_crashLog_size;
483}
484
485bool cl_cpu_data_present(void)
486{
487 return m_cpu_crashLog_present;
488}
489
490bool cl_pmc_data_present(void)
491{
492 return m_pmc_crashLog_present;
493}
494
495bool cl_ioe_data_present(void)
496{
497 return m_ioe_crashLog_present;
498}
499
500bool cpu_crashlog_support(void)
501{
502 return m_cpu_crashLog_support;
503}
504
505bool pmc_crashlog_support(void)
506{
507 return m_pmc_crashLog_support;
508}
509
510void update_new_pmc_crashlog_size(u32 *pmc_crash_size)
511{
512 m_pmc_crashLog_size = *pmc_crash_size;
513}
514
515void update_new_ioe_crashlog_size(u32 *ioe_crash_size)
516{
517 m_ioe_crashLog_size = *ioe_crash_size;
518}
519
520cpu_crashlog_discovery_table_t cl_get_cpu_discovery_table(void)
521{
522 return cpu_cl_disc_tab;
523}
524
525void update_new_cpu_crashlog_size(u32 *cpu_crash_size)
526{
527 m_cpu_crashLog_size = *cpu_crash_size;
528}