summaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/common/block/fast_spi/fast_spi_def.h6
-rw-r--r--src/soc/intel/common/block/fast_spi/fast_spi_flash.c37
2 files changed, 31 insertions, 12 deletions
diff --git a/src/soc/intel/common/block/fast_spi/fast_spi_def.h b/src/soc/intel/common/block/fast_spi/fast_spi_def.h
index cc1cdaa70c..72c359e6ee 100644
--- a/src/soc/intel/common/block/fast_spi/fast_spi_def.h
+++ b/src/soc/intel/common/block/fast_spi/fast_spi_def.h
@@ -3,6 +3,11 @@
#ifndef SOC_INTEL_COMMON_BLOCK_FAST_SPI_DEF_H
#define SOC_INTEL_COMMON_BLOCK_FAST_SPI_DEF_H
+/* From JEDEC SFDP JESD216F.02 */
+#define SFDP_HDR_SIG 0x00 /* 1st DWORD of SFDP header */
+#define SFDP_PARAM_DENSITY 0x04 /* 2nd DWORD of SFDP params */
+#define SFDP_SIGNATURE 0x50444653 /* Valid sig in 1st DWORD of SFDP header */
+
/* PCI configuration registers */
#define SPI_BIOS_DECODE_EN 0xd8
#define SPI_BIOS_DECODE_LOCK BIT(31)
@@ -153,7 +158,6 @@
#define SPIBAR_PTINX_HORD_SFDP (0 << 12)
#define SPIBAR_PTINX_HORD_PARAM (1 << 12)
#define SPIBAR_PTINX_HORD_JEDEC (2 << 12)
-#define SPIBAR_PTINX_IDX_MASK 0xffc
/* Register Offsets of BIOS Flash Program Registers */
#define SPIBAR_RESET_LOCK 0xf0
diff --git a/src/soc/intel/common/block/fast_spi/fast_spi_flash.c b/src/soc/intel/common/block/fast_spi/fast_spi_flash.c
index f896cd9a3a..e9cfc230a4 100644
--- a/src/soc/intel/common/block/fast_spi/fast_spi_flash.c
+++ b/src/soc/intel/common/block/fast_spi/fast_spi_flash.c
@@ -54,22 +54,22 @@ static void fast_spi_flash_ctrlr_reg_write(struct fast_spi_flash_ctx *ctx,
}
/*
- * The hardware datasheet is not clear on what HORD values actually do. It
- * seems that HORD_SFDP provides access to the first 8 bytes of the SFDP, which
- * is the signature and revision fields. HORD_JEDEC provides access to the
- * actual flash parameters, and is most likely what you want to use when
- * probing the flash from software.
+ * Via component field (bits 15-14) we can select either 1st or 2nd flash
+ * (in dual flash setups).
+ * Via HORD - Header or Data (bits 13-12) - we can select either:
+ * - SFDP Header
+ * - Param Table Header
+ * - Data (JEDEC params, including density)
+ *
* It's okay to rely on SFDP, since the SPI flash controller requires an SFDP
* 1.5 or newer compliant FAST_SPI flash chip.
* NOTE: Due to the register layout of the hardware, all accesses will be
* aligned to a 4 byte boundary.
*/
-static uint32_t fast_spi_flash_read_sfdp_param(struct fast_spi_flash_ctx *ctx,
- uint16_t sfdp_reg)
+static uint32_t fast_spi_flash_read_sfdp(struct fast_spi_flash_ctx *ctx,
+ uint32_t ptinx_reg)
{
- uint32_t ptinx_index = sfdp_reg & SPIBAR_PTINX_IDX_MASK;
- fast_spi_flash_ctrlr_reg_write(ctx, SPIBAR_PTINX,
- ptinx_index | SPIBAR_PTINX_HORD_JEDEC);
+ fast_spi_flash_ctrlr_reg_write(ctx, SPIBAR_PTINX, ptinx_reg);
return fast_spi_flash_ctrlr_reg_read(ctx, SPIBAR_PTDATA);
}
@@ -312,15 +312,30 @@ static int fast_spi_flash_probe(const struct spi_slave *dev,
{
BOILERPLATE_CREATE_CTX(ctx);
uint32_t flash_bits;
+ uint32_t ptinx_reg;
/*
* bytes = (bits + 1) / 8;
* But we need to do the addition in a way which doesn't overflow for
* 4 Gbit devices (flash_bits == 0xffffffff).
*/
- flash_bits = fast_spi_flash_read_sfdp_param(ctx, 0x04);
+ ptinx_reg = SPIBAR_PTINX_COMP_0 | SPIBAR_PTINX_HORD_JEDEC | SFDP_PARAM_DENSITY;
+ flash_bits = fast_spi_flash_read_sfdp(ctx, ptinx_reg);
flash->size = (flash_bits >> 3) + 1;
+ /*
+ * Now check if we have a second flash component.
+ * Check SFDP header for the SFDP signature. If valid, then 2nd component is present.
+ * Increase the flash size if 2nd component is found, analogically like the 1st
+ * component.
+ */
+ ptinx_reg = SPIBAR_PTINX_COMP_1 | SPIBAR_PTINX_HORD_SFDP | SFDP_HDR_SIG;
+ if (fast_spi_flash_read_sfdp(ctx, ptinx_reg) == SFDP_SIGNATURE) {
+ ptinx_reg = SPIBAR_PTINX_COMP_1 | SPIBAR_PTINX_HORD_JEDEC | SFDP_PARAM_DENSITY;
+ flash_bits = fast_spi_flash_read_sfdp(ctx, ptinx_reg);
+ flash->size += ((flash_bits >> 3) + 1);
+ }
+
memcpy(&flash->spi, dev, sizeof(*dev));
/* Can erase both 4 KiB and 64 KiB chunks. Declare the smaller size. */