diff --git a/src/drivers/spi/adesto.c b/src/drivers/spi/adesto.c index 0fba3e6677..fdde90f697 100644 --- a/src/drivers/spi/adesto.c +++ b/src/drivers/spi/adesto.c @@ -145,11 +145,6 @@ out: return ret; } -static int adesto_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_AT25DF_SE, offset, len); -} - struct spi_flash *spi_flash_probe_adesto(struct spi_slave *spi, u8 *idcode) { const struct adesto_spi_flash_params *params; @@ -183,7 +178,7 @@ struct spi_flash *spi_flash_probe_adesto(struct spi_slave *spi, u8 *idcode) page_size = 1 << params->l2_page_size; stm->flash.write = adesto_write; - stm->flash.erase = adesto_erase; + stm->flash.erase = spi_flash_cmd_erase; #if CONFIG_SPI_FLASH_NO_FAST_READ stm->flash.read = spi_flash_cmd_read_slow; #else @@ -194,6 +189,7 @@ struct spi_flash *spi_flash_probe_adesto(struct spi_slave *spi, u8 *idcode) stm->flash.size = page_size * params->pages_per_sector * params->sectors_per_block * params->nr_blocks; + stm->flash.erase_cmd = CMD_AT25DF_SE; return &stm->flash; } diff --git a/src/drivers/spi/amic.c b/src/drivers/spi/amic.c index 87ef95166a..e5f6672002 100644 --- a/src/drivers/spi/amic.c +++ b/src/drivers/spi/amic.c @@ -127,11 +127,6 @@ out: return ret; } -static int amic_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_A25_SE, offset, len); -} - struct spi_flash *spi_flash_probe_amic(struct spi_slave *spi, u8 *idcode) { const struct amic_spi_flash_params *params; @@ -165,7 +160,7 @@ struct spi_flash *spi_flash_probe_amic(struct spi_slave *spi, u8 *idcode) page_size = 1 << params->l2_page_size; amic->flash.write = amic_write; - amic->flash.erase = amic_erase; + amic->flash.erase = spi_flash_cmd_erase; #if CONFIG_SPI_FLASH_NO_FAST_READ amic->flash.read = spi_flash_cmd_read_slow; #else @@ -176,6 +171,7 @@ struct spi_flash *spi_flash_probe_amic(struct spi_slave *spi, u8 *idcode) amic->flash.size = page_size * params->pages_per_sector * params->sectors_per_block * params->nr_blocks; + amic->flash.erase_cmd = CMD_A25_SE; return &amic->flash; } diff --git a/src/drivers/spi/atmel.c b/src/drivers/spi/atmel.c index 4a0dc35e93..0286e09cdc 100644 --- a/src/drivers/spi/atmel.c +++ b/src/drivers/spi/atmel.c @@ -172,11 +172,6 @@ out: return ret; } -static int atmel_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_AT25_SE, offset, len); -} - struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode) { const struct atmel_spi_flash_params *params; @@ -210,7 +205,7 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode) page_size = 1 << params->l2_page_size; stm->flash.write = atmel_write; - stm->flash.erase = atmel_erase; + stm->flash.erase = spi_flash_cmd_erase; #if CONFIG_SPI_FLASH_NO_FAST_READ stm->flash.read = spi_flash_cmd_read_slow; #else @@ -221,6 +216,7 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode) stm->flash.size = page_size * params->pages_per_sector * params->sectors_per_block * params->nr_blocks; + stm->flash.erase_cmd = CMD_AT25_SE; return &stm->flash; } diff --git a/src/drivers/spi/eon.c b/src/drivers/spi/eon.c index 684fb2ec83..004b62bc05 100644 --- a/src/drivers/spi/eon.c +++ b/src/drivers/spi/eon.c @@ -138,11 +138,6 @@ out: return ret; } -static int eon_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_EN25_SE, offset, len); -} - struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode) { const struct eon_spi_flash_params *params; @@ -172,11 +167,12 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode) eon->flash.name = params->name; eon->flash.write = eon_write; - eon->flash.erase = eon_erase; + eon->flash.erase = spi_flash_cmd_erase; eon->flash.read = spi_flash_cmd_read_fast; eon->flash.sector_size = params->page_size * params->pages_per_sector; eon->flash.size = params->page_size * params->pages_per_sector * params->nr_sectors; + eon->flash.erase_cmd = CMD_EN25_SE; return &eon->flash; } diff --git a/src/drivers/spi/gigadevice.c b/src/drivers/spi/gigadevice.c index 9d163f8a22..9686ee9871 100644 --- a/src/drivers/spi/gigadevice.c +++ b/src/drivers/spi/gigadevice.c @@ -192,11 +192,6 @@ out: return ret; } -static int gigadevice_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_GD25_SE, offset, len); -} - static struct gigadevice_spi_flash stm; struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode) @@ -226,7 +221,7 @@ struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode) page_size = 1 << params->l2_page_size; stm.flash.write = gigadevice_write; - stm.flash.erase = gigadevice_erase; + stm.flash.erase = spi_flash_cmd_erase; #if CONFIG_SPI_FLASH_NO_FAST_READ stm.flash.read = spi_flash_cmd_read_slow; #else @@ -237,6 +232,7 @@ struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode) stm.flash.size = page_size * params->pages_per_sector * params->sectors_per_block * params->nr_blocks; + stm.flash.erase_cmd = CMD_GD25_SE; return &stm.flash; } diff --git a/src/drivers/spi/macronix.c b/src/drivers/spi/macronix.c index 51d8956351..8e514c27d0 100644 --- a/src/drivers/spi/macronix.c +++ b/src/drivers/spi/macronix.c @@ -212,11 +212,6 @@ static int macronix_write(struct spi_flash *flash, return ret; } -static int macronix_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_MX25XX_SE, offset, len); -} - struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode) { const struct macronix_spi_flash_params *params; @@ -246,7 +241,7 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode) mcx->flash.name = params->name; mcx->flash.write = macronix_write; - mcx->flash.erase = macronix_erase; + mcx->flash.erase = spi_flash_cmd_erase; #if CONFIG_SPI_FLASH_NO_FAST_READ mcx->flash.read = spi_flash_cmd_read_slow; #else @@ -255,6 +250,7 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode) mcx->flash.sector_size = params->page_size * params->pages_per_sector; mcx->flash.size = mcx->flash.sector_size * params->sectors_per_block * params->nr_blocks; + mcx->flash.erase_cmd = CMD_MX25XX_SE; return &mcx->flash; } diff --git a/src/drivers/spi/spansion.c b/src/drivers/spi/spansion.c index d7cca3ffae..6dd703c7ce 100644 --- a/src/drivers/spi/spansion.c +++ b/src/drivers/spi/spansion.c @@ -267,11 +267,6 @@ static int spansion_write(struct spi_flash *flash, return ret; } -static int spansion_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_S25FLXX_SE, offset, len); -} - static struct spansion_spi_flash spsn_flash; struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) @@ -300,10 +295,11 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) spsn->flash.name = params->name; spsn->flash.write = spansion_write; - spsn->flash.erase = spansion_erase; + spsn->flash.erase = spi_flash_cmd_erase; spsn->flash.read = spi_flash_cmd_read_slow; spsn->flash.sector_size = params->page_size * params->pages_per_sector; spsn->flash.size = spsn->flash.sector_size * params->nr_sectors; + spsn->flash.erase_cmd = CMD_S25FLXX_SE; return &spsn->flash; } diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c index 607fb214a8..8213e852be 100644 --- a/src/drivers/spi/spi_flash.c +++ b/src/drivers/spi/spi_flash.c @@ -7,6 +7,7 @@ * Licensed under the GPL-2 or later. */ +#include #include #include #include @@ -17,6 +18,8 @@ #include "spi_flash_internal.h" #include +static struct spi_flash *spi_flash_dev = NULL; + static void spi_flash_addr(u32 addr, u8 *cmd) { /* cmd[0] is actual command */ @@ -186,8 +189,7 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) CMD_READ_STATUS, STATUS_WIP); } -int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, - u32 offset, size_t len) +int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) { u32 start, end, erase_size; int ret; @@ -201,7 +203,7 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, flash->spi->rw = SPI_WRITE_FLAG; - cmd[0] = erase_cmd; + cmd[0] = flash->erase_cmd; start = offset; end = start + len; @@ -376,9 +378,45 @@ flash_detected: printk(BIOS_INFO, "SF: Detected %s with page size %x, total %x\n", flash->name, flash->sector_size, flash->size); + spi_flash_dev = flash; + return flash; err_manufacturer_probe: err_read_id: return NULL; } + +/* Only the RAM stage will build in the lb_new_record symbol + * so only define this function if we are after that stage */ +#ifdef __RAMSTAGE__ + +void lb_spi_flash(struct lb_header *header) +{ + struct lb_spi_flash *flash; + + flash = (struct lb_spi_flash *)lb_new_record(header); + + flash->tag = LB_TAG_SPI_FLASH; + flash->size = sizeof(*flash); + + /* Try to get the flash device if not loaded yet */ + if (!spi_flash_dev) { + struct cbfs_media media; + init_default_cbfs_media(&media); + } + + if (spi_flash_dev) { + flash->flash_size = spi_flash_dev->size; + flash->sector_size = spi_flash_dev->sector_size; + flash->erase_cmd = spi_flash_dev->erase_cmd; + } else { + flash->flash_size = CONFIG_ROM_SIZE; + /* Default 64k erase command should work on most flash. + * Uniform 4k erase only works on certain devices. */ + flash->sector_size = 64 * KiB; + flash->erase_cmd = CMD_BLOCK_ERASE; + } +} + +#endif diff --git a/src/drivers/spi/spi_flash_internal.h b/src/drivers/spi/spi_flash_internal.h index 4798b10925..6fe6c622b0 100644 --- a/src/drivers/spi/spi_flash_internal.h +++ b/src/drivers/spi/spi_flash_internal.h @@ -26,6 +26,8 @@ #define CMD_READ_STATUS 0x05 #define CMD_WRITE_ENABLE 0x06 +#define CMD_BLOCK_ERASE 0xD8 + /* Common status */ #define STATUS_WIP 0x01 @@ -56,8 +58,7 @@ int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout, int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout); /* Erase sectors. */ -int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, - u32 offset, size_t len); +int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len); /* Manufacturer-specific probe functions */ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode); diff --git a/src/drivers/spi/sst.c b/src/drivers/spi/sst.c index f681b7eeba..ecd792d46b 100644 --- a/src/drivers/spi/sst.c +++ b/src/drivers/spi/sst.c @@ -207,10 +207,6 @@ done: return ret; } -static int sst_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_SST_SE, offset, len); -} static int sst_unlock(struct spi_flash *flash) @@ -262,10 +258,11 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode) stm->flash.name = params->name; stm->flash.write = sst_write; - stm->flash.erase = sst_erase; + stm->flash.erase = spi_flash_cmd_erase; stm->flash.read = spi_flash_cmd_read_fast; stm->flash.sector_size = SST_SECTOR_SIZE; stm->flash.size = stm->flash.sector_size * params->nr_sectors; + stm->flash.erase_cmd = CMD_SST_SE; /* Flash powers up read-only, so clear BP# bits */ sst_unlock(&stm->flash); diff --git a/src/drivers/spi/stmicro.c b/src/drivers/spi/stmicro.c index 70ff1070a0..4df02b11a9 100644 --- a/src/drivers/spi/stmicro.c +++ b/src/drivers/spi/stmicro.c @@ -221,13 +221,6 @@ out: return ret; } -static int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash); - - return spi_flash_cmd_erase(flash, stm->params->op_erase, offset, len); -} - struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) { const struct stmicro_spi_flash_params *params; @@ -275,10 +268,11 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) stm->flash.name = params->name; stm->flash.write = stmicro_write; - stm->flash.erase = stmicro_erase; + stm->flash.erase = spi_flash_cmd_erase; stm->flash.read = spi_flash_cmd_read_fast; stm->flash.sector_size = params->page_size * params->pages_per_sector; stm->flash.size = stm->flash.sector_size * params->nr_sectors; + stm->flash.erase_cmd = params->op_erase; return &stm->flash; } diff --git a/src/drivers/spi/winbond.c b/src/drivers/spi/winbond.c index 5fc7b4274a..18ef105134 100644 --- a/src/drivers/spi/winbond.c +++ b/src/drivers/spi/winbond.c @@ -189,11 +189,6 @@ out: return ret; } -static int winbond_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_W25_SE, offset, len); -} - static struct winbond_spi_flash stm; struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) @@ -222,7 +217,7 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) page_size = 1 << params->l2_page_size; stm.flash.write = winbond_write; - stm.flash.erase = winbond_erase; + stm.flash.erase = spi_flash_cmd_erase; #if CONFIG_SPI_FLASH_NO_FAST_READ stm.flash.read = spi_flash_cmd_read_slow; #else @@ -233,6 +228,7 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) stm.flash.size = page_size * params->pages_per_sector * params->sectors_per_block * params->nr_blocks; + stm.flash.erase_cmd = CMD_W25_SE; return &stm.flash; } diff --git a/src/include/boot/coreboot_tables.h b/src/include/boot/coreboot_tables.h index a3cf2bd761..74851b2fbb 100644 --- a/src/include/boot/coreboot_tables.h +++ b/src/include/boot/coreboot_tables.h @@ -286,6 +286,15 @@ struct lb_ram_code { uint32_t ram_code; }; +#define LB_TAG_SPI_FLASH 0x0029 +struct lb_spi_flash { + uint32_t tag; + uint32_t size; + uint32_t flash_size; + uint32_t sector_size; + uint32_t erase_cmd; +}; + /* The following structures are for the cmos definitions table */ #define LB_TAG_CMOS_OPTION_TABLE 200 /* cmos header record */ diff --git a/src/include/spi_flash.h b/src/include/spi_flash.h index 8b8b0c54fe..cbb5919332 100644 --- a/src/include/spi_flash.h +++ b/src/include/spi_flash.h @@ -27,6 +27,7 @@ #include #include #include +#include struct spi_flash { struct spi_slave *spi; @@ -37,6 +38,8 @@ struct spi_flash { u32 sector_size; + u8 erase_cmd; + int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); int (*write)(struct spi_flash *flash, u32 offset, @@ -47,4 +50,6 @@ struct spi_flash { struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs); +void lb_spi_flash(struct lb_header *header); + #endif /* _SPI_FLASH_H_ */ diff --git a/src/lib/coreboot_table.c b/src/lib/coreboot_table.c index afb6743876..6450b5950f 100644 --- a/src/lib/coreboot_table.c +++ b/src/lib/coreboot_table.c @@ -32,6 +32,7 @@ #include #include #include +#include #if CONFIG_CHROMEOS #if CONFIG_HAVE_ACPI_TABLES #include @@ -468,6 +469,11 @@ unsigned long write_coreboot_table( /* Add RAM config if available */ lb_ram_code(head); +#if IS_ENABLED(CONFIG_SPI_FLASH) + /* Add SPI flash description if available */ + lb_spi_flash(head); +#endif + add_cbmem_pointers(head); /* Add board-specific table entries, if any. */