diff options
author | Michał Żygowski <michal.zygowski@3mdeb.com> | 2024-02-16 19:54:39 +0100 |
---|---|---|
committer | Nico Huber <nico.h@gmx.de> | 2024-04-04 21:06:26 +0000 |
commit | c72a65dccde199ef3e9b7ab51db86791b58e7b43 (patch) | |
tree | cb65a03361339893420651c291e8ff4c4ed4e3a7 /src/soc/intel/common | |
parent | 722565671618baeec9690a70a94c75467cb44117 (diff) |
soc/intel/common/block/fast_spi: probe for 2nd flash component
Fast SPI code assumes only one SPI flash is present. The SPI flash
driver for older southbridges is able to detect multichip. See the
spi_is_multichip() in src/southbridge/intel/common/spi.c.
Some boards (e.g. Lenovo ThinkCentre M920 Tiny) still come with two
chips populated instead of one. With this change, both chips are probed,
and the correct total size is calculated. Otherwise, only the first one
was probed, which resulted in an error such as:
SF size 0x1000000 does not correspond to CONFIG_ROM_SIZE 0x1800000!!
Change-Id: I8d7449f9e1470dc234fe5ba5217d3ce4c142b49c
Signed-off-by: Michał Żygowski <michal.zygowski@3mdeb.com>
Signed-off-by: Maciej Pijanowski <maciej.pijanowski@3mdeb.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/80608
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Diffstat (limited to 'src/soc/intel/common')
-rw-r--r-- | src/soc/intel/common/block/fast_spi/fast_spi_def.h | 6 | ||||
-rw-r--r-- | src/soc/intel/common/block/fast_spi/fast_spi_flash.c | 37 |
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. */ |