1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/bert_storage.h>
4 #include <console/console.h>
5 #include <device/pci_ops.h>
6 #include <intelblocks/crashlog.h>
7 #include <intelblocks/pmc_ipc.h>
8 #include <soc/crashlog.h>
10 #include <soc/pci_devs.h>
13 /* global crashLog info */
14 static bool m_pmc_crashLog_support
;
15 static bool m_pmc_crashLog_present
;
16 static bool m_cpu_crashLog_support
;
17 static bool m_cpu_crashLog_present
;
18 static u32 m_pmc_crashLog_size
;
19 static u32 m_cpu_crashLog_size
;
20 static u32 cpu_crash_version
;
21 static pmc_ipc_discovery_buf_t discovery_buf
;
22 static pmc_crashlog_desc_table_t descriptor_table
;
23 static tel_crashlog_devsc_cap_t cpu_cl_devsc_cap
;
24 static cpu_crashlog_discovery_table_t cpu_cl_disc_tab
;
26 uintptr_t __weak
cl_get_cpu_mb_int_addr(void)
28 return CRASHLOG_MAILBOX_INTF_ADDRESS
;
31 /* Get the SRAM BAR. */
32 static uintptr_t sram_get_bar(void)
35 const struct device
*dev
;
38 dev
= pcidev_path_on_root(PCH_DEVFN_SRAM
);
40 printk(BIOS_ERR
, "PCH_DEVFN_SRAM device not found!\n");
44 res
= probe_resource(dev
, PCI_BASE_ADDRESS_0
);
46 printk(BIOS_ERR
, "PCH SRAM device not found!\n");
50 /* Get the base address of the resource */
56 bool pmc_cl_discovery(void)
58 u32 tmp_bar_addr
= 0, desc_table_addr
= 0;
60 const struct pmc_ipc_buffer req
= { 0 };
61 struct pmc_ipc_buffer res
;
65 cmd_reg
= pmc_make_ipc_cmd(PMC_IPC_CMD_CRASHLOG
,
66 PMC_IPC_CMD_ID_CRASHLOG_DISCOVERY
,
67 PMC_IPC_CMD_SIZE_SHIFT
);
68 printk(BIOS_DEBUG
, "cmd_reg from pmc_make_ipc_cmd %d\n", cmd_reg
);
70 r
= pmc_send_ipc_cmd(cmd_reg
, &req
, &res
);
73 printk(BIOS_ERR
, "pmc_send_ipc_cmd failed in %s\n", __func__
);
76 discovery_buf
.val_64_bits
= ((u64
)res
.buf
[1] << 32) | res
.buf
[0];
79 if (discovery_buf
.bits
.supported
!= 1) {
80 printk(BIOS_INFO
, "PCH crashlog feature not supported.\n");
81 m_pmc_crashLog_support
= false;
84 m_pmc_crashLog_support
= true;
86 tmp_bar_addr
= sram_get_bar();
87 if (tmp_bar_addr
== 0) {
88 printk(BIOS_ERR
, "PCH SRAM not available, crashlog feature can't be enabled.\n");
92 if (discovery_buf
.bits
.discov_mechanism
== 1) {
94 if (discovery_buf
.bits
.base_offset
& BIT(31)) {
95 printk(BIOS_DEBUG
, "PCH discovery to be used is disabled.\n");
96 m_pmc_crashLog_present
= false;
97 m_pmc_crashLog_size
= 0;
100 desc_table_addr
= tmp_bar_addr
+ discovery_buf
.bits
.desc_tabl_offset
;
101 m_pmc_crashLog_size
= pmc_cl_gen_descriptor_table(desc_table_addr
,
103 printk(BIOS_DEBUG
, "PMC CrashLog size in discovery mode: 0x%X\n",
104 m_pmc_crashLog_size
);
107 if (discovery_buf
.bits
.dis
) {
108 printk(BIOS_DEBUG
, "PCH crashlog is disabled in legacy mode.\n");
109 m_pmc_crashLog_present
= false;
112 m_pmc_crashLog_size
= (discovery_buf
.bits
.size
!= 0) ?
113 (discovery_buf
.bits
.size
* sizeof(u32
)) : 0xC00;
114 printk(BIOS_DEBUG
, "PMC crashlog size in legacy mode = 0x%x\n",
115 m_pmc_crashLog_size
);
117 m_pmc_crashLog_present
= true;
122 uintptr_t cl_get_cpu_bar_addr(void)
125 if (cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
== TEL_DVSEC_TBIR_BAR0
) {
126 base_addr
= pci_read_config32(SA_DEV_TMT
, PCI_BASE_ADDRESS_0
) &
127 ~PCI_BASE_ADDRESS_MEM_ATTR_MASK
;
128 } else if (cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
== TEL_DVSEC_TBIR_BAR1
) {
129 base_addr
= pci_read_config32(SA_DEV_TMT
, PCI_BASE_ADDRESS_1
) &
130 ~PCI_BASE_ADDRESS_MEM_ATTR_MASK
;
132 printk(BIOS_ERR
, "Invalid TEL_CFG_BAR value %d, discovery failure expected.\n",
133 cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
);
140 uintptr_t cl_get_cpu_tmp_bar(void)
142 return sram_get_bar();
145 bool cl_pmc_sram_has_mmio_access(void)
147 if (pci_read_config16(PCH_DEV_SRAM
, PCI_VENDOR_ID
) == 0xFFFF) {
148 printk(BIOS_ERR
, "PMC SSRAM PCI device disabled. Can be enabled in device tree.\n");
155 static bool cpu_cl_get_capability(tel_crashlog_devsc_cap_t
*cl_devsc_cap
)
157 cl_devsc_cap
->cap_data
.data
= pci_read_config32(SA_DEV_TMT
,
158 TEL_DVSEC_OFFSET
+ TEL_DVSEC_PCIE_CAP_ID
);
159 if (cl_devsc_cap
->cap_data
.fields
.pcie_cap_id
!= TELEMETRY_EXTENDED_CAP_ID
) {
160 printk(BIOS_DEBUG
, "Read ID for Telemetry: 0x%x differs from expected: 0x%x\n",
161 cl_devsc_cap
->cap_data
.fields
.pcie_cap_id
, TELEMETRY_EXTENDED_CAP_ID
);
165 /* walk through the entries until crashLog entry */
166 cl_devsc_cap
->devsc_data
.data_32
[1] = pci_read_config32(SA_DEV_TMT
, TEL_DVSEV_ID
);
168 while (cl_devsc_cap
->devsc_data
.fields
.devsc_id
!= CRASHLOG_DVSEC_ID
) {
169 if (cl_devsc_cap
->cap_data
.fields
.next_cap_offset
== 0
170 || cl_devsc_cap
->cap_data
.fields
.next_cap_offset
== 0xFFFF) {
171 printk(BIOS_DEBUG
, "Read invalid pcie_cap_id value: 0x%x\n",
172 cl_devsc_cap
->cap_data
.fields
.pcie_cap_id
);
175 new_offset
= cl_devsc_cap
->cap_data
.fields
.next_cap_offset
;
176 cl_devsc_cap
->cap_data
.data
= pci_read_config32(SA_DEV_TMT
,
177 new_offset
+ TEL_DVSEC_PCIE_CAP_ID
);
178 cl_devsc_cap
->devsc_data
.data_32
[1] = pci_read_config32(SA_DEV_TMT
,
179 new_offset
+ TEL_DVSEV_ID
);
181 cpu_crash_version
= cl_devsc_cap
->devsc_data
.fields
.devsc_ver
;
183 cl_devsc_cap
->discovery_data
.data
= pci_read_config32(SA_DEV_TMT
, new_offset
184 + TEL_DVSEV_DISCOVERY_TABLE_OFFSET
);
190 static bool cpu_cl_gen_discovery_table(void)
192 uintptr_t bar_addr
= 0, disc_tab_addr
= 0;
193 bar_addr
= cl_get_cpu_bar_addr();
198 disc_tab_addr
= bar_addr
+
199 cpu_cl_devsc_cap
.discovery_data
.fields
.discovery_table_offset
;
200 memset(&cpu_cl_disc_tab
, 0, sizeof(cpu_crashlog_discovery_table_t
));
202 printk(BIOS_DEBUG
, "cpu discovery table offset: 0x%x\n",
203 cpu_cl_devsc_cap
.discovery_data
.fields
.discovery_table_offset
);
205 cpu_cl_disc_tab
.header
.data
= ((u64
)read32((u32
*)disc_tab_addr
) +
206 ((u64
)read32((u32
*)(disc_tab_addr
+ 4)) << 32));
208 cpu_cl_disc_tab
.cmd_mailbox
.data
= read32((u32
*)(disc_tab_addr
+ 8));
209 cpu_cl_disc_tab
.mailbox_data
= read32((u32
*)(disc_tab_addr
+ 12));
211 printk(BIOS_DEBUG
, "cpu_crashlog_discovery_table buffer count: 0x%x\n",
212 cpu_cl_disc_tab
.header
.fields
.count
);
215 for (int i
= 0; i
< cpu_cl_disc_tab
.header
.fields
.count
; i
++) {
216 cur_offset
= 16 + 8*i
;
217 cpu_cl_disc_tab
.buffers
[i
].data
= ((u64
)read32((u32
*)(disc_tab_addr
+
218 cur_offset
)) + ((u64
)read32((u32
*)
219 (disc_tab_addr
+ cur_offset
+ 4)) << 32));
220 printk(BIOS_DEBUG
, "cpu_crashlog_discovery_table buffer: 0x%x size: "
221 "0x%x offset: 0x%x\n", i
, cpu_cl_disc_tab
.buffers
[i
].fields
.size
,
222 cpu_cl_disc_tab
.buffers
[i
].fields
.offset
);
223 m_cpu_crashLog_size
+= cpu_cl_disc_tab
.buffers
[i
].fields
.size
* sizeof(u32
);
226 m_cpu_crashLog_present
= m_cpu_crashLog_size
> 0;
231 bool cpu_cl_discovery(void)
233 memset(&cpu_cl_devsc_cap
, 0, sizeof(tel_crashlog_devsc_cap_t
));
235 if (!cpu_cl_get_capability(&cpu_cl_devsc_cap
)) {
236 printk(BIOS_ERR
, "CPU crashlog capability not found.\n");
237 m_cpu_crashLog_support
= false;
241 m_cpu_crashLog_support
= true;
243 const struct resource
*res
= find_resource(SA_DEV_TMT
, PCI_BASE_ADDRESS_0
);
244 printk(BIOS_DEBUG
, "cpu crashlog bar addr: 0x%llX\n", res
->base
);
246 if (!cpu_cl_gen_discovery_table()) {
247 printk(BIOS_ERR
, "CPU crashlog discovery table not valid.\n");
248 m_cpu_crashLog_present
= false;
255 void reset_discovery_buffers(void)
257 memset(&discovery_buf
, 0, sizeof(pmc_ipc_discovery_buf_t
));
258 memset(&descriptor_table
, 0, sizeof(pmc_crashlog_desc_table_t
));
259 memset(&cpu_cl_devsc_cap
, 0, sizeof(tel_crashlog_devsc_cap_t
));
262 int cl_get_total_data_size(void)
264 return m_pmc_crashLog_size
+ m_cpu_crashLog_size
;
267 pmc_ipc_discovery_buf_t
cl_get_pmc_discovery_buf(void)
269 return discovery_buf
;
272 pmc_crashlog_desc_table_t
cl_get_pmc_descriptor_table(void)
274 return descriptor_table
;
277 int cl_get_pmc_record_size(void)
279 return m_pmc_crashLog_size
;
282 int cl_get_cpu_record_size(void)
284 return m_cpu_crashLog_size
;
287 bool cl_cpu_data_present(void)
289 return m_cpu_crashLog_present
;
292 bool cl_pmc_data_present(void)
294 return m_pmc_crashLog_present
;
297 bool cpu_crashlog_support(void)
299 return m_cpu_crashLog_support
;
302 bool pmc_crashlog_support(void)
304 return m_pmc_crashLog_support
;
307 void update_new_pmc_crashlog_size(u32
*pmc_crash_size
)
309 m_pmc_crashLog_size
= *pmc_crash_size
;
312 cpu_crashlog_discovery_table_t
cl_get_cpu_discovery_table(void)
314 return cpu_cl_disc_tab
;
317 void update_new_cpu_crashlog_size(u32
*cpu_crash_size
)
319 m_cpu_crashLog_size
= *cpu_crash_size
;