blob: 93baf0442fcbc5001c2f3de1d4e68f00f1ab67bf [file] [log] [blame]
Francois Toguo15cbc3b2021-01-26 10:27:49 -08001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <console/console.h>
4#include <cbmem.h>
5#include <delay.h>
6#include <intelblocks/crashlog.h>
7#include <string.h>
8#include <soc/crashlog.h>
9#include <arch/bert_storage.h>
10#include <soc/iomap.h>
11#include <soc/pci_devs.h>
12
13/* global crashLog info */
14static bool m_pmc_crashLog_support;
15static bool m_pmc_crashLog_present;
16static bool m_cpu_crashLog_support;
17static bool m_cpu_crashLog_present;
18static u32 m_pmc_crashLog_size;
19static u32 m_cpu_crashLog_size;
20static u32 cpu_crash_version;
21static pmc_ipc_discovery_buf_t discovery_buf;
22static pmc_crashlog_desc_table_t descriptor_table;
23static tel_crashlog_devsc_cap_t cpu_cl_devsc_cap;
24static cpu_crashlog_discovery_table_t cpu_cl_disc_tab;
25
26u32 __weak cl_get_cpu_mb_int_addr(void)
27{
28 return CRASHLOG_MAILBOX_INTF_ADDRESS;
29}
30
31bool pmc_cl_discovery(void)
32{
33 u32 tmp_bar_addr = 0, desc_table_addr = 0;
34
35 const struct pmc_ipc_buffer *req = { 0 };
36 struct pmc_ipc_buffer *res = NULL;
37 uint32_t cmd_reg;
38 int r;
39
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);
44
45 r = pmc_send_ipc_cmd(cmd_reg, req, res);
46
47 if (r < 0) {
48 printk(BIOS_ERR, "pmc_send_ipc_cmd failed in %s\n", __func__);
49 return false;
50 }
51 discovery_buf.val_64_bits = ((u64)res->buf[1] << 32) | res->buf[0];
52
53
54 if (discovery_buf.bits.supported != 1) {
55 printk(BIOS_DEBUG, "PCH crashlog feature not supported.\n");
56 m_pmc_crashLog_support = false;
57 return false;
58 }
59 m_pmc_crashLog_support = true;
60
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);
65
66 if (discovery_buf.bits.discov_mechanism == 1) {
67 /* discovery mode */
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;
72 return false;
73 }
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,
76 &descriptor_table);
77 printk(BIOS_DEBUG, "PMC crashLog size in discovery mode : 0x%X\n",
78 m_pmc_crashLog_size);
79 } else {
80 /* legacy mode */
81 if (discovery_buf.bits.dis) {
82 printk(BIOS_DEBUG, "PCH crashlog is disabled in legacy mode.\n");
83 m_pmc_crashLog_present = false;
84 return false;
85 }
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",
89 m_pmc_crashLog_size);
90 }
91 m_pmc_crashLog_present = true;
92
93 return true;
94}
95
96u32 cl_get_cpu_bar_addr(void)
97{
98 u32 base_addr = 0;
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;
105 } else {
106 printk(BIOS_ERR, "Invalid TEL_CFG_BAR value %d:\n",
107 cpu_cl_devsc_cap.discovery_data.fields.t_bir_q);
108 }
109
110 return base_addr;
111}
112
113
114u32 cl_get_cpu_tmp_bar(void)
115{
116 return SPI_BASE_ADDRESS;
117}
118
119bool cl_pmc_sram_has_mmio_access(void)
120{
121
122 if (pci_read_config16(PCH_DEV_SRAM, PCI_VENDOR_ID) == 0xFFFF) {
123 printk(BIOS_ERR, "PMC SSRAM PCI device is disabled.\n");
124 return false;
125 }
126
127 return true;
128}
129
130static bool cpu_cl_get_capability(tel_crashlog_devsc_cap_t *cl_devsc_cap)
131{
132 cl_devsc_cap->cap_data.data = pci_read_config32(SA_DEV_TMT,
133 TEL_DVSEC_OFFSET + TEL_DVSEC_PCIE_CAP_ID);
134 if (cl_devsc_cap->cap_data.fields.pcie_cap_id != TELEMETRY_EXTENDED_CAP_ID) {
135 printk(BIOS_DEBUG, "Read ID for Telemetry: 0x%x differs from expected: 0x%x\n",
136 cl_devsc_cap->cap_data.fields.pcie_cap_id, TELEMETRY_EXTENDED_CAP_ID);
137 return false;
138 }
139
140 /* walk through the entries until crashLog entry */
141 cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(SA_DEV_TMT, TEL_DVSEV_ID);
142 int new_offset = 0;
143 while (cl_devsc_cap->devsc_data.fields.devsc_id != CRASHLOG_DVSEC_ID) {
144 if (cl_devsc_cap->cap_data.fields.next_cap_offset == 0
145 || cl_devsc_cap->cap_data.fields.next_cap_offset == 0xFFFF) {
146 printk(BIOS_DEBUG, "Read invalid pcie_cap_id value: : 0x%x\n",
147 cl_devsc_cap->cap_data.fields.pcie_cap_id);
148 return false;
149 }
150 new_offset = cl_devsc_cap->cap_data.fields.next_cap_offset;
151 cl_devsc_cap->cap_data.data = pci_read_config32(SA_DEV_TMT,
152 new_offset + TEL_DVSEC_PCIE_CAP_ID);
153 cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(SA_DEV_TMT,
154 new_offset + TEL_DVSEV_ID);
155 }
156 cpu_crash_version = cl_devsc_cap->devsc_data.fields.devsc_ver;
157
158 cl_devsc_cap->discovery_data.data = pci_read_config32(SA_DEV_TMT, new_offset
159 + TEL_DVSEV_DISCOVERY_TABLE_OFFSET);
160
161 return true;
162}
163
164
165static bool cpu_cl_gen_discovery_table(void)
166{
167 u32 bar_addr = 0, disc_tab_addr = 0;
168 bar_addr = cl_get_cpu_bar_addr();
169 disc_tab_addr = bar_addr +
170 cpu_cl_devsc_cap.discovery_data.fields.discovery_table_offset;
171 memset(&cpu_cl_disc_tab, 0, sizeof(cpu_crashlog_discovery_table_t));
172
173 cpu_cl_disc_tab.header.data = ((u64)read32((u32 *)disc_tab_addr) +
174 ((u64)read32((u32 *)(disc_tab_addr + 4)) << 32));
175
176 cpu_cl_disc_tab.cmd_mailbox.data = read32((u32 *)(disc_tab_addr + 8));
177 cpu_cl_disc_tab.mailbox_data = read32((u32 *)(disc_tab_addr + 12));
178
179 printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer count: 0x%x\n",
180 cpu_cl_disc_tab.header.fields.count);
181
182 if (cpu_cl_disc_tab.header.fields.guid != CPU_CRASHLOG_DISC_TAB_GUID_VALID) {
183 printk(BIOS_ERR, "Invalid CPU crashlog discovery table GUID, expected = 0x%X ,"
184 "actual = 0x%X\n", CPU_CRASHLOG_DISC_TAB_GUID_VALID,
185 cpu_cl_disc_tab.header.fields.guid);
186 return false;
187 }
188
189 int cur_offset = 0;
190 for (int i = 0; i < cpu_cl_disc_tab.header.fields.count ; i++) {
191 cur_offset = 16 + 8*i;
192 cpu_cl_disc_tab.buffers[i].data = ((u64)read32((u32 *)(disc_tab_addr +
193 cur_offset)) + ((u64)read32((u32 *)
194 (disc_tab_addr + cur_offset + 4)) << 32));
195 printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer: 0x%x size:"
196 "0x%x offset: 0x%x\n", i, cpu_cl_disc_tab.buffers[i].fields.size,
197 cpu_cl_disc_tab.buffers[i].fields.offset);
198 m_cpu_crashLog_size += cpu_cl_disc_tab.buffers[i].fields.size * sizeof(u32);
199 }
200
201 m_cpu_crashLog_present = m_cpu_crashLog_size > 0;
202
203 return true;
204}
205
206bool cpu_cl_discovery(void)
207{
208 memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
209
210 if (!cpu_cl_get_capability(&cpu_cl_devsc_cap)) {
211 printk(BIOS_ERR, "CPU crashlog capability not found.\n");
212 m_cpu_crashLog_support = false;
213 return false;
214 }
215
216 m_cpu_crashLog_support = true;
217
218 /* Program BAR address and enable command register memory space decoding */
219 u32 tmp_bar_addr = PCH_PWRM_BASE_ADDRESS;
220 printk(BIOS_DEBUG, "tmp_bar_addr: 0x%X\n", tmp_bar_addr);
221
222 if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR0) {
Francois Toguo4280b432021-02-25 15:04:56 -0800223 pci_write_config32(SA_DEV_TMT, PCI_BASE_ADDRESS_0, tmp_bar_addr);
Francois Toguo15cbc3b2021-01-26 10:27:49 -0800224 } else if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR1) {
Francois Toguo4280b432021-02-25 15:04:56 -0800225 pci_write_config32(SA_DEV_TMT, PCI_BASE_ADDRESS_1, tmp_bar_addr);
Francois Toguo15cbc3b2021-01-26 10:27:49 -0800226 } else {
227 printk(BIOS_DEBUG, "invalid discovery data t_bir_q: 0x%x\n",
228 cpu_cl_devsc_cap.discovery_data.fields.t_bir_q);
229 return false;
230 }
231 pci_or_config16(SA_DEV_TMT, PCI_COMMAND, PCI_COMMAND_MEMORY);
232
233 if (!cpu_cl_gen_discovery_table()) {
234 printk(BIOS_ERR, "CPU crashlog discovery table not valid.\n");
235 m_cpu_crashLog_present = false;
236 return false;
237 }
238 m_cpu_crashLog_present = true;
239
240 return true;
241}
242
243void reset_discovery_buffers(void)
244{
245 memset(&discovery_buf, 0, sizeof(pmc_ipc_discovery_buf_t));
246 memset(&descriptor_table, 0, sizeof(pmc_crashlog_desc_table_t));
247 memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
248}
249
250
251int cl_get_total_data_size(void)
252{
253 return m_pmc_crashLog_size + m_cpu_crashLog_size;
254}
255
256
257pmc_ipc_discovery_buf_t cl_get_pmc_discovery_buf(void)
258{
259 return discovery_buf;
260}
261
262
263pmc_crashlog_desc_table_t cl_get_pmc_descriptor_table(void)
264{
265 return descriptor_table;
266}
267
268
269int cl_get_pmc_record_size(void)
270{
271 return m_pmc_crashLog_size;
272}
273
274
275int cl_get_cpu_record_size(void)
276{
277 return m_cpu_crashLog_size;
278}
279
280
281bool cl_cpu_data_present(void)
282{
283 return m_cpu_crashLog_present;
284}
285
286
287bool cl_pmc_data_present(void)
288{
289 return m_pmc_crashLog_present;
290}
291
292
293bool cpu_crashlog_support(void)
294{
295 return m_cpu_crashLog_support;
296}
297
298
299bool pmc_crashlog_support(void)
300{
301 return m_pmc_crashLog_support;
302}
303
304
305void update_new_pmc_crashlog_size(u32 *pmc_crash_size)
306{
307 m_pmc_crashLog_size = *pmc_crash_size;
308}
309
310
311cpu_crashlog_discovery_table_t cl_get_cpu_discovery_table(void)
312{
313 return cpu_cl_disc_tab;
314}
315
316
317void update_new_cpu_crashlog_size(u32 *cpu_crash_size)
318{
319 m_cpu_crashLog_size = *cpu_crash_size;
320}