diff options
-rw-r--r-- | src/drivers/spi/spi_flash.c | 81 | ||||
-rw-r--r-- | src/include/spi-generic.h | 4 | ||||
-rw-r--r-- | src/include/spi_flash.h | 7 | ||||
-rw-r--r-- | src/soc/intel/apollolake/spi.c | 4 | ||||
-rw-r--r-- | src/soc/intel/skylake/flash_controller.c | 4 | ||||
-rw-r--r-- | src/soc/mediatek/mt8173/flash_controller.c | 2 | ||||
-rw-r--r-- | src/soc/mediatek/mt8173/include/soc/flash_controller.h | 1 | ||||
-rw-r--r-- | src/soc/mediatek/mt8173/spi.c | 2 | ||||
-rw-r--r-- | src/southbridge/intel/common/spi.c | 13 |
9 files changed, 65 insertions, 53 deletions
diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c index baa1f1aeab..b2fdab9f2d 100644 --- a/src/drivers/spi/spi_flash.c +++ b/src/drivers/spi/spi_flash.c @@ -296,46 +296,39 @@ static struct { }; #define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN) +struct spi_flash * +__attribute__((weak)) spi_flash_programmer_probe(struct spi_slave *spi, + int force) +{ + /* Default weak implementation. Do nothing. */ + return NULL; +} -/* Public API implementations. */ -struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs) +static struct spi_flash *__spi_flash_probe(struct spi_slave *spi) { - struct spi_slave *spi; - struct spi_flash *flash = NULL; int ret, i, shift; u8 idcode[IDCODE_LEN], *idp; - - spi = spi_setup_slave(bus, cs); - if (!spi) { - printk(BIOS_WARNING, "SF: Failed to set up slave\n"); - return NULL; - } - - if (spi->force_programmer_specific && spi->programmer_specific_probe) { - flash = spi->programmer_specific_probe (spi); - if (!flash) - goto err_read_id; - goto flash_detected; - } + struct spi_flash *flash = NULL; /* Read the ID codes */ ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); if (ret) - goto err_read_id; + return NULL; -#if CONFIG_DEBUG_SPI_FLASH - printk(BIOS_SPEW, "SF: Got idcode: "); - for (i = 0; i < sizeof(idcode); i++) - printk(BIOS_SPEW, "%02x ", idcode[i]); - printk(BIOS_SPEW, "\n"); -#endif + if (IS_ENABLED(CONFIG_DEBUG_SPI_FLASH)) { + printk(BIOS_SPEW, "SF: Got idcode: "); + for (i = 0; i < sizeof(idcode); i++) + printk(BIOS_SPEW, "%02x ", idcode[i]); + printk(BIOS_SPEW, "\n"); + } /* count the number of continuation bytes */ - for (shift = 0, idp = idcode; - shift < IDCODE_CONT_LEN && *idp == 0x7f; + for (shift = 0, idp = idcode; shift < IDCODE_CONT_LEN && *idp == 0x7f; ++shift, ++idp) continue; + printk(BIOS_INFO, "Manufacturer: %02x\n", *idp); + /* search the table for matches in shift and id */ for (i = 0; i < ARRAY_SIZE(flashes); ++i) if (flashes[i].shift == shift && flashes[i].idcode == *idp) { @@ -345,15 +338,37 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs) break; } - if (!flash && spi->programmer_specific_probe) { - flash = spi->programmer_specific_probe (spi); + return flash; +} + +struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs) +{ + struct spi_slave *spi; + struct spi_flash *flash; + + spi = spi_setup_slave(bus, cs); + if (!spi) { + printk(BIOS_WARNING, "SF: Failed to set up slave\n"); + return NULL; } + + /* Try special programmer probe if any (without force). */ + flash = spi_flash_programmer_probe(spi, 0); + + /* If flash is not found, try generic spi flash probe. */ + if (!flash) + flash = __spi_flash_probe(spi); + + /* If flash is not yet found, force special programmer probe if any. */ + if (!flash) + flash = spi_flash_programmer_probe(spi, 1); + + /* Give up -- nothing more to try if flash is not found. */ if (!flash) { - printk(BIOS_WARNING, "SF: Unsupported manufacturer %02x\n", *idp); - goto err_manufacturer_probe; + printk(BIOS_WARNING, "SF: Unsupported manufacturer!\n"); + return NULL; } -flash_detected: printk(BIOS_INFO, "SF: Detected %s with sector size 0x%x, total 0x%x\n", flash->name, flash->sector_size, flash->size); @@ -366,10 +381,6 @@ flash_detected: spi_flash_dev = flash; return flash; - -err_manufacturer_probe: -err_read_id: - return NULL; } int spi_flash_read(const struct spi_flash *flash, u32 offset, size_t len, diff --git a/src/include/spi-generic.h b/src/include/spi-generic.h index eacb092d1c..e57f56d88c 100644 --- a/src/include/spi-generic.h +++ b/src/include/spi-generic.h @@ -27,16 +27,12 @@ /*----------------------------------------------------------------------- * Representation of a SPI slave, i.e. what we're communicating with. * - * Drivers are expected to extend this with controller-specific data. - * * bus: ID of the bus that the slave is attached to. * cs: ID of the chip select connected to the slave. */ struct spi_slave { unsigned int bus; unsigned int cs; - int force_programmer_specific; - struct spi_flash * (*programmer_specific_probe) (struct spi_slave *spi); }; /*----------------------------------------------------------------------- diff --git a/src/include/spi_flash.h b/src/include/spi_flash.h index 5cb68299e9..70eef8e325 100644 --- a/src/include/spi_flash.h +++ b/src/include/spi_flash.h @@ -45,6 +45,13 @@ void lb_spi_flash(struct lb_header *header); /* SPI Flash Driver Public API */ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs); +/* + * Specialized probing performed by platform. This is a weak function which can + * be overriden by platform driver. + * spi = Pointer to spi_slave structure. + * force = Indicates if the platform driver can skip specialized probing. + */ +struct spi_flash *spi_flash_programmer_probe(struct spi_slave *spi, int force); /* All the following functions return 0 on success and non-zero on error. */ int spi_flash_read(const struct spi_flash *flash, u32 offset, size_t len, diff --git a/src/soc/intel/apollolake/spi.c b/src/soc/intel/apollolake/spi.c index 018572cfab..4da292ac85 100644 --- a/src/soc/intel/apollolake/spi.c +++ b/src/soc/intel/apollolake/spi.c @@ -354,7 +354,7 @@ static struct spi_flash boot_flash CAR_GLOBAL; * The size of the flash component is always taken from density field in the * SFDP table. FLCOMP.C0DEN is no longer used by the Flash Controller. */ -static struct spi_flash *nuclear_flash_probe(struct spi_slave *spi) +struct spi_flash *spi_flash_programmer_probe(struct spi_slave *spi, int force) { BOILERPLATE_CREATE_CTX(ctx); struct spi_flash *flash; @@ -403,8 +403,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) slave->bus = bus; slave->cs = cs; - slave->programmer_specific_probe = nuclear_flash_probe; - slave->force_programmer_specific = 1; return slave; } diff --git a/src/soc/intel/skylake/flash_controller.c b/src/soc/intel/skylake/flash_controller.c index 5a715a4011..eacd414046 100644 --- a/src/soc/intel/skylake/flash_controller.c +++ b/src/soc/intel/skylake/flash_controller.c @@ -345,7 +345,7 @@ int pch_hwseq_read_status(const struct spi_flash *flash, u8 *reg) static struct spi_slave boot_spi CAR_GLOBAL; static struct spi_flash boot_flash CAR_GLOBAL; -static struct spi_flash *spi_flash_hwseq_probe(struct spi_slave *spi) +struct spi_flash *spi_flash_programmer_probe(struct spi_slave *spi, int force) { struct spi_flash *flash; @@ -380,8 +380,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) slave->bus = bus; slave->cs = cs; - slave->force_programmer_specific = 1; - slave->programmer_specific_probe = spi_flash_hwseq_probe; return slave; } diff --git a/src/soc/mediatek/mt8173/flash_controller.c b/src/soc/mediatek/mt8173/flash_controller.c index dc64d4083c..3799c6ac10 100644 --- a/src/soc/mediatek/mt8173/flash_controller.c +++ b/src/soc/mediatek/mt8173/flash_controller.c @@ -233,7 +233,7 @@ static int nor_erase(const struct spi_flash *flash, u32 offset, size_t len) return 0; } -struct spi_flash *mt8173_nor_flash_probe(struct spi_slave *spi) +struct spi_flash *spi_flash_programmer_probe(struct spi_slave *spi, int force) { static struct spi_flash flash = {0}; diff --git a/src/soc/mediatek/mt8173/include/soc/flash_controller.h b/src/soc/mediatek/mt8173/include/soc/flash_controller.h index 1d2ac32432..458f357f5d 100644 --- a/src/soc/mediatek/mt8173/include/soc/flash_controller.h +++ b/src/soc/mediatek/mt8173/include/soc/flash_controller.h @@ -87,5 +87,4 @@ struct mt8173_nor_regs { check_member(mt8173_nor_regs, fdma_end_dadr, 0x724); static struct mt8173_nor_regs * const mt8173_nor = (void *)SFLASH_REG_BASE; -struct spi_flash *mt8173_nor_flash_probe(struct spi_slave *spi); #endif /* __SOC_MEDIATEK_MT8173_FLASH_CONTROLLER_H__ */ diff --git a/src/soc/mediatek/mt8173/spi.c b/src/soc/mediatek/mt8173/spi.c index c35b1fc507..d8639e0ceb 100644 --- a/src/soc/mediatek/mt8173/spi.c +++ b/src/soc/mediatek/mt8173/spi.c @@ -173,8 +173,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) case CONFIG_BOOT_DEVICE_SPI_FLASH_BUS: slave.bus = bus; slave.cs = cs; - slave.force_programmer_specific = 1; - slave.programmer_specific_probe = &mt8173_nor_flash_probe; return &slave; default: die ("wrong bus number.\n"); diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c index e0414220c6..36102c201c 100644 --- a/src/southbridge/intel/common/spi.c +++ b/src/southbridge/intel/common/spi.c @@ -66,7 +66,6 @@ #endif /* !__SMM__ */ static int spi_is_multichip(void); -static struct spi_flash *spi_flash_hwseq(struct spi_slave *spi); typedef struct spi_slave ich_spi_slave; @@ -299,8 +298,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) slave->bus = bus; slave->cs = cs; - slave->force_programmer_specific = spi_is_multichip (); - slave->programmer_specific_probe = spi_flash_hwseq; return slave; } @@ -920,11 +917,19 @@ static int ich_hwseq_write(const struct spi_flash *flash, u32 addr, size_t len, } -static struct spi_flash *spi_flash_hwseq(struct spi_slave *spi) +struct spi_flash *spi_flash_programmer_probe(struct spi_slave *spi, int force) { struct spi_flash *flash = NULL; uint32_t flcomp; + /* + * Perform SPI flash probing only if: + * 1. spi_is_multichip returns 1 or + * 2. Specialized probing is forced by SPI flash driver. + */ + if (!spi_is_multichip() && !force) + return NULL; + flash = malloc(sizeof(*flash)); if (!flash) { printk(BIOS_WARNING, "SF: Failed to allocate memory\n"); |