blob: 7bfa70baeb4ea238cbff7afd7588d730adc40758 [file] [log] [blame]
Francois Toguocea4f922021-04-16 21:20:39 -07001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <console/console.h>
Francois Toguocea4f922021-04-16 21:20:39 -07004#include <intelblocks/crashlog.h>
5#include <string.h>
6#include <soc/crashlog.h>
7#include <arch/bert_storage.h>
8#include <soc/iomap.h>
9#include <soc/pci_devs.h>
10
11/* global crashLog info */
12static bool m_pmc_crashLog_support;
13static bool m_pmc_crashLog_present;
14static bool m_cpu_crashLog_support;
15static bool m_cpu_crashLog_present;
16static u32 m_pmc_crashLog_size;
17static u32 m_cpu_crashLog_size;
18static u32 cpu_crash_version;
19static pmc_ipc_discovery_buf_t discovery_buf;
20static pmc_crashlog_desc_table_t descriptor_table;
21static tel_crashlog_devsc_cap_t cpu_cl_devsc_cap;
22static cpu_crashlog_discovery_table_t cpu_cl_disc_tab;
23
24u32 __weak cl_get_cpu_mb_int_addr(void)
25{
26 return CRASHLOG_MAILBOX_INTF_ADDRESS;
27}
28
29bool pmc_cl_discovery(void)
30{
31 u32 tmp_bar_addr = 0, desc_table_addr = 0;
32
John Zhao270e2552021-07-06 10:28:18 -070033 const struct pmc_ipc_buffer req = { 0 };
34 struct pmc_ipc_buffer res;
Francois Toguocea4f922021-04-16 21:20:39 -070035 uint32_t cmd_reg;
36 int r;
37
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);
42
John Zhao270e2552021-07-06 10:28:18 -070043 r = pmc_send_ipc_cmd(cmd_reg, &req, &res);
Francois Toguocea4f922021-04-16 21:20:39 -070044
45 if (r < 0) {
46 printk(BIOS_ERR, "pmc_send_ipc_cmd failed in %s\n", __func__);
47 return false;
48 }
John Zhao270e2552021-07-06 10:28:18 -070049 discovery_buf.val_64_bits = ((u64)res.buf[1] << 32) | res.buf[0];
Francois Toguocea4f922021-04-16 21:20:39 -070050
51
52 if (discovery_buf.bits.supported != 1) {
53 printk(BIOS_INFO, "PCH crashlog feature not supported.\n");
54 m_pmc_crashLog_support = false;
55 return false;
56 }
57 m_pmc_crashLog_support = true;
58
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);
63
64 if (discovery_buf.bits.discov_mechanism == 1) {
65 /* discovery mode */
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;
70 return false;
71 }
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,
74 &descriptor_table);
75 printk(BIOS_DEBUG, "PMC CrashLog size in discovery mode: 0x%X\n",
76 m_pmc_crashLog_size);
77 } else {
78 /* legacy mode */
79 if (discovery_buf.bits.dis) {
80 printk(BIOS_DEBUG, "PCH crashlog is disabled in legacy mode.\n");
81 m_pmc_crashLog_present = false;
82 return false;
83 }
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",
87 m_pmc_crashLog_size);
88 }
89 m_pmc_crashLog_present = true;
90
91 return true;
92}
93
94u32 cl_get_cpu_bar_addr(void)
95{
96 u32 base_addr = 0;
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;
103 } else {
104 printk(BIOS_ERR, "Invalid TEL_CFG_BAR value %d, discovery failure expected.\n",
105 cpu_cl_devsc_cap.discovery_data.fields.t_bir_q);
106 }
107
108 return base_addr;
109}
110
111
112u32 cl_get_cpu_tmp_bar(void)
113{
114 return SPI_BASE_ADDRESS;
115}
116
117bool cl_pmc_sram_has_mmio_access(void)
118{
119 if (pci_read_config16(PCH_DEV_SRAM, PCI_VENDOR_ID) == 0xFFFF) {
120 printk(BIOS_ERR, "PMC SSRAM PCI device disabled. Can be enabled in device tree.\n");
121 return false;
122 }
123
124 return true;
125}
126
127static bool cpu_cl_get_capability(tel_crashlog_devsc_cap_t *cl_devsc_cap)
128{
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);
134 return false;
135 }
136
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);
139 int new_offset = 0;
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);
145 return false;
146 }
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);
152 }
153 cpu_crash_version = cl_devsc_cap->devsc_data.fields.devsc_ver;
154
155 cl_devsc_cap->discovery_data.data = pci_read_config32(SA_DEV_TMT, new_offset
156 + TEL_DVSEV_DISCOVERY_TABLE_OFFSET);
157
158 return true;
159}
160
161
162static bool cpu_cl_gen_discovery_table(void)
163{
164 u32 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));
169
170 printk(BIOS_DEBUG, "cpu discovery table offset: 0x%x\n",
171 cpu_cl_devsc_cap.discovery_data.fields.discovery_table_offset);
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 int cur_offset = 0;
183 for (int i = 0; i < cpu_cl_disc_tab.header.fields.count; i++) {
184 cur_offset = 16 + 8*i;
185 cpu_cl_disc_tab.buffers[i].data = ((u64)read32((u32 *)(disc_tab_addr +
186 cur_offset)) + ((u64)read32((u32 *)
187 (disc_tab_addr + cur_offset + 4)) << 32));
188 printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer: 0x%x size: "
189 "0x%x offset: 0x%x\n", i, cpu_cl_disc_tab.buffers[i].fields.size,
190 cpu_cl_disc_tab.buffers[i].fields.offset);
191 m_cpu_crashLog_size += cpu_cl_disc_tab.buffers[i].fields.size * sizeof(u32);
192 }
193
194 m_cpu_crashLog_present = m_cpu_crashLog_size > 0;
195
196 return true;
197}
198
199bool cpu_cl_discovery(void)
200{
201 memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
202
203 if (!cpu_cl_get_capability(&cpu_cl_devsc_cap)) {
204 printk(BIOS_ERR, "CPU crashlog capability not found.\n");
205 m_cpu_crashLog_support = false;
206 return false;
207 }
208
209 m_cpu_crashLog_support = true;
210
Kane Chen3c011232021-11-16 09:07:16 +0800211 const struct resource *res = find_resource(SA_DEV_TMT, PCI_BASE_ADDRESS_0);
212 printk(BIOS_DEBUG, "cpu crashlog bar addr: 0x%llX\n", res->base);
Francois Toguocea4f922021-04-16 21:20:39 -0700213
214 if (!cpu_cl_gen_discovery_table()) {
215 printk(BIOS_ERR, "CPU crashlog discovery table not valid.\n");
216 m_cpu_crashLog_present = false;
217 return false;
218 }
Francois Toguocea4f922021-04-16 21:20:39 -0700219
220 return true;
221}
222
223void reset_discovery_buffers(void)
224{
225 memset(&discovery_buf, 0, sizeof(pmc_ipc_discovery_buf_t));
226 memset(&descriptor_table, 0, sizeof(pmc_crashlog_desc_table_t));
227 memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
228}
229
230int cl_get_total_data_size(void)
231{
232 return m_pmc_crashLog_size + m_cpu_crashLog_size;
233}
234
235pmc_ipc_discovery_buf_t cl_get_pmc_discovery_buf(void)
236{
237 return discovery_buf;
238}
239
240pmc_crashlog_desc_table_t cl_get_pmc_descriptor_table(void)
241{
242 return descriptor_table;
243}
244
245int cl_get_pmc_record_size(void)
246{
247 return m_pmc_crashLog_size;
248}
249
250int cl_get_cpu_record_size(void)
251{
252 return m_cpu_crashLog_size;
253}
254
255bool cl_cpu_data_present(void)
256{
257 return m_cpu_crashLog_present;
258}
259
260bool cl_pmc_data_present(void)
261{
262 return m_pmc_crashLog_present;
263}
264
265bool cpu_crashlog_support(void)
266{
267 return m_cpu_crashLog_support;
268}
269
270bool pmc_crashlog_support(void)
271{
272 return m_pmc_crashLog_support;
273}
274
275void update_new_pmc_crashlog_size(u32 *pmc_crash_size)
276{
277 m_pmc_crashLog_size = *pmc_crash_size;
278}
279
280cpu_crashlog_discovery_table_t cl_get_cpu_discovery_table(void)
281{
282 return cpu_cl_disc_tab;
283}
284
285void update_new_cpu_crashlog_size(u32 *cpu_crash_size)
286{
287 m_cpu_crashLog_size = *cpu_crash_size;
288}