1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
4 #include <intelblocks/crashlog.h>
6 #include <soc/crashlog.h>
7 #include <arch/bert_storage.h>
9 #include <soc/pci_devs.h>
11 /* global crashLog info */
12 static bool m_pmc_crashLog_support
;
13 static bool m_pmc_crashLog_present
;
14 static bool m_cpu_crashLog_support
;
15 static bool m_cpu_crashLog_present
;
16 static u32 m_pmc_crashLog_size
;
17 static u32 m_cpu_crashLog_size
;
18 static u32 cpu_crash_version
;
19 static pmc_ipc_discovery_buf_t discovery_buf
;
20 static pmc_crashlog_desc_table_t descriptor_table
;
21 static tel_crashlog_devsc_cap_t cpu_cl_devsc_cap
;
22 static cpu_crashlog_discovery_table_t cpu_cl_disc_tab
;
24 uintptr_t __weak
cl_get_cpu_mb_int_addr(void)
26 return CRASHLOG_MAILBOX_INTF_ADDRESS
;
29 bool pmc_cl_discovery(void)
31 u32 tmp_bar_addr
= 0, desc_table_addr
= 0;
33 const struct pmc_ipc_buffer
*req
= { 0 };
34 struct pmc_ipc_buffer
*res
= NULL
;
38 cmd_reg
= pmc_make_ipc_cmd(PMC_IPC_CMD_CRASHLOG
,
39 PMC_IPC_CMD_ID_CRASHLOG_DISCOVERY
,
40 PMC_IPC_CMD_SIZE_SHIFT
);
41 printk(BIOS_DEBUG
, "cmd_reg from pmc_make_ipc_cmd %d\n", cmd_reg
);
43 r
= pmc_send_ipc_cmd(cmd_reg
, req
, res
);
46 printk(BIOS_ERR
, "pmc_send_ipc_cmd failed in %s\n", __func__
);
49 discovery_buf
.val_64_bits
= ((u64
)res
->buf
[1] << 32) | res
->buf
[0];
52 if (discovery_buf
.bits
.supported
!= 1) {
53 printk(BIOS_DEBUG
, "PCH crashlog feature not supported.\n");
54 m_pmc_crashLog_support
= false;
57 m_pmc_crashLog_support
= true;
59 /* Program BAR 0 and enable command register memory space decoding */
60 tmp_bar_addr
= SPI_BASE_ADDRESS
;
61 pci_write_config32(PCH_DEV_SRAM
, PCI_BASE_ADDRESS_0
, tmp_bar_addr
);
62 pci_or_config16(PCH_DEV_SRAM
, PCI_COMMAND
, PCI_COMMAND_MEMORY
);
64 if (discovery_buf
.bits
.discov_mechanism
== 1) {
66 if (discovery_buf
.bits
.base_offset
& BIT(31)) {
67 printk(BIOS_DEBUG
, "PCH discovery to be used is disabled.\n");
68 m_pmc_crashLog_present
= false;
69 m_pmc_crashLog_size
= 0;
72 desc_table_addr
= tmp_bar_addr
+ discovery_buf
.bits
.desc_tabl_offset
;
73 m_pmc_crashLog_size
= pmc_cl_gen_descriptor_table(desc_table_addr
,
75 printk(BIOS_DEBUG
, "PMC crashLog size in discovery mode : 0x%X\n",
79 if (discovery_buf
.bits
.dis
) {
80 printk(BIOS_DEBUG
, "PCH crashlog is disabled in legacy mode.\n");
81 m_pmc_crashLog_present
= false;
84 m_pmc_crashLog_size
= (discovery_buf
.bits
.size
!= 0) ?
85 (discovery_buf
.bits
.size
* sizeof(u32
)) : 0xC00;
86 printk(BIOS_DEBUG
, "PMC crashlog size in legacy mode = 0x%x\n",
89 m_pmc_crashLog_present
= true;
94 uintptr_t cl_get_cpu_bar_addr(void)
97 if (cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
== TEL_DVSEC_TBIR_BAR0
) {
98 base_addr
= pci_read_config32(SA_DEV_TMT
, PCI_BASE_ADDRESS_0
) &
99 ~PCI_BASE_ADDRESS_MEM_ATTR_MASK
;
100 } else if (cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
== TEL_DVSEC_TBIR_BAR1
) {
101 base_addr
= pci_read_config32(SA_DEV_TMT
, PCI_BASE_ADDRESS_1
) &
102 ~PCI_BASE_ADDRESS_MEM_ATTR_MASK
;
104 printk(BIOS_ERR
, "Invalid TEL_CFG_BAR value %d:\n",
105 cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
);
112 uintptr_t cl_get_cpu_tmp_bar(void)
114 return SPI_BASE_ADDRESS
;
117 bool cl_pmc_sram_has_mmio_access(void)
119 if (pci_read_config16(PCH_DEV_SRAM
, PCI_VENDOR_ID
) == 0xFFFF) {
120 printk(BIOS_ERR
, "PMC SSRAM PCI device is disabled.\n");
127 static bool cpu_cl_get_capability(tel_crashlog_devsc_cap_t
*cl_devsc_cap
)
129 cl_devsc_cap
->cap_data
.data
= pci_read_config32(SA_DEV_TMT
,
130 TEL_DVSEC_OFFSET
+ TEL_DVSEC_PCIE_CAP_ID
);
131 if (cl_devsc_cap
->cap_data
.fields
.pcie_cap_id
!= TELEMETRY_EXTENDED_CAP_ID
) {
132 printk(BIOS_DEBUG
, "Read ID for Telemetry: 0x%x differs from expected: 0x%x\n",
133 cl_devsc_cap
->cap_data
.fields
.pcie_cap_id
, TELEMETRY_EXTENDED_CAP_ID
);
137 /* walk through the entries until crashLog entry */
138 cl_devsc_cap
->devsc_data
.data_32
[1] = pci_read_config32(SA_DEV_TMT
, TEL_DVSEV_ID
);
140 while (cl_devsc_cap
->devsc_data
.fields
.devsc_id
!= CRASHLOG_DVSEC_ID
) {
141 if (cl_devsc_cap
->cap_data
.fields
.next_cap_offset
== 0
142 || cl_devsc_cap
->cap_data
.fields
.next_cap_offset
== 0xFFFF) {
143 printk(BIOS_DEBUG
, "Read invalid pcie_cap_id value: : 0x%x\n",
144 cl_devsc_cap
->cap_data
.fields
.pcie_cap_id
);
147 new_offset
= cl_devsc_cap
->cap_data
.fields
.next_cap_offset
;
148 cl_devsc_cap
->cap_data
.data
= pci_read_config32(SA_DEV_TMT
,
149 new_offset
+ TEL_DVSEC_PCIE_CAP_ID
);
150 cl_devsc_cap
->devsc_data
.data_32
[1] = pci_read_config32(SA_DEV_TMT
,
151 new_offset
+ TEL_DVSEV_ID
);
153 cpu_crash_version
= cl_devsc_cap
->devsc_data
.fields
.devsc_ver
;
155 cl_devsc_cap
->discovery_data
.data
= pci_read_config32(SA_DEV_TMT
, new_offset
156 + TEL_DVSEV_DISCOVERY_TABLE_OFFSET
);
162 static bool cpu_cl_gen_discovery_table(void)
164 uintptr_t bar_addr
= 0, disc_tab_addr
= 0;
165 bar_addr
= cl_get_cpu_bar_addr();
170 disc_tab_addr
= bar_addr
+
171 cpu_cl_devsc_cap
.discovery_data
.fields
.discovery_table_offset
;
172 memset(&cpu_cl_disc_tab
, 0, sizeof(cpu_crashlog_discovery_table_t
));
174 cpu_cl_disc_tab
.header
.data
= ((u64
)read32((u32
*)disc_tab_addr
) +
175 ((u64
)read32((u32
*)(disc_tab_addr
+ 4)) << 32));
177 cpu_cl_disc_tab
.cmd_mailbox
.data
= read32((u32
*)(disc_tab_addr
+ 8));
178 cpu_cl_disc_tab
.mailbox_data
= read32((u32
*)(disc_tab_addr
+ 12));
180 printk(BIOS_DEBUG
, "cpu_crashlog_discovery_table buffer count: 0x%x\n",
181 cpu_cl_disc_tab
.header
.fields
.count
);
183 if (cpu_cl_disc_tab
.header
.fields
.guid
!= CPU_CRASHLOG_DISC_TAB_GUID_VALID
) {
184 printk(BIOS_ERR
, "Invalid CPU crashlog discovery table GUID, expected = 0x%X ,"
185 "actual = 0x%X\n", CPU_CRASHLOG_DISC_TAB_GUID_VALID
,
186 cpu_cl_disc_tab
.header
.fields
.guid
);
191 for (int i
= 0; i
< cpu_cl_disc_tab
.header
.fields
.count
; i
++) {
192 cur_offset
= 16 + 8*i
;
193 cpu_cl_disc_tab
.buffers
[i
].data
= ((u64
)read32((u32
*)(disc_tab_addr
+
194 cur_offset
)) + ((u64
)read32((u32
*)
195 (disc_tab_addr
+ cur_offset
+ 4)) << 32));
196 printk(BIOS_DEBUG
, "cpu_crashlog_discovery_table buffer: 0x%x size:"
197 "0x%x offset: 0x%x\n", i
, cpu_cl_disc_tab
.buffers
[i
].fields
.size
,
198 cpu_cl_disc_tab
.buffers
[i
].fields
.offset
);
199 m_cpu_crashLog_size
+= cpu_cl_disc_tab
.buffers
[i
].fields
.size
* sizeof(u32
);
202 m_cpu_crashLog_present
= m_cpu_crashLog_size
> 0;
207 bool cpu_cl_discovery(void)
209 memset(&cpu_cl_devsc_cap
, 0, sizeof(tel_crashlog_devsc_cap_t
));
211 if (!cpu_cl_get_capability(&cpu_cl_devsc_cap
)) {
212 printk(BIOS_ERR
, "CPU crashlog capability not found.\n");
213 m_cpu_crashLog_support
= false;
217 m_cpu_crashLog_support
= true;
219 /* Program BAR address and enable command register memory space decoding */
220 u32 tmp_bar_addr
= PCH_PWRM_BASE_ADDRESS
;
221 printk(BIOS_DEBUG
, "tmp_bar_addr: 0x%X\n", tmp_bar_addr
);
223 if (cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
== TEL_DVSEC_TBIR_BAR0
) {
224 pci_write_config32(SA_DEV_TMT
, PCI_BASE_ADDRESS_0
, tmp_bar_addr
);
225 } else if (cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
== TEL_DVSEC_TBIR_BAR1
) {
226 pci_write_config32(SA_DEV_TMT
, PCI_BASE_ADDRESS_1
, tmp_bar_addr
);
228 printk(BIOS_DEBUG
, "invalid discovery data t_bir_q: 0x%x\n",
229 cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
);
232 pci_or_config16(SA_DEV_TMT
, PCI_COMMAND
, PCI_COMMAND_MEMORY
);
234 if (!cpu_cl_gen_discovery_table()) {
235 printk(BIOS_ERR
, "CPU crashlog discovery table not valid.\n");
236 m_cpu_crashLog_present
= false;
239 m_cpu_crashLog_present
= true;
244 void reset_discovery_buffers(void)
246 memset(&discovery_buf
, 0, sizeof(pmc_ipc_discovery_buf_t
));
247 memset(&descriptor_table
, 0, sizeof(pmc_crashlog_desc_table_t
));
248 memset(&cpu_cl_devsc_cap
, 0, sizeof(tel_crashlog_devsc_cap_t
));
252 int cl_get_total_data_size(void)
254 return m_pmc_crashLog_size
+ m_cpu_crashLog_size
;
258 pmc_ipc_discovery_buf_t
cl_get_pmc_discovery_buf(void)
260 return discovery_buf
;
264 pmc_crashlog_desc_table_t
cl_get_pmc_descriptor_table(void)
266 return descriptor_table
;
270 int cl_get_pmc_record_size(void)
272 return m_pmc_crashLog_size
;
276 int cl_get_cpu_record_size(void)
278 return m_cpu_crashLog_size
;
282 bool cl_cpu_data_present(void)
284 return m_cpu_crashLog_present
;
288 bool cl_pmc_data_present(void)
290 return m_pmc_crashLog_present
;
294 bool cpu_crashlog_support(void)
296 return m_cpu_crashLog_support
;
300 bool pmc_crashlog_support(void)
302 return m_pmc_crashLog_support
;
306 void update_new_pmc_crashlog_size(u32
*pmc_crash_size
)
308 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
;
318 void update_new_cpu_crashlog_size(u32
*cpu_crash_size
)
320 m_cpu_crashLog_size
= *cpu_crash_size
;