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 bool pmc_cl_discovery(void)
33 u32 tmp_bar_addr
= 0, desc_table_addr
= 0;
35 const struct pmc_ipc_buffer
*req
= { 0 };
36 struct pmc_ipc_buffer
*res
= NULL
;
40 cmd_reg
= pmc_make_ipc_cmd(PMC_IPC_CMD_CRASHLOG
,
41 PMC_IPC_CMD_ID_CRASHLOG_DISCOVERY
,
42 PMC_IPC_CMD_SIZE_SHIFT
);
43 printk(BIOS_DEBUG
, "cmd_reg from pmc_make_ipc_cmd %d\n", cmd_reg
);
45 r
= pmc_send_ipc_cmd(cmd_reg
, req
, res
);
48 printk(BIOS_ERR
, "pmc_send_ipc_cmd failed in %s\n", __func__
);
51 discovery_buf
.val_64_bits
= ((u64
)res
->buf
[1] << 32) | res
->buf
[0];
54 if (discovery_buf
.bits
.supported
!= 1) {
55 printk(BIOS_DEBUG
, "PCH crashlog feature not supported.\n");
56 m_pmc_crashLog_support
= false;
59 m_pmc_crashLog_support
= true;
61 /* Program BAR 0 and enable command register memory space decoding */
62 tmp_bar_addr
= SPI_BASE_ADDRESS
;
63 pci_write_config32(PCH_DEV_SRAM
, PCI_BASE_ADDRESS_0
, tmp_bar_addr
);
64 pci_or_config16(PCH_DEV_SRAM
, PCI_COMMAND
, PCI_COMMAND_MEMORY
);
66 if (discovery_buf
.bits
.discov_mechanism
== 1) {
68 if (discovery_buf
.bits
.base_offset
& BIT(31)) {
69 printk(BIOS_DEBUG
, "PCH discovery to be used is disabled.\n");
70 m_pmc_crashLog_present
= false;
71 m_pmc_crashLog_size
= 0;
74 desc_table_addr
= tmp_bar_addr
+ discovery_buf
.bits
.desc_tabl_offset
;
75 m_pmc_crashLog_size
= pmc_cl_gen_descriptor_table(desc_table_addr
,
77 printk(BIOS_DEBUG
, "PMC crashLog size in discovery mode : 0x%X\n",
81 if (discovery_buf
.bits
.dis
) {
82 printk(BIOS_DEBUG
, "PCH crashlog is disabled in legacy mode.\n");
83 m_pmc_crashLog_present
= false;
86 m_pmc_crashLog_size
= (discovery_buf
.bits
.size
!= 0) ?
87 (discovery_buf
.bits
.size
* sizeof(u32
)) : 0xC00;
88 printk(BIOS_DEBUG
, "PMC crashlog size in legacy mode = 0x%x\n",
91 m_pmc_crashLog_present
= true;
96 uintptr_t cl_get_cpu_bar_addr(void)
99 if (cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
== TEL_DVSEC_TBIR_BAR0
) {
100 base_addr
= pci_read_config32(SA_DEV_TMT
, PCI_BASE_ADDRESS_0
) &
101 ~PCI_BASE_ADDRESS_MEM_ATTR_MASK
;
102 } else if (cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
== TEL_DVSEC_TBIR_BAR1
) {
103 base_addr
= pci_read_config32(SA_DEV_TMT
, PCI_BASE_ADDRESS_1
) &
104 ~PCI_BASE_ADDRESS_MEM_ATTR_MASK
;
106 printk(BIOS_ERR
, "Invalid TEL_CFG_BAR value %d:\n",
107 cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
);
113 uintptr_t cl_get_cpu_tmp_bar(void)
115 return SPI_BASE_ADDRESS
;
118 bool cl_pmc_sram_has_mmio_access(void)
120 if (pci_read_config16(PCH_DEV_SRAM
, PCI_VENDOR_ID
) == 0xFFFF) {
121 printk(BIOS_ERR
, "PMC SSRAM PCI device is disabled.\n");
128 static bool cpu_cl_get_capability(tel_crashlog_devsc_cap_t
*cl_devsc_cap
)
130 cl_devsc_cap
->cap_data
.data
= pci_read_config32(SA_DEV_TMT
,
131 TEL_DVSEC_OFFSET
+ TEL_DVSEC_PCIE_CAP_ID
);
132 if (cl_devsc_cap
->cap_data
.fields
.pcie_cap_id
!= TELEMETRY_EXTENDED_CAP_ID
) {
133 printk(BIOS_DEBUG
, "Read ID for Telemetry: 0x%x differs from expected: 0x%x\n",
134 cl_devsc_cap
->cap_data
.fields
.pcie_cap_id
, TELEMETRY_EXTENDED_CAP_ID
);
138 /* walk through the entries until crashLog entry */
139 cl_devsc_cap
->devsc_data
.data_32
[1] = pci_read_config32(SA_DEV_TMT
, TEL_DVSEV_ID
);
141 while (cl_devsc_cap
->devsc_data
.fields
.devsc_id
!= CRASHLOG_DVSEC_ID
) {
142 if (cl_devsc_cap
->cap_data
.fields
.next_cap_offset
== 0
143 || cl_devsc_cap
->cap_data
.fields
.next_cap_offset
== 0xFFFF) {
144 printk(BIOS_DEBUG
, "Read invalid pcie_cap_id value: : 0x%x\n",
145 cl_devsc_cap
->cap_data
.fields
.pcie_cap_id
);
148 new_offset
= cl_devsc_cap
->cap_data
.fields
.next_cap_offset
;
149 cl_devsc_cap
->cap_data
.data
= pci_read_config32(SA_DEV_TMT
,
150 new_offset
+ TEL_DVSEC_PCIE_CAP_ID
);
151 cl_devsc_cap
->devsc_data
.data_32
[1] = pci_read_config32(SA_DEV_TMT
,
152 new_offset
+ TEL_DVSEV_ID
);
154 cpu_crash_version
= cl_devsc_cap
->devsc_data
.fields
.devsc_ver
;
156 cl_devsc_cap
->discovery_data
.data
= pci_read_config32(SA_DEV_TMT
, new_offset
157 + 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();
166 disc_tab_addr
= bar_addr
+
167 cpu_cl_devsc_cap
.discovery_data
.fields
.discovery_table_offset
;
168 memset(&cpu_cl_disc_tab
, 0, sizeof(cpu_crashlog_discovery_table_t
));
170 cpu_cl_disc_tab
.header
.data
= ((u64
)read32((u32
*)disc_tab_addr
) +
171 ((u64
)read32((u32
*)(disc_tab_addr
+ 4)) << 32));
173 cpu_cl_disc_tab
.cmd_mailbox
.data
= read32((u32
*)(disc_tab_addr
+ 8));
174 cpu_cl_disc_tab
.mailbox_data
= read32((u32
*)(disc_tab_addr
+ 12));
176 printk(BIOS_DEBUG
, "cpu_crashlog_discovery_table buffer count: 0x%x\n",
177 cpu_cl_disc_tab
.header
.fields
.count
);
179 if (cpu_cl_disc_tab
.header
.fields
.guid
!= CPU_CRASHLOG_DISC_TAB_GUID_VALID
) {
180 printk(BIOS_ERR
, "Invalid CPU crashlog discovery table GUID, expected = 0x%X ,"
181 "actual = 0x%X\n", CPU_CRASHLOG_DISC_TAB_GUID_VALID
,
182 cpu_cl_disc_tab
.header
.fields
.guid
);
187 for (int i
= 0; i
< cpu_cl_disc_tab
.header
.fields
.count
; i
++) {
188 cur_offset
= 16 + 8*i
;
189 cpu_cl_disc_tab
.buffers
[i
].data
= ((u64
)read32((u32
*)(disc_tab_addr
+
190 cur_offset
)) + ((u64
)read32((u32
*)
191 (disc_tab_addr
+ cur_offset
+ 4)) << 32));
192 printk(BIOS_DEBUG
, "cpu_crashlog_discovery_table buffer: 0x%x size:"
193 "0x%x offset: 0x%x\n", i
, cpu_cl_disc_tab
.buffers
[i
].fields
.size
,
194 cpu_cl_disc_tab
.buffers
[i
].fields
.offset
);
195 m_cpu_crashLog_size
+= cpu_cl_disc_tab
.buffers
[i
].fields
.size
* sizeof(u32
);
198 m_cpu_crashLog_present
= m_cpu_crashLog_size
> 0;
203 bool cpu_cl_discovery(void)
205 memset(&cpu_cl_devsc_cap
, 0, sizeof(tel_crashlog_devsc_cap_t
));
207 if (!cpu_cl_get_capability(&cpu_cl_devsc_cap
)) {
208 printk(BIOS_ERR
, "CPU crashlog capability not found.\n");
209 m_cpu_crashLog_support
= false;
213 m_cpu_crashLog_support
= true;
215 /* Program BAR address and enable command register memory space decoding */
216 u32 tmp_bar_addr
= PCH_PWRM_BASE_ADDRESS
;
217 printk(BIOS_DEBUG
, "tmp_bar_addr: 0x%X\n", tmp_bar_addr
);
219 if (cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
== TEL_DVSEC_TBIR_BAR0
) {
220 pci_write_config32(SA_DEV_TMT
, PCI_BASE_ADDRESS_0
, tmp_bar_addr
);
221 } else if (cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
== TEL_DVSEC_TBIR_BAR1
) {
222 pci_write_config32(SA_DEV_TMT
, PCI_BASE_ADDRESS_1
, tmp_bar_addr
);
224 printk(BIOS_DEBUG
, "invalid discovery data t_bir_q: 0x%x\n",
225 cpu_cl_devsc_cap
.discovery_data
.fields
.t_bir_q
);
228 pci_or_config16(SA_DEV_TMT
, PCI_COMMAND
, PCI_COMMAND_MEMORY
);
230 if (!cpu_cl_gen_discovery_table()) {
231 printk(BIOS_ERR
, "CPU crashlog discovery table not valid.\n");
232 m_cpu_crashLog_present
= false;
235 m_cpu_crashLog_present
= true;
240 void reset_discovery_buffers(void)
242 memset(&discovery_buf
, 0, sizeof(pmc_ipc_discovery_buf_t
));
243 memset(&descriptor_table
, 0, sizeof(pmc_crashlog_desc_table_t
));
244 memset(&cpu_cl_devsc_cap
, 0, sizeof(tel_crashlog_devsc_cap_t
));
248 int cl_get_total_data_size(void)
250 return m_pmc_crashLog_size
+ m_cpu_crashLog_size
;
253 pmc_ipc_discovery_buf_t
cl_get_pmc_discovery_buf(void)
255 return discovery_buf
;
258 pmc_crashlog_desc_table_t
cl_get_pmc_descriptor_table(void)
260 return descriptor_table
;
263 int cl_get_pmc_record_size(void)
265 return m_pmc_crashLog_size
;
268 int cl_get_cpu_record_size(void)
270 return m_cpu_crashLog_size
;
273 bool cl_cpu_data_present(void)
275 return m_cpu_crashLog_present
;
278 bool cl_pmc_data_present(void)
280 return m_pmc_crashLog_present
;
283 bool cpu_crashlog_support(void)
285 return m_cpu_crashLog_support
;
288 bool pmc_crashlog_support(void)
290 return m_pmc_crashLog_support
;
293 void update_new_pmc_crashlog_size(u32
*pmc_crash_size
)
295 m_pmc_crashLog_size
= *pmc_crash_size
;
298 cpu_crashlog_discovery_table_t
cl_get_cpu_discovery_table(void)
300 return cpu_cl_disc_tab
;
303 void update_new_cpu_crashlog_size(u32
*cpu_crash_size
)
305 m_cpu_crashLog_size
= *cpu_crash_size
;