summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/common/block/include/intelblocks/spi.h11
-rw-r--r--src/soc/intel/common/block/spi/spi.c81
2 files changed, 92 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/include/intelblocks/spi.h b/src/soc/intel/common/block/include/intelblocks/spi.h
index 38c9a57eb5..4ab4105787 100644
--- a/src/soc/intel/common/block/include/intelblocks/spi.h
+++ b/src/soc/intel/common/block/include/intelblocks/spi.h
@@ -3,6 +3,17 @@
#ifndef SOC_INTEL_COMMON_BLOCK_SPI_H
#define SOC_INTEL_COMMON_BLOCK_SPI_H
+#include <types.h>
+
+/*
+ * Check if write protection for CSE RO is enabled or not.
+ * Returns true if write protection for CSE RO is enabled, false otherwise.
+ */
+bool is_spi_wp_cse_ro_en(void);
+
+/* Gets CSE RO's write protected area's base address and limit */
+void spi_get_wp_cse_ro_range(uint32_t *base, uint32_t *limit);
+
/*
* SoC overrides
*
diff --git a/src/soc/intel/common/block/spi/spi.c b/src/soc/intel/common/block/spi/spi.c
index 50e1beaf1e..0716e1ae90 100644
--- a/src/soc/intel/common/block/spi/spi.c
+++ b/src/soc/intel/common/block/spi/spi.c
@@ -1,8 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#define __SIMPLE_DEVICE__
+
#include <device/device.h>
+#include <device/mmio.h>
#include <device/pci.h>
#include <device/pci_ids.h>
+#include <device/pci_ops.h>
#include <device/spi.h>
#include <intelblocks/fast_spi.h>
#include <intelblocks/gspi.h>
@@ -20,6 +24,83 @@ const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);
+#define MMIO_BIOS_GPR0 0x98
+
+union spi_bios_gpr0 {
+ struct {
+ /* Specified write protection is enabled */
+ /*
+ * This field corresponds to flash address bits 26:12
+ * and specifies the lower limit of protected range.
+ */
+ uint32_t protect_range_base:15;
+
+ /* Specifies read protection is enabled */
+ uint32_t read_protect_en:1;
+
+ /*
+ * This field corresponds to flash address bits 26:12
+ * and specifies the upper limit of the protected range
+ */
+ uint32_t protect_range_limit:15;
+
+ uint32_t write_protect_en:1;
+ } __packed fields;
+
+ uint32_t data;
+};
+
+/* Read SPI BAR 0 from PCI configuration space */
+static uintptr_t get_spi_bar(pci_devfn_t dev)
+{
+ uintptr_t bar;
+
+ bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
+ assert(bar != 0);
+ /*
+ * Bits 31-12 are the base address as per EDS for SPI,
+ * Don't care about 0-11 bit
+ */
+ return bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+}
+
+static uint32_t spi_read_bar(pci_devfn_t dev, uint32_t offset)
+{
+ return read32p(get_spi_bar(dev) + offset);
+}
+
+static uint32_t spi_read_bios_gpr0(void)
+{
+ return spi_read_bar(PCH_DEV_SPI, MMIO_BIOS_GPR0);
+}
+
+static uint32_t spi_get_wp_cse_ro_start_offset(union spi_bios_gpr0 bios_gpr0)
+{
+ return bios_gpr0.fields.protect_range_base << 12;
+}
+
+static uint32_t spi_get_wp_cse_ro_limit(union spi_bios_gpr0 bios_gpr0)
+{
+ return bios_gpr0.fields.protect_range_limit << 12 | 0xfff;
+}
+
+bool is_spi_wp_cse_ro_en(void)
+{
+ union spi_bios_gpr0 bios_gpr0;
+
+ bios_gpr0.data = spi_read_bios_gpr0();
+ return !!bios_gpr0.fields.write_protect_en;
+}
+
+void spi_get_wp_cse_ro_range(uint32_t *base, uint32_t *limit)
+{
+ union spi_bios_gpr0 bios_gpr0;
+
+ bios_gpr0.data = spi_read_bios_gpr0();
+ *base = spi_get_wp_cse_ro_start_offset(bios_gpr0);
+ *limit = spi_get_wp_cse_ro_limit(bios_gpr0);
+}
+
static int spi_dev_to_bus(struct device *dev)
{
return spi_soc_devfn_to_bus(dev->path.pci.devfn);