summaryrefslogtreecommitdiff
path: root/src/soc/intel
diff options
context:
space:
mode:
authorJędrzej Ciupis <jciupis@google.com>2024-08-02 14:38:54 +0200
committerFelix Held <felix-coreboot@felixheld.de>2024-08-22 13:13:47 +0000
commit07dd73c9214b766762a89ffe51f27c77799293be (patch)
treefec99f9588327d4a6a0db2b400c75a6ea902d558 /src/soc/intel
parent94a65fa2c6c8922ef9883cc45656a19f994975e5 (diff)
soc/intel/jasperlake: Add CrashLog implementation for Intel JSL
Extend support for CrashLog to Intel Jasperlake based platforms. This commit is based on 15cbc3b5996ae64aff2e4741c4c3ec3d7f5cc1a7, originally reviewed on https://review.coreboot.org/c/coreboot/+/49943. BUG=b:354834461 TEST=CrashLog can be enabled in Kconfig for Jasperlake based platforms and can generate a BERT table, if enabled. Change-Id: Ia18a79d8de849d556b4b8fd0e6b43090311eb23f Signed-off-by: Jędrzej Ciupis <jciupis@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/83884 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Jakub Czapiga <czapiga@google.com>
Diffstat (limited to 'src/soc/intel')
-rw-r--r--src/soc/intel/jasperlake/Makefile.mk1
-rw-r--r--src/soc/intel/jasperlake/crashlog_lib.c306
-rw-r--r--src/soc/intel/jasperlake/include/soc/crashlog.h23
-rw-r--r--src/soc/intel/jasperlake/include/soc/pci_devs.h7
-rw-r--r--src/soc/intel/jasperlake/romstage/fsp_params.c6
5 files changed, 343 insertions, 0 deletions
diff --git a/src/soc/intel/jasperlake/Makefile.mk b/src/soc/intel/jasperlake/Makefile.mk
index 1377fff9e0..2763d71ae6 100644
--- a/src/soc/intel/jasperlake/Makefile.mk
+++ b/src/soc/intel/jasperlake/Makefile.mk
@@ -42,6 +42,7 @@ ramstage-y += reset.c
ramstage-y += systemagent.c
ramstage-y += sd.c
ramstage-y += xhci.c
+ramstage-$(CONFIG_SOC_INTEL_CRASHLOG) += crashlog_lib.c
smm-y += gpio.c
smm-y += p2sb.c
diff --git a/src/soc/intel/jasperlake/crashlog_lib.c b/src/soc/intel/jasperlake/crashlog_lib.c
new file mode 100644
index 0000000000..abe448f9e6
--- /dev/null
+++ b/src/soc/intel/jasperlake/crashlog_lib.c
@@ -0,0 +1,306 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/bert_storage.h>
+#include <console/console.h>
+#include <device/pci_ops.h>
+#include <intelblocks/crashlog.h>
+#include <intelblocks/pmc_ipc.h>
+#include <soc/crashlog.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include <string.h>
+
+/* global crashLog info */
+static bool m_pmc_crashLog_support;
+static bool m_pmc_crashLog_present;
+static bool m_cpu_crashLog_support;
+static bool m_cpu_crashLog_present;
+static u32 m_pmc_crashLog_size;
+static u32 m_cpu_crashLog_size;
+static u32 cpu_crash_version;
+static pmc_ipc_discovery_buf_t discovery_buf;
+static pmc_crashlog_desc_table_t descriptor_table;
+static tel_crashlog_devsc_cap_t cpu_cl_devsc_cap;
+static cpu_crashlog_discovery_table_t cpu_cl_disc_tab;
+
+uintptr_t __weak cl_get_cpu_mb_int_addr(void)
+{
+ return CRASHLOG_MAILBOX_INTF_ADDRESS;
+}
+
+bool pmc_cl_discovery(void)
+{
+ u32 tmp_bar_addr = 0, desc_table_addr = 0;
+
+ const struct pmc_ipc_buffer *req = { 0 };
+ struct pmc_ipc_buffer *res = NULL;
+ uint32_t cmd_reg;
+ int r;
+
+ cmd_reg = pmc_make_ipc_cmd(PMC_IPC_CMD_CRASHLOG,
+ PMC_IPC_CMD_ID_CRASHLOG_DISCOVERY,
+ PMC_IPC_CMD_SIZE_SHIFT);
+ printk(BIOS_DEBUG, "cmd_reg from pmc_make_ipc_cmd %d\n", cmd_reg);
+
+ r = pmc_send_ipc_cmd(cmd_reg, req, res);
+
+ if (r < 0) {
+ printk(BIOS_ERR, "pmc_send_ipc_cmd failed in %s\n", __func__);
+ return false;
+ }
+ discovery_buf.val_64_bits = ((u64)res->buf[1] << 32) | res->buf[0];
+
+
+ if (discovery_buf.bits.supported != 1) {
+ printk(BIOS_DEBUG, "PCH crashlog feature not supported.\n");
+ m_pmc_crashLog_support = false;
+ return false;
+ }
+ m_pmc_crashLog_support = true;
+
+ /* Program BAR 0 and enable command register memory space decoding */
+ tmp_bar_addr = SPI_BASE_ADDRESS;
+ pci_write_config32(PCH_DEV_SRAM, PCI_BASE_ADDRESS_0, tmp_bar_addr);
+ pci_or_config16(PCH_DEV_SRAM, PCI_COMMAND, PCI_COMMAND_MEMORY);
+
+ if (discovery_buf.bits.discov_mechanism == 1) {
+ /* discovery mode */
+ if (discovery_buf.bits.base_offset & BIT(31)) {
+ printk(BIOS_DEBUG, "PCH discovery to be used is disabled.\n");
+ m_pmc_crashLog_present = false;
+ m_pmc_crashLog_size = 0;
+ return false;
+ }
+ desc_table_addr = tmp_bar_addr + discovery_buf.bits.desc_tabl_offset;
+ m_pmc_crashLog_size = pmc_cl_gen_descriptor_table(desc_table_addr,
+ &descriptor_table);
+ printk(BIOS_DEBUG, "PMC crashLog size in discovery mode : 0x%X\n",
+ m_pmc_crashLog_size);
+ } else {
+ /* legacy mode */
+ if (discovery_buf.bits.dis) {
+ printk(BIOS_DEBUG, "PCH crashlog is disabled in legacy mode.\n");
+ m_pmc_crashLog_present = false;
+ return false;
+ }
+ m_pmc_crashLog_size = (discovery_buf.bits.size != 0) ?
+ (discovery_buf.bits.size * sizeof(u32)) : 0xC00;
+ printk(BIOS_DEBUG, "PMC crashlog size in legacy mode = 0x%x\n",
+ m_pmc_crashLog_size);
+ }
+ m_pmc_crashLog_present = true;
+
+ return true;
+}
+
+uintptr_t cl_get_cpu_bar_addr(void)
+{
+ u32 base_addr = 0;
+ if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR0) {
+ base_addr = pci_read_config32(SA_DEV_TMT, PCI_BASE_ADDRESS_0) &
+ ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+ } else if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR1) {
+ base_addr = pci_read_config32(SA_DEV_TMT, PCI_BASE_ADDRESS_1) &
+ ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+ } else {
+ printk(BIOS_ERR, "Invalid TEL_CFG_BAR value %d:\n",
+ cpu_cl_devsc_cap.discovery_data.fields.t_bir_q);
+ }
+
+ return base_addr;
+}
+
+uintptr_t cl_get_cpu_tmp_bar(void)
+{
+ return SPI_BASE_ADDRESS;
+}
+
+bool cl_pmc_sram_has_mmio_access(void)
+{
+ if (pci_read_config16(PCH_DEV_SRAM, PCI_VENDOR_ID) == 0xFFFF) {
+ printk(BIOS_ERR, "PMC SSRAM PCI device is disabled.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool cpu_cl_get_capability(tel_crashlog_devsc_cap_t *cl_devsc_cap)
+{
+ cl_devsc_cap->cap_data.data = pci_read_config32(SA_DEV_TMT,
+ TEL_DVSEC_OFFSET + TEL_DVSEC_PCIE_CAP_ID);
+ if (cl_devsc_cap->cap_data.fields.pcie_cap_id != TELEMETRY_EXTENDED_CAP_ID) {
+ printk(BIOS_DEBUG, "Read ID for Telemetry: 0x%x differs from expected: 0x%x\n",
+ cl_devsc_cap->cap_data.fields.pcie_cap_id, TELEMETRY_EXTENDED_CAP_ID);
+ return false;
+ }
+
+ /* walk through the entries until crashLog entry */
+ cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(SA_DEV_TMT, TEL_DVSEV_ID);
+ int new_offset = 0;
+ while (cl_devsc_cap->devsc_data.fields.devsc_id != CRASHLOG_DVSEC_ID) {
+ if (cl_devsc_cap->cap_data.fields.next_cap_offset == 0
+ || cl_devsc_cap->cap_data.fields.next_cap_offset == 0xFFFF) {
+ printk(BIOS_DEBUG, "Read invalid pcie_cap_id value: : 0x%x\n",
+ cl_devsc_cap->cap_data.fields.pcie_cap_id);
+ return false;
+ }
+ new_offset = cl_devsc_cap->cap_data.fields.next_cap_offset;
+ cl_devsc_cap->cap_data.data = pci_read_config32(SA_DEV_TMT,
+ new_offset + TEL_DVSEC_PCIE_CAP_ID);
+ cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(SA_DEV_TMT,
+ new_offset + TEL_DVSEV_ID);
+ }
+ cpu_crash_version = cl_devsc_cap->devsc_data.fields.devsc_ver;
+
+ cl_devsc_cap->discovery_data.data = pci_read_config32(SA_DEV_TMT, new_offset
+ + TEL_DVSEV_DISCOVERY_TABLE_OFFSET);
+
+ return true;
+}
+
+static bool cpu_cl_gen_discovery_table(void)
+{
+ uintptr_t bar_addr = 0, disc_tab_addr = 0;
+ bar_addr = cl_get_cpu_bar_addr();
+ disc_tab_addr = bar_addr +
+ cpu_cl_devsc_cap.discovery_data.fields.discovery_table_offset;
+ memset(&cpu_cl_disc_tab, 0, sizeof(cpu_crashlog_discovery_table_t));
+
+ cpu_cl_disc_tab.header.data = ((u64)read32((u32 *)disc_tab_addr) +
+ ((u64)read32((u32 *)(disc_tab_addr + 4)) << 32));
+
+ cpu_cl_disc_tab.cmd_mailbox.data = read32((u32 *)(disc_tab_addr + 8));
+ cpu_cl_disc_tab.mailbox_data = read32((u32 *)(disc_tab_addr + 12));
+
+ printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer count: 0x%x\n",
+ cpu_cl_disc_tab.header.fields.count);
+
+ if (cpu_cl_disc_tab.header.fields.guid != CPU_CRASHLOG_DISC_TAB_GUID_VALID) {
+ printk(BIOS_ERR, "Invalid CPU crashlog discovery table GUID, expected = 0x%X ,"
+ "actual = 0x%X\n", CPU_CRASHLOG_DISC_TAB_GUID_VALID,
+ cpu_cl_disc_tab.header.fields.guid);
+ return false;
+ }
+
+ int cur_offset = 0;
+ for (int i = 0; i < cpu_cl_disc_tab.header.fields.count ; i++) {
+ cur_offset = 16 + 8*i;
+ cpu_cl_disc_tab.buffers[i].data = ((u64)read32((u32 *)(disc_tab_addr +
+ cur_offset)) + ((u64)read32((u32 *)
+ (disc_tab_addr + cur_offset + 4)) << 32));
+ printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer: 0x%x size:"
+ "0x%x offset: 0x%x\n", i, cpu_cl_disc_tab.buffers[i].fields.size,
+ cpu_cl_disc_tab.buffers[i].fields.offset);
+ m_cpu_crashLog_size += cpu_cl_disc_tab.buffers[i].fields.size * sizeof(u32);
+ }
+
+ m_cpu_crashLog_present = m_cpu_crashLog_size > 0;
+
+ return true;
+}
+
+bool cpu_cl_discovery(void)
+{
+ memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
+
+ if (!cpu_cl_get_capability(&cpu_cl_devsc_cap)) {
+ printk(BIOS_ERR, "CPU crashlog capability not found.\n");
+ m_cpu_crashLog_support = false;
+ return false;
+ }
+
+ m_cpu_crashLog_support = true;
+
+ /* Program BAR address and enable command register memory space decoding */
+ u32 tmp_bar_addr = PCH_PWRM_BASE_ADDRESS;
+ printk(BIOS_DEBUG, "tmp_bar_addr: 0x%X\n", tmp_bar_addr);
+
+ if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR0) {
+ pci_write_config32(SA_DEV_TMT, PCI_BASE_ADDRESS_0, tmp_bar_addr);
+ } else if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR1) {
+ pci_write_config32(SA_DEV_TMT, PCI_BASE_ADDRESS_1, tmp_bar_addr);
+ } else {
+ printk(BIOS_DEBUG, "invalid discovery data t_bir_q: 0x%x\n",
+ cpu_cl_devsc_cap.discovery_data.fields.t_bir_q);
+ return false;
+ }
+ pci_or_config16(SA_DEV_TMT, PCI_COMMAND, PCI_COMMAND_MEMORY);
+
+ if (!cpu_cl_gen_discovery_table()) {
+ printk(BIOS_ERR, "CPU crashlog discovery table not valid.\n");
+ m_cpu_crashLog_present = false;
+ return false;
+ }
+ m_cpu_crashLog_present = true;
+
+ return true;
+}
+
+void reset_discovery_buffers(void)
+{
+ memset(&discovery_buf, 0, sizeof(pmc_ipc_discovery_buf_t));
+ memset(&descriptor_table, 0, sizeof(pmc_crashlog_desc_table_t));
+ memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
+}
+
+
+int cl_get_total_data_size(void)
+{
+ return m_pmc_crashLog_size + m_cpu_crashLog_size;
+}
+
+pmc_ipc_discovery_buf_t cl_get_pmc_discovery_buf(void)
+{
+ return discovery_buf;
+}
+
+pmc_crashlog_desc_table_t cl_get_pmc_descriptor_table(void)
+{
+ return descriptor_table;
+}
+
+int cl_get_pmc_record_size(void)
+{
+ return m_pmc_crashLog_size;
+}
+
+int cl_get_cpu_record_size(void)
+{
+ return m_cpu_crashLog_size;
+}
+
+bool cl_cpu_data_present(void)
+{
+ return m_cpu_crashLog_present;
+}
+
+bool cl_pmc_data_present(void)
+{
+ return m_pmc_crashLog_present;
+}
+
+bool cpu_crashlog_support(void)
+{
+ return m_cpu_crashLog_support;
+}
+
+bool pmc_crashlog_support(void)
+{
+ return m_pmc_crashLog_support;
+}
+
+void update_new_pmc_crashlog_size(u32 *pmc_crash_size)
+{
+ m_pmc_crashLog_size = *pmc_crash_size;
+}
+
+cpu_crashlog_discovery_table_t cl_get_cpu_discovery_table(void)
+{
+ return cpu_cl_disc_tab;
+}
+
+void update_new_cpu_crashlog_size(u32 *cpu_crash_size)
+{
+ m_cpu_crashLog_size = *cpu_crash_size;
+}
diff --git a/src/soc/intel/jasperlake/include/soc/crashlog.h b/src/soc/intel/jasperlake/include/soc/crashlog.h
new file mode 100644
index 0000000000..e8ba0aaa10
--- /dev/null
+++ b/src/soc/intel/jasperlake/include/soc/crashlog.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _SOC_JASPERLAKE_BLOCK_CRASHLOG_LIB_H_
+#define _SOC_JASPERLAKE_BLOCK_CRASHLOG_LIB_H_
+
+#include <types.h>
+
+/* DVSEC capability Registers */
+#define TEL_DVSEC_OFFSET 0x100
+#define TEL_DVSEC_PCIE_CAP_ID 0x0
+#define TEL_DVSEC_NEXT_CAP 0x2
+#define TEL_DVSEV_ID 0x8
+#define TEL_DVSEV_DISCOVERY_TABLE_OFFSET 0xC
+#define TELEMETRY_EXTENDED_CAP_ID 0x23
+#define CRASHLOG_DVSEC_ID 0x04
+#define TEL_DVSEC_TBIR_BAR0 0
+#define TEL_DVSEC_TBIR_BAR1 1
+
+/* CPU CrashLog MMIO Registers */
+#define CRASHLOG_MAILBOX_INTF_ADDRESS 0x6038
+#define CRASHLOG_POINTER_SIZE_FIELD_OFFSET 0x04
+
+#endif /* _SOC_JASPERLAKE_BLOCK_CRASHLOG_LIB_H_ */
diff --git a/src/soc/intel/jasperlake/include/soc/pci_devs.h b/src/soc/intel/jasperlake/include/soc/pci_devs.h
index e3276458bf..b8cc067a36 100644
--- a/src/soc/intel/jasperlake/include/soc/pci_devs.h
+++ b/src/soc/intel/jasperlake/include/soc/pci_devs.h
@@ -5,12 +5,15 @@
#include <device/pci_def.h>
+#define _SA_DEVFN(slot, func) PCI_DEVFN(SA_DEV_SLOT_ ## slot, func)
#define _PCH_DEVFN(slot, func) PCI_DEVFN(PCH_DEV_SLOT_ ## slot, func)
#if !defined(__SIMPLE_DEVICE__)
#include <device/device.h>
+#define _SA_DEV(slot, func) pcidev_path_on_root(_SA_DEVFN(slot, func))
#define _PCH_DEV(slot, func) pcidev_path_on_root_debug(_PCH_DEVFN(slot, func), __func__)
#else
+#define _SA_DEV(slot, func) PCI_DEV(0, SA_DEV_SLOT_ ## slot, func)
#define _PCH_DEV(slot, func) PCI_DEV(0, PCH_DEV_SLOT_ ## slot, func)
#endif
@@ -48,6 +51,10 @@
#define SA_DEVFN_GNA PCI_DEVFN(SA_DEV_SLOT_GNA, 0)
#define SA_DEV_GNA PCI_DEV(0, SA_DEV_SLOT_GNA, 0)
+#define SA_DEV_SLOT_TMT 0x14
+#define SA_DEVFN_TMT _SA_DEVFN(TMT, 2)
+#define SA_DEV_TMT _SA_DEV(TMT, 2)
+
/* PCH Devices */
#define PCH_DEV_SLOT_SIO0 0x10
#define PCH_DEVFN_CNVI_BT _PCH_DEVFN(SIO0, 2)
diff --git a/src/soc/intel/jasperlake/romstage/fsp_params.c b/src/soc/intel/jasperlake/romstage/fsp_params.c
index 0299860931..a5750279db 100644
--- a/src/soc/intel/jasperlake/romstage/fsp_params.c
+++ b/src/soc/intel/jasperlake/romstage/fsp_params.c
@@ -142,6 +142,12 @@ static void soc_memory_init_params(FSP_M_CONFIG *m_cfg,
* and rely on GPIO settings programmed before moved to FSP.
*/
m_cfg->GpioOverride = 1;
+
+ /* crashLog config */
+ if (CONFIG(SOC_INTEL_CRASHLOG)) {
+ m_cfg->CpuCrashLogDevice = 1;
+ m_cfg->CpuCrashLogEnable = 1;
+ }
}
void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)