summaryrefslogtreecommitdiff
path: root/src/soc/intel/common/block
diff options
context:
space:
mode:
authorSrinidhi N Kaushik <srinidhi.n.kaushik@intel.com>2020-11-25 01:07:06 -0800
committerFurquan Shaikh <furquan@google.com>2020-12-08 22:56:31 +0000
commit63afea54f41cb6054d8a3625238424e381a4fada (patch)
tree1845bc50f96b62c0d3342ab785e4c911df399a18 /src/soc/intel/common/block
parent493937e1d67e734c2ac45f92280f2c2c22a50b85 (diff)
soc/intel/common/dmi: Add DMI driver support
This change allows configuring the General Purpose Memory Range(GPMR) register in BIOS to set up the decoding in DMI. This driver provides the following functionality: 1. Add a helper function dmi_enable_gpmr which takes as input base, limit and destination ID to configure in general purpose memory range registers and then set the GPMR registers in the next available free GMPR and enable the decoding. 2. Add helper function get_available_gpmr which returns available free GPMR. 3. This helper function can be utilized by the fast SPI driver to configure the window for the extended BIOS region. BUG=b:171534504 Signed-off-by: Srinidhi N Kaushik <srinidhi.n.kaushik@intel.com> Change-Id: I34a894e295ecb98fbc4a81282361e851c436a403 Reviewed-on: https://review.coreboot.org/c/coreboot/+/47988 Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc/intel/common/block')
-rw-r--r--src/soc/intel/common/block/dmi/Kconfig5
-rw-r--r--src/soc/intel/common/block/dmi/Makefile.inc7
-rw-r--r--src/soc/intel/common/block/dmi/dmi.c81
-rw-r--r--src/soc/intel/common/block/include/intelblocks/dmi.h14
4 files changed, 107 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/dmi/Kconfig b/src/soc/intel/common/block/dmi/Kconfig
new file mode 100644
index 0000000000..2cc4646312
--- /dev/null
+++ b/src/soc/intel/common/block/dmi/Kconfig
@@ -0,0 +1,5 @@
+config SOC_INTEL_COMMON_BLOCK_DMI
+ bool
+ select SOC_INTEL_COMMON_BLOCK_PCR
+ help
+ Intel Processor common DMI support
diff --git a/src/soc/intel/common/block/dmi/Makefile.inc b/src/soc/intel/common/block/dmi/Makefile.inc
new file mode 100644
index 0000000000..7d013c96bc
--- /dev/null
+++ b/src/soc/intel/common/block/dmi/Makefile.inc
@@ -0,0 +1,7 @@
+ifeq ($(CONFIG_SOC_INTEL_COMMON_BLOCK_DMI), y)
+
+bootblock-y += dmi.c
+romstage-y += dmi.c
+ramstage-y += dmi.c
+
+endif
diff --git a/src/soc/intel/common/block/dmi/dmi.c b/src/soc/intel/common/block/dmi/dmi.c
new file mode 100644
index 0000000000..1a3a6023d6
--- /dev/null
+++ b/src/soc/intel/common/block/dmi/dmi.c
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <intelblocks/dmi.h>
+#include <intelblocks/pcr.h>
+#include <soc/pcr_ids.h>
+
+#define MAX_GPMR_REGS 3
+
+#define GPMR_OFFSET(x) (0x277c + (x) * 8)
+#define DMI_PCR_GPMR_LIMIT_MASK 0xffff0000
+#define DMI_PCR_GPMR_BASE_SHIFT 16
+#define DMI_PCR_GPMR_BASE_MASK 0xffff
+
+#define GPMR_DID_OFFSET(x) (0x2780 + (x) * 8)
+#define DMI_PCR_GPMR_EN BIT(31)
+
+/* GPMR Register read given offset */
+static uint32_t gpmr_read32(uint16_t offset)
+{
+ return pcr_read32(PID_DMI, offset);
+}
+
+/* GPMR Register write given offset and val */
+static void gpmr_write32(uint16_t offset, uint32_t val)
+{
+ return pcr_write32(PID_DMI, offset, val);
+}
+
+/* Check for available free gpmr */
+static int get_available_gpmr(void)
+{
+ int i;
+ uint32_t val;
+
+ for (i = 0; i < MAX_GPMR_REGS; i++) {
+ val = gpmr_read32(GPMR_DID_OFFSET(i));
+ if (!(val & DMI_PCR_GPMR_EN))
+ return i;
+ }
+ printk(BIOS_ERR, "%s: No available free gpmr found\n", __func__);
+ return CB_ERR;
+}
+
+/* Configure GPMR for the given base and size of extended BIOS Region */
+enum cb_err dmi_enable_gpmr(uint32_t base, uint32_t size, uint32_t dest_id)
+{
+ int gpmr_num;
+ uint32_t limit;
+
+ if (base & ~(DMI_PCR_GPMR_BASE_MASK << DMI_PCR_GPMR_BASE_SHIFT)) {
+ printk(BIOS_ERR, "base is not 64-KiB aligned!\n");
+ return CB_ERR;
+ }
+
+ limit = base + (size - 1);
+
+ if (limit < base) {
+ printk(BIOS_ERR, "Invalid limit: limit cannot be less than base!\n");
+ return CB_ERR;
+ }
+
+ if ((limit & ~DMI_PCR_GPMR_LIMIT_MASK) != 0xffff) {
+ printk(BIOS_ERR, "limit does not end on a 64-KiB boundary!\n");
+ return CB_ERR;
+ }
+
+ /* Get available free GPMR */
+ gpmr_num = get_available_gpmr();
+ if (gpmr_num == CB_ERR)
+ return CB_ERR;
+
+ /* Program Range for the given decode window */
+ gpmr_write32(GPMR_OFFSET(gpmr_num), (limit & DMI_PCR_GPMR_LIMIT_MASK) |
+ ((base >> DMI_PCR_GPMR_BASE_SHIFT) & DMI_PCR_GPMR_BASE_MASK));
+
+ /* Program source decode enable bit and the Destination ID */
+ gpmr_write32(GPMR_DID_OFFSET(gpmr_num), dest_id | DMI_PCR_GPMR_EN);
+
+ return CB_SUCCESS;
+}
diff --git a/src/soc/intel/common/block/include/intelblocks/dmi.h b/src/soc/intel/common/block/include/intelblocks/dmi.h
new file mode 100644
index 0000000000..b771b22022
--- /dev/null
+++ b/src/soc/intel/common/block/include/intelblocks/dmi.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef SOC_INTEL_COMMON_BLOCK_DMI_H
+#define SOC_INTEL_COMMON_BLOCK_DMI_H
+
+#include <types.h>
+
+/*
+ * Takes base, size and destination ID and configures the GPMR
+ * for accessing the region.
+ */
+enum cb_err dmi_enable_gpmr(uint32_t base, uint32_t size, uint32_t dest_id);
+
+#endif /* SOC_INTEL_COMMON_BLOCK_DMI_H */