diff options
author | Aaron Durbin <adurbin@chromium.org> | 2020-01-12 15:12:18 -0700 |
---|---|---|
committer | Aaron Durbin <adurbin@chromium.org> | 2020-01-17 05:49:09 +0000 |
commit | 5abeb06a73c6f3073f2796a726ea6dc7fb584371 (patch) | |
tree | 82c6a3b967edcf0ccf0aabcbd06894b8847009af | |
parent | a6c73c898775bbc59b9d6e1fcb03e340db89ee67 (diff) | |
download | coreboot-5abeb06a73c6f3073f2796a726ea6dc7fb584371.tar.xz |
drivers/spi/spi_flash: organize spi flash by sector topology
By grouping the spi flash parts by their {vendor, sector topology}
tuple one can use a common probe function for looking up the part
instead of having per-vendor probe functions. Additionally, by
grouping by the command set one can save more space as well. SST
is the exception that requires after_probe() function to unlock the
parts.
2KiB of savings in each of verstage, romstage, and ramstage
on Aleena Chrome OS Build.
Change-Id: I9cc20ca0f3d0a1b97154b000c95ff2e7e87f3375
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/38379
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
-rw-r--r-- | src/drivers/spi/adesto.c | 59 | ||||
-rw-r--r-- | src/drivers/spi/amic.c | 57 | ||||
-rw-r--r-- | src/drivers/spi/atmel.c | 55 | ||||
-rw-r--r-- | src/drivers/spi/eon.c | 68 | ||||
-rw-r--r-- | src/drivers/spi/gigadevice.c | 62 | ||||
-rw-r--r-- | src/drivers/spi/macronix.c | 65 | ||||
-rw-r--r-- | src/drivers/spi/spansion.c | 106 | ||||
-rw-r--r-- | src/drivers/spi/spi_flash.c | 160 | ||||
-rw-r--r-- | src/drivers/spi/spi_flash_internal.h | 76 | ||||
-rw-r--r-- | src/drivers/spi/sst.c | 112 | ||||
-rw-r--r-- | src/drivers/spi/stmicro.c | 134 | ||||
-rw-r--r-- | src/drivers/spi/winbond.c | 89 | ||||
-rw-r--r-- | src/include/spi_flash.h | 3 |
13 files changed, 346 insertions, 700 deletions
diff --git a/src/drivers/spi/adesto.c b/src/drivers/spi/adesto.c index cfcde34a95..89e33f78ef 100644 --- a/src/drivers/spi/adesto.c +++ b/src/drivers/spi/adesto.c @@ -44,113 +44,70 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x4218, .name = "AT25SL128A", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, }, { .id = 0x4501, .name = "AT25DF081A", /* Yes, 81A id < 81 */ .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = 0x4502, .name = "AT25DF081", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = 0x4602, .name = "AT25DF161", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x4603, .name = "AT25DL161", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x4700, .name = "AT25DF321", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = 0x4701, .name = "AT25DF321A", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = 0x4800, .name = "AT25DF641", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, { .id = 0x8501, .name = "AT25SF081", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = 0x8600, .name = "AT25DQ161", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x8601, .name = "AT25SF161", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x8700, .name = "AT25DQ321", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, }; -static const struct spi_flash_ops spi_flash_ops = { - .read = spi_flash_cmd_read, - .write = spi_flash_cmd_write_page_program, - .erase = spi_flash_cmd_erase, - .status = spi_flash_cmd_status, +const struct spi_flash_vendor_info spi_flash_adesto_vi = { + .id = VENDOR_ID_ADESTO, + .page_size_shift = 8, + .sector_size_kib_shift = 2, + .match_id_mask = 0xffff, + .ids = flash_table, + .nr_part_ids = ARRAY_SIZE(flash_table), + .desc = &spi_flash_pp_0x20_sector_desc, }; - -int spi_flash_probe_adesto(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) -{ - const struct spi_flash_part_id *params; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(flash_table); i++) { - params = &flash_table[i]; - if (params->id == ((idcode[1] << 8) | idcode[2])) - break; - } - - if (i == ARRAY_SIZE(flash_table)) { - printk(BIOS_WARNING, "SF: Unsupported adesto ID %02x%02x\n", - idcode[1], idcode[2]); - return -1; - } - - memcpy(&flash->spi, spi, sizeof(*spi)); - flash->name = params->name; - /* Assuming power-of-two page size initially. */ - flash->page_size = 256; - flash->sector_size = (1U << params->sector_size_kib_shift) * KiB; - flash->size = flash->sector_size * (1U << params->nr_sectors_shift); - flash->erase_cmd = CMD_AT25DF_SE; - flash->status_cmd = CMD_AT25DF_RDSR; - flash->pp_cmd = CMD_AT25DF_PP; - flash->wren_cmd = CMD_AT25DF_WREN; - - flash->ops = &spi_flash_ops; - - return 0; -} diff --git a/src/drivers/spi/amic.c b/src/drivers/spi/amic.c index fb5bdea27e..8e25cd933c 100644 --- a/src/drivers/spi/amic.c +++ b/src/drivers/spi/amic.c @@ -39,96 +39,55 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x2015, .name = "A25L16PU", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x2025, .name = "A25L16PT", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x3014, .name = "A25L080", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = 0x3015, .name = "A25L016", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x3016, .name = "A25L032", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = 0x4014, .name = "A25LQ080", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = 0x4015, .name = "A25LQ16", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x4016, .name = "A25LQ032", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = 0x4017, .name = "A25LQ64", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, }; -static const struct spi_flash_ops spi_flash_ops = { - .read = spi_flash_cmd_read, - .write = spi_flash_cmd_write_page_program, - .erase = spi_flash_cmd_erase, - .status = spi_flash_cmd_status, +const struct spi_flash_vendor_info spi_flash_amic_vi = { + .id = VENDOR_ID_AMIC, + .page_size_shift = 8, + .sector_size_kib_shift = 2, + .match_id_mask = 0xffff, + .ids = flash_table, + .nr_part_ids = ARRAY_SIZE(flash_table), + .desc = &spi_flash_pp_0x20_sector_desc, }; - -int spi_flash_probe_amic(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) -{ - const struct spi_flash_part_id *params; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(flash_table); i++) { - params = &flash_table[i]; - if (params->id == ((idcode[1] << 8) | idcode[2])) - break; - } - - if (i == ARRAY_SIZE(flash_table)) { - printk(BIOS_WARNING, "SF: Unsupported AMIC ID %02x%02x\n", - idcode[1], idcode[2]); - return -1; - } - - memcpy(&flash->spi, spi, sizeof(*spi)); - flash->name = params->name; - - /* Assuming power-of-two page size initially. */ - flash->page_size = 256; - flash->sector_size = (1U << params->sector_size_kib_shift) * KiB; - flash->size = flash->sector_size * (1U << params->nr_sectors_shift); - flash->erase_cmd = CMD_A25_SE; - flash->status_cmd = CMD_A25_RDSR; - flash->pp_cmd = CMD_A25_PP; - flash->wren_cmd = CMD_A25_WREN; - - flash->ops = &spi_flash_ops; - - return 0; -} diff --git a/src/drivers/spi/atmel.c b/src/drivers/spi/atmel.c index a49484464e..ae282c323b 100644 --- a/src/drivers/spi/atmel.c +++ b/src/drivers/spi/atmel.c @@ -39,84 +39,45 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x3015, .name = "AT25X16", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x47, .name = "AT25DF32", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = 0x3017, .name = "AT25X64", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, { .id = 0x4015, .name = "AT25Q16", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x4016, .name = "AT25Q32", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = 0x4017, .name = "AT25Q64", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, { .id = 0x4018, .name = "AT25Q128", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, }, }; -static const struct spi_flash_ops spi_flash_ops = { - .read = spi_flash_cmd_read, - .write = spi_flash_cmd_write_page_program, - .erase = spi_flash_cmd_erase, - .status = spi_flash_cmd_status, +const struct spi_flash_vendor_info spi_flash_atmel_vi = { + .id = VENDOR_ID_ATMEL, + .page_size_shift = 8, + .sector_size_kib_shift = 2, + .match_id_mask = 0xffff, + .ids = flash_table, + .nr_part_ids = ARRAY_SIZE(flash_table), + .desc = &spi_flash_pp_0x20_sector_desc, }; - -int spi_flash_probe_atmel(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) -{ - const struct spi_flash_part_id *params; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(flash_table); i++) { - params = &flash_table[i]; - if (params->id == ((idcode[1] << 8) | idcode[2])) - break; - } - - if (i == ARRAY_SIZE(flash_table)) { - printk(BIOS_WARNING, "SF: Unsupported Atmel ID %02x%02x\n", - idcode[1], idcode[2]); - return -1; - } - - memcpy(&flash->spi, spi, sizeof(*spi)); - flash->name = params->name; - - /* Assuming power-of-two page size initially. */ - flash->page_size = 256; - flash->sector_size = (1U << params->sector_size_kib_shift) * KiB; - flash->size = flash->sector_size * (1U << params->nr_sectors_shift); - flash->erase_cmd = CMD_AT25_SE; - flash->status_cmd = CMD_AT25_RDSR; - flash->pp_cmd = CMD_AT25_PP; - flash->wren_cmd = CMD_AT25_WREN; - - flash->ops = &spi_flash_ops; - - return 0; -} diff --git a/src/drivers/spi/eon.c b/src/drivers/spi/eon.c index 3270c39ab5..6d4833ce22 100644 --- a/src/drivers/spi/eon.c +++ b/src/drivers/spi/eon.c @@ -60,167 +60,115 @@ static const struct spi_flash_part_id flash_table[] = { .id = EON_ID_EN25B80, .name = "EN25B80", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25B16, .name = "EN25B16", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25B32, .name = "EN25B32", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25B64, .name = "EN25B64", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25F80, .name = "EN25F80", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25F16, .name = "EN25F16", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25F32, .name = "EN25F32", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25F64, .name = "EN25F64", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25Q80, .name = "EN25Q80(A)", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25Q16, .name = "EN25Q16(D16)", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25Q32, .name = "EN25Q32(A/B)", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25Q64, .name = "EN25Q64", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25Q128, .name = "EN25Q128", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25QH16, .name = "EN25QH16", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25QH32, .name = "EN25QH32", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25QH64, .name = "EN25QH64", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25QH128, .name = "EN25QH128", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25S80, .name = "EN25S80", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25S16, .name = "EN25S16", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25S32, .name = "EN25S32", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = EON_ID_EN25S64, .name = "EN25S64", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, }; -static const struct spi_flash_ops spi_flash_ops = { - .read = spi_flash_cmd_read, - .write = spi_flash_cmd_write_page_program, - .erase = spi_flash_cmd_erase, - .status = spi_flash_cmd_status, +const struct spi_flash_vendor_info spi_flash_eon_vi = { + .id = VENDOR_ID_EON, + .page_size_shift = 8, + .sector_size_kib_shift = 2, + .match_id_mask = 0xffff, + .ids = flash_table, + .nr_part_ids = ARRAY_SIZE(flash_table), + .desc = &spi_flash_pp_0x20_sector_desc, }; - -int spi_flash_probe_eon(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) -{ - const struct spi_flash_part_id *params; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(flash_table); ++i) { - params = &flash_table[i]; - if (params->id == ((idcode[1] << 8) | idcode[2])) - break; - } - - if (i == ARRAY_SIZE(flash_table)) { - printk(BIOS_WARNING, "SF: Unsupported EON ID %#02x%02x\n", - idcode[1], idcode[2]); - return -1; - } - - memcpy(&flash->spi, spi, sizeof(*spi)); - - flash->name = params->name; - flash->page_size = 256; - flash->sector_size = (1U << params->sector_size_kib_shift) * KiB; - flash->size = flash->sector_size * (1U << params->nr_sectors_shift); - flash->erase_cmd = CMD_EN25_SE; - flash->status_cmd = CMD_EN25_RDSR; - flash->pp_cmd = CMD_EN25_PP; - flash->wren_cmd = CMD_EN25_WREN; - - flash->ops = &spi_flash_ops; - - return 0; -} diff --git a/src/drivers/spi/gigadevice.c b/src/drivers/spi/gigadevice.c index 010fb45e4a..64d9706551 100644 --- a/src/drivers/spi/gigadevice.c +++ b/src/drivers/spi/gigadevice.c @@ -39,133 +39,87 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x3114, .name = "GD25T80", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = 0x4014, .name = "GD25Q80", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, /* also GD25Q80B */ { .id = 0x4015, .name = "GD25Q16", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, /* also GD25Q16B */ { .id = 0x4016, .name = "GD25Q32B", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, /* also GD25Q32B */ { .id = 0x4017, .name = "GD25Q64", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, /* also GD25Q64B, GD25B64C */ { .id = 0x4018, .name = "GD25Q128", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, /* also GD25Q128B */ { .id = 0x4214, .name = "GD25VQ80C", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, { .id = 0x4215, .name = "GD25VQ16C", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, { .id = 0x6014, .name = "GD25LQ80", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, { .id = 0x6015, .name = "GD25LQ16", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, { .id = 0x6016, .name = "GD25LQ32", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, { .id = 0x6017, .name = "GD25LQ64C", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, /* also GD25LB64C */ { .id = 0x6018, .name = "GD25LQ128", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, }; -static const struct spi_flash_ops spi_flash_ops = { - .read = spi_flash_cmd_read, - .write = spi_flash_cmd_write_page_program, - .erase = spi_flash_cmd_erase, - .status = spi_flash_cmd_status, +const struct spi_flash_vendor_info spi_flash_gigadevice_vi = { + .id = VENDOR_ID_GIGADEVICE, + .page_size_shift = 8, + .sector_size_kib_shift = 2, + .match_id_mask = 0xffff, + .ids = flash_table, + .nr_part_ids = ARRAY_SIZE(flash_table), + .desc = &spi_flash_pp_0x20_sector_desc, }; - -int spi_flash_probe_gigadevice(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) -{ - const struct spi_flash_part_id *params; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(flash_table); i++) { - params = &flash_table[i]; - if (params->id == ((idcode[1] << 8) | idcode[2])) - break; - } - - if (i == ARRAY_SIZE(flash_table)) { - printk(BIOS_WARNING, - "SF gigadevice.c: Unsupported ID %#02x%02x\n", - idcode[1], idcode[2]); - return -1; - } - - memcpy(&flash->spi, spi, sizeof(*spi)); - flash->name = params->name; - - /* Assuming power-of-two page size initially. */ - flash->page_size = 256; - flash->sector_size = (1U << params->sector_size_kib_shift) * KiB; - flash->size = flash->sector_size * (1U << params->nr_sectors_shift); - flash->erase_cmd = CMD_GD25_SE; - flash->status_cmd = CMD_GD25_RDSR; - flash->pp_cmd = CMD_GD25_PP; - flash->wren_cmd = CMD_GD25_WREN; - - flash->ops = &spi_flash_ops; - - return 0; -} diff --git a/src/drivers/spi/macronix.c b/src/drivers/spi/macronix.c index c7a4ce06aa..f23b421211 100644 --- a/src/drivers/spi/macronix.c +++ b/src/drivers/spi/macronix.c @@ -41,154 +41,105 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x2014, .name = "MX25L8005", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = 0x2015, .name = "MX25L1605D", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x2016, .name = "MX25L3205D", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = 0x2017, .name = "MX25L6405D", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, { .id = 0x2018, .name = "MX25L12805D", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, }, { .id = 0x2019, .name = "MX25L25635F", .nr_sectors_shift = 13, - .sector_size_kib_shift = 2, }, { .id = 0x201a, .name = "MX66L51235F", .nr_sectors_shift = 14, - .sector_size_kib_shift = 2, }, { .id = 0x2415, .name = "MX25L1635D", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x2515, .name = "MX25L1635E", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x2534, .name = "MX25U8032E", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = 0x2535, .name = "MX25U1635E", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x2536, .name = "MX25U3235E", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = 0x2537, .name = "MX25U6435F", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, { .id = 0x2538, .name = "MX25U12835F", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, }, { .id = 0x2539, .name = "MX25U25635F", .nr_sectors_shift = 13, - .sector_size_kib_shift = 2, }, { .id = 0x253a, .name = "MX25U51245G", .nr_sectors_shift = 14, - .sector_size_kib_shift = 2, }, { .id = 0x2618, .name = "MX25L12855E", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, }, { .id = 0x5e16, .name = "MX25L3235D", /* MX25L3225D/MX25L3236D/MX25L3237D */ .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = 0x9517, .name = "MX25L6495F", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, }; -static const struct spi_flash_ops spi_flash_ops = { - .read = spi_flash_cmd_read, - .write = spi_flash_cmd_write_page_program, - .erase = spi_flash_cmd_erase, - .status = spi_flash_cmd_status, +const struct spi_flash_vendor_info spi_flash_macronix_vi = { + .id = VENDOR_ID_MACRONIX, + .page_size_shift = 8, + .sector_size_kib_shift = 2, + .match_id_mask = 0xffff, + .ids = flash_table, + .nr_part_ids = ARRAY_SIZE(flash_table), + .desc = &spi_flash_pp_0x20_sector_desc, }; - -int spi_flash_probe_macronix(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) -{ - const struct spi_flash_part_id *params; - unsigned int i; - u16 id = idcode[2] | idcode[1] << 8; - - for (i = 0; i < ARRAY_SIZE(flash_table); i++) { - params = &flash_table[i]; - if (params->id == id) - break; - } - - if (i == ARRAY_SIZE(flash_table)) { - printk(BIOS_WARNING, "SF: Unsupported Macronix ID %04x\n", id); - return -1; - } - - memcpy(&flash->spi, spi, sizeof(*spi)); - flash->name = params->name; - flash->page_size = 256; - flash->sector_size = (1U << params->sector_size_kib_shift) * KiB; - flash->size = flash->sector_size * params->nr_sectors_shift; - flash->erase_cmd = CMD_MX25XX_SE; - flash->status_cmd = CMD_MX25XX_RDSR; - flash->pp_cmd = CMD_MX25XX_PP; - flash->wren_cmd = CMD_MX25XX_WREN; - - flash->ops = &spi_flash_ops; - - return 0; -} diff --git a/src/drivers/spi/spansion.c b/src/drivers/spi/spansion.c index b4fca4f8b3..c694f4517e 100644 --- a/src/drivers/spi/spansion.c +++ b/src/drivers/spi/spansion.c @@ -54,55 +54,49 @@ static const struct spi_flash_part_id flash_table_ext[] = { .id = SPSN_ID_S25FL008A, .name = "S25FL008A", .nr_sectors_shift = 4, - .sector_size_kib_shift = 6, }, { .id = SPSN_ID_S25FL016A, .name = "S25FL016A", .nr_sectors_shift = 5, - .sector_size_kib_shift = 6, }, { .id = SPSN_ID_S25FL032A, .name = "S25FL032A", .nr_sectors_shift = 6, - .sector_size_kib_shift = 6, }, { .id = SPSN_ID_S25FL064A, .name = "S25FL064A", .nr_sectors_shift = 7, - .sector_size_kib_shift = 6, }, { .id = (SPSN_EXT_ID_S25FL128P_64KB << 16) | SPSN_ID_S25FL128P, .name = "S25FL128P_64K", .nr_sectors_shift = 8, - .sector_size_kib_shift = 6, - }, - { - .id = (SPSN_EXT_ID_S25FL128P_256KB << 16) | SPSN_ID_S25FL128P, - .name = "S25FL128P_256K", - .nr_sectors_shift = 6, - .sector_size_kib_shift = 8, }, { .id = (SPSN_EXT_ID_S25FLXXS_64KB << 16) | SPSN_ID_S25FL128S, .name = "S25FL128S_256K", .nr_sectors_shift = 9, - .sector_size_kib_shift = 6, }, { .id = (SPSN_EXT_ID_S25FL032P << 16) | SPSN_ID_S25FL032A, .name = "S25FL032P", .nr_sectors_shift = 6, - .sector_size_kib_shift = 6, }, { .id = (SPSN_EXT_ID_S25FLXXS_64KB << 16) | SPSN_ID_S25FL128P, .name = "S25FS128S", .nr_sectors_shift = 8, - .sector_size_kib_shift = 6, + }, +}; + +static const struct spi_flash_part_id flash_table_256k_sector[] = { + { + .id = (SPSN_EXT_ID_S25FL128P_256KB << 16) | SPSN_ID_S25FL128P, + .name = "S25FL128P_256K", + .nr_sectors_shift = 6, }, }; @@ -111,82 +105,50 @@ static const struct spi_flash_part_id flash_table[] = { .id = SPSN_ID_S25FL208K, .name = "S25FL208K", .nr_sectors_shift = 4, - .sector_size_kib_shift = 6, }, { .id = SPSN_ID_S25FL116K, .name = "S25FL116K_16M", .nr_sectors_shift = 5, - .sector_size_kib_shift = 6, }, { .id = SPSN_ID_S25FL132K, .name = "S25FL132K", .nr_sectors_shift = 6, - .sector_size_kib_shift = 6, }, { .id = SPSN_ID_S25FL164K, .name = "S25FL164K", .nr_sectors_shift = 7, - .sector_size_kib_shift = 6, }, }; -static const struct spi_flash_ops spi_flash_ops = { - .read = spi_flash_cmd_read, - .write = spi_flash_cmd_write_page_program, - .erase = spi_flash_cmd_erase, - .status = spi_flash_cmd_status, +const struct spi_flash_vendor_info spi_flash_spansion_ext1_vi = { + .id = VENDOR_ID_SPANSION, + .page_size_shift = 8, + .sector_size_kib_shift = 6, + .match_id_mask = 0xffffffff, + .ids = flash_table_ext, + .nr_part_ids = ARRAY_SIZE(flash_table_ext), + .desc = &spi_flash_pp_0xd8_sector_desc, }; +const struct spi_flash_vendor_info spi_flash_spansion_ext2_vi = { + .id = VENDOR_ID_SPANSION, + .page_size_shift = 8, + .sector_size_kib_shift = 8, + .match_id_mask = 0xffffffff, + .ids = flash_table_256k_sector, + .nr_part_ids = ARRAY_SIZE(flash_table_256k_sector), + .desc = &spi_flash_pp_0xd8_sector_desc, +}; -static int match_table(const struct spi_slave *spi, struct spi_flash *flash, u32 id, - const struct spi_flash_part_id *parts, size_t num_parts) -{ - const struct spi_flash_part_id *params = NULL; - unsigned int i; - - for (i = 0; i < num_parts; i++) { - if (parts[i].id != id) - continue; - params = &parts[i]; - break; - } - - if (params == NULL) - return -1; - - memcpy(&flash->spi, spi, sizeof(*spi)); - flash->name = params->name; - flash->page_size = 256; - flash->sector_size = (1U << params->sector_size_kib_shift) * KiB; - flash->size = flash->sector_size * (1U << params->nr_sectors_shift); - flash->erase_cmd = CMD_S25FLXX_SE; - flash->status_cmd = CMD_S25FLXX_RDSR; - flash->pp_cmd = CMD_S25FLXX_PP; - flash->wren_cmd = CMD_S25FLXX_WREN; - - flash->ops = &spi_flash_ops; - - return 0; -} - -int spi_flash_probe_spansion(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) -{ - u32 id; - - id = ((idcode[3] << 8) | idcode[4]) << 16; - id |= (idcode[1] << 8) | idcode[2]; - - if (!match_table(spi, flash, id, flash_table_ext, ARRAY_SIZE(flash_table_ext))) - return 0; - - if (!match_table(spi, flash, id & 0xffff, flash_table, ARRAY_SIZE(flash_table))) - return 0; - - printk(BIOS_WARNING, "SF: Unsupported SPANSION ID %08x\n", id); - - return -1; -} +const struct spi_flash_vendor_info spi_flash_spansion_vi = { + .id = VENDOR_ID_SPANSION, + .page_size_shift = 8, + .sector_size_kib_shift = 6, + .match_id_mask = 0xffff, + .ids = flash_table, + .nr_part_ids = ARRAY_SIZE(flash_table), + .desc = &spi_flash_pp_0xd8_sector_desc, +}; diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c index 0024e9b286..90dd5877ff 100644 --- a/src/drivers/spi/spi_flash.c +++ b/src/drivers/spi/spi_flash.c @@ -309,64 +309,122 @@ out: return ret; } -/* - * The following table holds all device probe functions - * - * idcode: the expected IDCODE - * probe: the function to call - * - * Several matching entries are permitted, they will be tried - * in sequence until a probe function returns non NULL. - * - * Probe functions will be given the idcode buffer starting at their - * manu id byte (the "idcode" in the table below). - */ -static struct { - const u8 idcode; - int (*probe) (const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash); -} flashes[] = { - /* Keep it sorted by define name */ +static const struct spi_flash_vendor_info *spi_flash_vendors[] = { +#if CONFIG(SPI_FLASH_ADESTO) + &spi_flash_adesto_vi, +#endif #if CONFIG(SPI_FLASH_AMIC) - { VENDOR_ID_AMIC, spi_flash_probe_amic, }, + &spi_flash_amic_vi, #endif #if CONFIG(SPI_FLASH_ATMEL) - { VENDOR_ID_ATMEL, spi_flash_probe_atmel, }, + &spi_flash_atmel_vi, #endif #if CONFIG(SPI_FLASH_EON) - { VENDOR_ID_EON, spi_flash_probe_eon, }, + &spi_flash_eon_vi, #endif #if CONFIG(SPI_FLASH_GIGADEVICE) - { VENDOR_ID_GIGADEVICE, spi_flash_probe_gigadevice, }, + &spi_flash_gigadevice_vi, #endif #if CONFIG(SPI_FLASH_MACRONIX) - { VENDOR_ID_MACRONIX, spi_flash_probe_macronix, }, + &spi_flash_macronix_vi, #endif #if CONFIG(SPI_FLASH_SPANSION) - { VENDOR_ID_SPANSION, spi_flash_probe_spansion, }, + &spi_flash_spansion_ext1_vi, + &spi_flash_spansion_ext2_vi, + &spi_flash_spansion_vi, #endif #if CONFIG(SPI_FLASH_SST) - { VENDOR_ID_SST, spi_flash_probe_sst, }, + &spi_flash_sst_ai_vi, + &spi_flash_sst_vi, #endif #if CONFIG(SPI_FLASH_STMICRO) - { VENDOR_ID_STMICRO, spi_flash_probe_stmicro, }, + &spi_flash_stmicro1_vi, + &spi_flash_stmicro2_vi, + &spi_flash_stmicro3_vi, + &spi_flash_stmicro4_vi, #endif #if CONFIG(SPI_FLASH_WINBOND) - { VENDOR_ID_WINBOND, spi_flash_probe_winbond, }, -#endif - /* Keep it sorted by best detection */ -#if CONFIG(SPI_FLASH_ADESTO) - { VENDOR_ID_ADESTO, spi_flash_probe_adesto, }, + &spi_flash_winbond_vi, #endif }; #define IDCODE_LEN 5 +static int fill_spi_flash(const struct spi_slave *spi, struct spi_flash *flash, + const struct spi_flash_vendor_info *vi, + const struct spi_flash_part_id *part) +{ + memcpy(&flash->spi, spi, sizeof(*spi)); + flash->vendor = vi->id; + flash->model = part->id; + flash->name = part->name; + + flash->page_size = 1U << vi->page_size_shift; + flash->sector_size = (1U << vi->sector_size_kib_shift) * KiB; + flash->size = flash->sector_size * (1U << part->nr_sectors_shift); + flash->erase_cmd = vi->desc->erase_cmd; + flash->status_cmd = vi->desc->status_cmd; + flash->pp_cmd = vi->desc->pp_cmd; + flash->wren_cmd = vi->desc->wren_cmd; + + flash->flags.dual_spi = part->fast_read_dual_output_support; + + flash->ops = &vi->desc->ops; + flash->prot_ops = vi->prot_ops; + flash->part = part; + + if (vi->after_probe) + return vi->after_probe(flash); + + return 0; +} + +static const struct spi_flash_part_id *find_part(const struct spi_flash_vendor_info *vi, + uint32_t id) +{ + size_t i; + + for (i = 0; i < vi->nr_part_ids; i++) { + const struct spi_flash_part_id *part = &vi->ids[i]; + + if (part->id == id) + return part; + } + + return NULL; +} + +static int find_match(const struct spi_slave *spi, struct spi_flash *flash, + uint8_t manuf_id, uint32_t id) +{ + int i; + + for (i = 0; i < (int)ARRAY_SIZE(spi_flash_vendors); i++) { + const struct spi_flash_vendor_info *vi; + const struct spi_flash_part_id *part; + + vi = spi_flash_vendors[i]; + + if (manuf_id != vi->id) + continue; + + part = find_part(vi, id & vi->match_id_mask); + + if (part == NULL) + continue; + + return fill_spi_flash(spi, flash, vi, part); + } + + return -1; +} + int spi_flash_generic_probe(const struct spi_slave *spi, struct spi_flash *flash) { int ret, i; u8 idcode[IDCODE_LEN]; u8 manuf_id; + u32 id; /* Read the ID codes */ ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); @@ -392,19 +450,9 @@ int spi_flash_generic_probe(const struct spi_slave *spi, manuf_id = idcode[0]; } - /* search the table for matches in shift and id */ - for (i = 0; i < (int)ARRAY_SIZE(flashes); ++i) - if (flashes[i].idcode == manuf_id) { - /* we have a match, call probe */ - if (flashes[i].probe(spi, idcode, flash) == 0) { - flash->vendor = idcode[0]; - flash->model = (idcode[1] << 8) | idcode[2]; - return 0; - } - } + id = (idcode[3] << 24) | (idcode[4] << 16) | (idcode[1] << 8) | idcode[2]; - /* No match, return error. */ - return -1; + return find_match(spi, flash, manuf_id, id); } int spi_flash_probe(unsigned int bus, unsigned int cs, struct spi_flash *flash) @@ -701,3 +749,29 @@ int spi_flash_vector_helper(const struct spi_slave *slave, return ret; } + +const struct spi_flash_ops_descriptor spi_flash_pp_0x20_sector_desc = { + .erase_cmd = 0x20, /* Sector Erase */ + .status_cmd = 0x05, /* Read Status */ + .pp_cmd = 0x02, /* Page Program */ + .wren_cmd = 0x06, /* Write Enable */ + .ops = { + .read = spi_flash_cmd_read, + .write = spi_flash_cmd_write_page_program, + .erase = spi_flash_cmd_erase, + .status = spi_flash_cmd_status, + }, +}; + +const struct spi_flash_ops_descriptor spi_flash_pp_0xd8_sector_desc = { + .erase_cmd = 0xd8, /* Sector Erase */ + .status_cmd = 0x05, /* Read Status */ + .pp_cmd = 0x02, /* Page Program */ + .wren_cmd = 0x06, /* Write Enable */ + .ops = { + .read = spi_flash_cmd_read, + .write = spi_flash_cmd_write_page_program, + .erase = spi_flash_cmd_erase, + .status = spi_flash_cmd_status, + }, +}; diff --git a/src/drivers/spi/spi_flash_internal.h b/src/drivers/spi/spi_flash_internal.h index cc258ded20..bd52d66075 100644 --- a/src/drivers/spi/spi_flash_internal.h +++ b/src/drivers/spi/spi_flash_internal.h @@ -69,42 +69,70 @@ int spi_flash_cmd_write_page_program(const struct spi_flash *flash, u32 offset, /* Read len bytes into buf at offset. */ int spi_flash_cmd_read(const struct spi_flash *flash, u32 offset, size_t len, void *buf); -/* Manufacturer-specific probe functions */ -int spi_flash_probe_spansion(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash); -int spi_flash_probe_amic(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash); -int spi_flash_probe_atmel(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash); -int spi_flash_probe_eon(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash); -int spi_flash_probe_macronix(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash); -int spi_flash_probe_sst(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash); -int spi_flash_probe_stmicro(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash); /* Release from deep sleep an provide alternative rdid information. */ int stmicro_release_deep_sleep_identify(const struct spi_slave *spi, u8 *idcode); -int spi_flash_probe_winbond(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash); -int spi_flash_probe_gigadevice(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash); -int spi_flash_probe_adesto(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash); struct spi_flash_part_id { + /* rdid command constructs a 32-bit id using the following method + * for matching: 31 | id[3] | id[4] | id[1] | id[2] | 0 */ uint32_t id; const char *name; /* Log based 2 total number of sectors. */ uint16_t nr_sectors_shift: 4; - /* Log based 2 sector size */ - uint16_t sector_size_kib_shift: 4; uint16_t fast_read_dual_output_support : 1; - uint16_t _reserved_for_flags: 7; + uint16_t _reserved_for_flags: 3; /* Block protection. Currently used by Winbond. */ uint16_t protection_granularity_shift : 5; uint16_t bp_bits : 3; }; +struct spi_flash_ops_descriptor { + uint8_t erase_cmd; /* Sector Erase */ + uint8_t status_cmd; /* Read Status Register */ + uint8_t pp_cmd; /* Page program command, if supported. */ + uint8_t wren_cmd; /* Write Enable command. */ + struct spi_flash_ops ops; +}; + +/* Vendor info represents a common set of organization and commands by a given + * vendor. One can implement multiple sets from a single vendor by having + * separate objects. */ +struct spi_flash_vendor_info { + uint8_t id; + uint8_t page_size_shift : 4; /* if page programming oriented. */ + /* Log based 2 sector size */ + uint8_t sector_size_kib_shift : 4; + uint16_t nr_part_ids; + const struct spi_flash_part_id *ids; + uint32_t match_id_mask; /* matching bytes of the id for this set*/ + const struct spi_flash_ops_descriptor *desc; + const struct spi_flash_protection_ops *prot_ops; + /* Returns 0 on success. !0 otherwise. */ + int (*after_probe)(const struct spi_flash *flash); +}; + +/* Manufacturer-specific probe information */ +extern const struct spi_flash_vendor_info spi_flash_adesto_vi; +extern const struct spi_flash_vendor_info spi_flash_amic_vi; +extern const struct spi_flash_vendor_info spi_flash_atmel_vi; +extern const struct spi_flash_vendor_info spi_flash_eon_vi; +extern const struct spi_flash_vendor_info spi_flash_gigadevice_vi; +extern const struct spi_flash_vendor_info spi_flash_macronix_vi; +/* Probing order matters between the spansion sequence. */ +extern const struct spi_flash_vendor_info spi_flash_spansion_ext1_vi; +extern const struct spi_flash_vendor_info spi_flash_spansion_ext2_vi; +extern const struct spi_flash_vendor_info spi_flash_spansion_vi; +extern const struct spi_flash_vendor_info spi_flash_sst_ai_vi; +extern const struct spi_flash_vendor_info spi_flash_sst_vi; +extern const struct spi_flash_vendor_info spi_flash_stmicro1_vi; +extern const struct spi_flash_vendor_info spi_flash_stmicro2_vi; +extern const struct spi_flash_vendor_info spi_flash_stmicro3_vi; +extern const struct spi_flash_vendor_info spi_flash_stmicro4_vi; +extern const struct spi_flash_vendor_info spi_flash_winbond_vi; + +/* Page Programming Command Set with 0x20 Sector Erase command. */ +extern const struct spi_flash_ops_descriptor spi_flash_pp_0x20_sector_desc; +/* Page Programming Command Set with 0xd8 Sector Erase command. */ +extern const struct spi_flash_ops_descriptor spi_flash_pp_0xd8_sector_desc; + #endif /* SPI_FLASH_INTERNAL_H */ diff --git a/src/drivers/spi/sst.c b/src/drivers/spi/sst.c index 1b4ba57f1e..559f30f022 100644 --- a/src/drivers/spi/sst.c +++ b/src/drivers/spi/sst.c @@ -44,79 +44,51 @@ #define SST_SR_AAI (1 << 6) /* Addressing mode */ #define SST_SR_BPL (1 << 7) /* BP bits lock */ -static int sst_write_ai(const struct spi_flash *flash, u32 offset, size_t len, - const void *buf); - -static const struct spi_flash_ops spi_flash_ops_write_ai = { - .read = spi_flash_cmd_read, - .write = sst_write_ai, - .erase = spi_flash_cmd_erase, - .status = spi_flash_cmd_status, -}; - -static const struct spi_flash_ops spi_flash_ops_write_256 = { - .read = spi_flash_cmd_read, - .write = spi_flash_cmd_write_page_program, - .erase = spi_flash_cmd_erase, - .status = spi_flash_cmd_status, -}; - static const struct spi_flash_part_id flash_table_ai[] = { { .id = 0x8d, .name = "SST25VF040B", .nr_sectors_shift = 7, - .sector_size_kib_shift = 2, },{ .id = 0x8e, .name = "SST25VF080B", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, },{ .id = 0x80, .name = "SST25VF080", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, },{ .id = 0x41, .name = "SST25VF016B", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, },{ .id = 0x4a, .name = "SST25VF032B", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, },{ .id = 0x01, .name = "SST25WF512", .nr_sectors_shift = 4, - .sector_size_kib_shift = 2, },{ .id = 0x02, .name = "SST25WF010", .nr_sectors_shift = 5, - .sector_size_kib_shift = 2, },{ .id = 0x03, .name = "SST25WF020", .nr_sectors_shift = 6, - .sector_size_kib_shift = 2, },{ .id = 0x04, .name = "SST25WF040", .nr_sectors_shift = 7, - .sector_size_kib_shift = 2, },{ .id = 0x05, .name = "SST25WF080", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, },{ .id = 0x14, .name = "SST25WF080B", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, }; @@ -125,7 +97,6 @@ static const struct spi_flash_part_id flash_table_pp256[] = { .id = 0x4b, .name = "SST25VF064C", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, }; @@ -247,9 +218,8 @@ done: return ret; } - -static int -sst_unlock(const struct spi_flash *flash) +/* Flash powers up read-only, so clear BP# bits */ +static int sst_unlock(const struct spi_flash *flash) { int ret; u8 cmd, status; @@ -269,53 +239,35 @@ sst_unlock(const struct spi_flash *flash) return ret; } -static int match_table(const struct spi_slave *spi, struct spi_flash *flash, u8 id, - const struct spi_flash_part_id *parts, size_t num_parts, - const struct spi_flash_ops *ops) -{ - const struct spi_flash_part_id *params; - size_t i; - - for (i = 0; i < num_parts; i++) { - params = &parts[i]; - if (params->id == id) - break; - } - - if (i == num_parts) - return -1; - - memcpy(&flash->spi, spi, sizeof(*spi)); - flash->name = params->name; - flash->sector_size = (1U << params->sector_size_kib_shift) * KiB; - flash->size = flash->sector_size * (1U << params->nr_sectors_shift); - flash->erase_cmd = CMD_SST_SE; - flash->status_cmd = CMD_SST_RDSR; - flash->wren_cmd = CMD_SST_WREN; - - flash->ops = ops; - - /* Flash powers up read-only, so clear BP# bits */ - sst_unlock(flash); - - return 0; -} - -int spi_flash_probe_sst(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) -{ - if (!match_table(spi, flash, idcode[2], flash_table_ai, - ARRAY_SIZE(flash_table_ai), &spi_flash_ops_write_ai)) - return 0; - - if (!match_table(spi, flash, idcode[2], flash_table_pp256, - ARRAY_SIZE(flash_table_pp256), &spi_flash_ops_write_256)) { - flash->page_size = 256; - flash->pp_cmd = CMD_SST_PP; - return 0; - } +static const struct spi_flash_ops_descriptor descai = { + .erase_cmd = CMD_SST_SE, + .status_cmd = CMD_SST_RDSR, + .wren_cmd = CMD_SST_WREN, + .ops = { + .read = spi_flash_cmd_read, + .write = sst_write_ai, + .erase = spi_flash_cmd_erase, + .status = spi_flash_cmd_status, + }, +}; - printk(BIOS_WARNING, "SF: Unsupported SST ID %02x\n", idcode[2]); +const struct spi_flash_vendor_info spi_flash_sst_ai_vi = { + .id = VENDOR_ID_SST, + .sector_size_kib_shift = 2, + .match_id_mask = 0xff, + .ids = flash_table_ai, + .nr_part_ids = ARRAY_SIZE(flash_table_ai), + .desc = &descai, + .after_probe = sst_unlock, +}; - return -1; -} +const struct spi_flash_vendor_info spi_flash_sst_vi = { + .id = VENDOR_ID_SST, + .page_size_shift = 8, + .sector_size_kib_shift = 2, + .match_id_mask = 0xff, + .ids = flash_table_pp256, + .nr_part_ids = ARRAY_SIZE(flash_table_pp256), + .desc = &spi_flash_pp_0x20_sector_desc, + .after_probe = sst_unlock, +}; diff --git a/src/drivers/spi/stmicro.c b/src/drivers/spi/stmicro.c index 2f4e42a630..62755f4a01 100644 --- a/src/drivers/spi/stmicro.c +++ b/src/drivers/spi/stmicro.c @@ -64,102 +64,92 @@ #define STM_ID_N25Q128__1E 0xbb18 #define STM_ID_N25Q256__1E 0xbb19 -static const struct spi_flash_part_id flash_table_se[] = { +static const struct spi_flash_part_id flash_table_se32k[] = { { .id = STM_ID_M25P10, .name = "M25P10", .nr_sectors_shift = 2, - .sector_size_kib_shift = 5, }, +}; + +static const struct spi_flash_part_id flash_table_se64k[] = { { .id = STM_ID_M25P16, .name = "M25P16", .nr_sectors_shift = 5, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25P20, .name = "M25P20", .nr_sectors_shift = 2, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25P32, .name = "M25P32", .nr_sectors_shift = 6, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25P40, .name = "M25P40", .nr_sectors_shift = 3, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25P64, .name = "M25P64", .nr_sectors_shift = 7, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25P80, .name = "M25P80", .nr_sectors_shift = 4, - .sector_size_kib_shift = 6, - }, - { - .id = STM_ID_M25P128, - .name = "M25P128", - .nr_sectors_shift = 6, - .sector_size_kib_shift = 8, }, { .id = STM_ID_M25PX80, .name = "M25PX80", .nr_sectors_shift = 4, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25PX16, .name = "M25PX16", .nr_sectors_shift = 5, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25PX32, .name = "M25PX32", .nr_sectors_shift = 6, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25PX64, .name = "M25PX64", .nr_sectors_shift = 7, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25PE80, .name = "M25PE80", .nr_sectors_shift = 4, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25PE16, .name = "M25PE16", .nr_sectors_shift = 5, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25PE32, .name = "M25PE32", .nr_sectors_shift = 6, - .sector_size_kib_shift = 6, }, { .id = STM_ID_M25PE64, .name = "M25PE64", .nr_sectors_shift = 7, - .sector_size_kib_shift = 6, + }, +}; + +static const struct spi_flash_part_id flash_table_se256k[] = { + { + .id = STM_ID_M25P128, + .name = "M25P128", + .nr_sectors_shift = 6, }, }; @@ -168,71 +158,54 @@ static const struct spi_flash_part_id flash_table_sse[] = { .id = STM_ID_N25Q016__3E, .name = "N25Q016..3E", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = STM_ID_N25Q032__3E, .name = "N25Q032..3E", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = STM_ID_N25Q064__3E, .name = "N25Q064..3E", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, { .id = STM_ID_N25Q128__3E, .name = "N25Q128..3E", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, }, { .id = STM_ID_N25Q256__3E, .name = "N25Q256..3E", .nr_sectors_shift = 13, - .sector_size_kib_shift = 2, }, { .id = STM_ID_N25Q016__1E, .name = "N25Q016..1E", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = STM_ID_N25Q032__1E, .name = "N25Q032..1E", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = STM_ID_N25Q064__1E, .name = "N25Q064..1E", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, }, { .id = STM_ID_N25Q128__1E, .name = "N25Q128..1E", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, }, { .id = STM_ID_N25Q256__1E, .name = "N25Q256..1E", .nr_sectors_shift = 13, - .sector_size_kib_shift = 2, }, }; -static const struct spi_flash_ops spi_flash_ops = { - .read = spi_flash_cmd_read, - .write = spi_flash_cmd_write_page_program, - .erase = spi_flash_cmd_erase, - .status = spi_flash_cmd_status, -}; - int stmicro_release_deep_sleep_identify(const struct spi_slave *spi, u8 *idcode) { if (spi_flash_cmd(spi, CMD_M25PXX_RES, idcode, 4)) @@ -251,53 +224,42 @@ int stmicro_release_deep_sleep_identify(const struct spi_slave *spi, u8 *idcode) return 0; } -static int match_table(const struct spi_slave *spi, struct spi_flash *flash, u16 id, - const struct spi_flash_part_id *parts, size_t num_parts, - u8 erase_cmd) -{ - const struct spi_flash_part_id *params; - size_t i; - - for (i = 0; i < num_parts; i++) { - params = &parts[i]; - if (params->id == id) - break; - } - - if (i == num_parts) { - printk(BIOS_WARNING, "SF: Unsupported STMicro ID %04x\n", id); - return -1; - } - - memcpy(&flash->spi, spi, sizeof(*spi)); - flash->name = params->name; - flash->page_size = 256; - flash->sector_size = (1U << params->sector_size_kib_shift) * KiB; - flash->size = flash->sector_size * (1U << params->nr_sectors_shift); - flash->erase_cmd = erase_cmd; - flash->status_cmd = CMD_M25PXX_RDSR; - flash->pp_cmd = CMD_M25PXX_PP; - flash->wren_cmd = CMD_M25PXX_WREN; - - flash->ops = &spi_flash_ops; - - return 0; -} - -int spi_flash_probe_stmicro(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) -{ - u16 id = (idcode[1] << 8) | idcode[2]; +const struct spi_flash_vendor_info spi_flash_stmicro1_vi = { + .id = VENDOR_ID_STMICRO, + .page_size_shift = 8, + .sector_size_kib_shift = 5, + .match_id_mask = 0xffff, + .ids = flash_table_se32k, + .nr_part_ids = ARRAY_SIZE(flash_table_se32k), + .desc = &spi_flash_pp_0xd8_sector_desc, +}; - if (!match_table(spi, flash, id, flash_table_se, ARRAY_SIZE(flash_table_se), - CMD_M25PXX_SE)) { - return 0; - } +const struct spi_flash_vendor_info spi_flash_stmicro2_vi = { + .id = VENDOR_ID_STMICRO, + .page_size_shift = 8, + .sector_size_kib_shift = 6, + .match_id_mask = 0xffff, + .ids = flash_table_se64k, + .nr_part_ids = ARRAY_SIZE(flash_table_se64k), + .desc = &spi_flash_pp_0xd8_sector_desc, +}; - if (!match_table(spi, flash, id, flash_table_sse, ARRAY_SIZE(flash_table_sse), - CMD_M25PXX_SSE)) { - return 0; - } +const struct spi_flash_vendor_info spi_flash_stmicro3_vi = { + .id = VENDOR_ID_STMICRO, + .page_size_shift = 8, + .sector_size_kib_shift = 8, + .match_id_mask = 0xffff, + .ids = flash_table_se256k, + .nr_part_ids = ARRAY_SIZE(flash_table_se256k), + .desc = &spi_flash_pp_0xd8_sector_desc, +}; - return -1; -} +const struct spi_flash_vendor_info spi_flash_stmicro4_vi = { + .id = VENDOR_ID_STMICRO, + .page_size_shift = 8, + .sector_size_kib_shift = 2, + .match_id_mask = 0xffff, + .ids = flash_table_sse, + .nr_part_ids = ARRAY_SIZE(flash_table_sse), + .desc = &spi_flash_pp_0x20_sector_desc, +}; diff --git a/src/drivers/spi/winbond.c b/src/drivers/spi/winbond.c index 6766bb6e44..e85f59db03 100644 --- a/src/drivers/spi/winbond.c +++ b/src/drivers/spi/winbond.c @@ -84,60 +84,51 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x2014, .name = "W25P80", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, }, { .id = 0x2015, .name = "W25P16", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, }, { .id = 0x2016, .name = "W25P32", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, }, { .id = 0x3014, .name = "W25X80", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, { .id = 0x3015, .name = "W25X16", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, { .id = 0x3016, .name = "W25X32", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, { .id = 0x3017, .name = "W25X64", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, { .id = 0x4014, .name = "W25Q80_V", .nr_sectors_shift = 8, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, }, { .id = 0x4015, .name = "W25Q16_V", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 16, .bp_bits = 3, @@ -146,7 +137,6 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x6015, .name = "W25Q16DW", .nr_sectors_shift = 9, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 16, .bp_bits = 3, @@ -155,7 +145,6 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x4016, .name = "W25Q32_V", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 16, .bp_bits = 3, @@ -164,7 +153,6 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x6016, .name = "W25Q32DW", .nr_sectors_shift = 10, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 16, .bp_bits = 3, @@ -173,7 +161,6 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x4017, .name = "W25Q64_V", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 17, .bp_bits = 3, @@ -182,7 +169,6 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x6017, .name = "W25Q64DW", .nr_sectors_shift = 11, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 17, .bp_bits = 3, @@ -191,7 +177,6 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x4018, .name = "W25Q128_V", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 18, .bp_bits = 3, @@ -200,7 +185,6 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x6018, .name = "W25Q128FW", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 18, .bp_bits = 3, @@ -209,7 +193,6 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x7018, .name = "W25Q128J", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 18, .bp_bits = 3, @@ -218,7 +201,6 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x8018, .name = "W25Q128JW", .nr_sectors_shift = 12, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 18, .bp_bits = 3, @@ -227,7 +209,6 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x4019, .name = "W25Q256_V", .nr_sectors_shift = 13, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 16, .bp_bits = 4, @@ -236,7 +217,6 @@ static const struct spi_flash_part_id flash_table[] = { .id = 0x7019, .name = "W25Q256J", .nr_sectors_shift = 13, - .sector_size_kib_shift = 2, .fast_read_dual_output_support = 1, .protection_granularity_shift = 16, .bp_bits = 4, @@ -266,17 +246,6 @@ static void winbond_bpbits_to_region(const size_t granularity, out->size = protected_size; } -static const struct spi_flash_part_id *lookup_part(u16 id) -{ - size_t i; - - for (i = 0; i < ARRAY_SIZE(flash_table); i++) { - if (flash_table[i].id == id) - return &flash_table[i]; - } - - return NULL; -} /* * Available on all devices. * Read block protect bits from Status/Status2 Reg. @@ -296,7 +265,7 @@ static int winbond_get_write_protection(const struct spi_flash *flash, u8 bp, tb; int ret; - params = lookup_part(flash->model); + params = flash->part; if (!params) return -1; @@ -479,7 +448,7 @@ winbond_set_write_protection(const struct spi_flash *flash, if (region_offset(region) != 0 && region_end(region) != flash->size) return -1; - params = lookup_part(flash->model); + params = flash->part; if (!params) return -1; @@ -573,52 +542,18 @@ winbond_set_write_protection(const struct spi_flash *flash, return ret; } -static const struct spi_flash_ops spi_flash_ops = { - .read = spi_flash_cmd_read, - .write = spi_flash_cmd_write_page_program, - .erase = spi_flash_cmd_erase, - .status = spi_flash_cmd_status, -}; - static const struct spi_flash_protection_ops spi_flash_protection_ops = { .get_write = winbond_get_write_protection, .set_write = winbond_set_write_protection, }; -int spi_flash_probe_winbond(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) -{ - const struct spi_flash_part_id *params; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(flash_table); i++) { - params = &flash_table[i]; - if (params->id == ((idcode[1] << 8) | idcode[2])) - break; - } - - if (i == ARRAY_SIZE(flash_table)) { - printk(BIOS_WARNING, "SF: Unsupported Winbond ID %02x%02x\n", - idcode[1], idcode[2]); - return -1; - } - - memcpy(&flash->spi, spi, sizeof(*spi)); - flash->name = params->name; - - /* Params are in power-of-two. */ - flash->page_size = 256; - flash->sector_size = (1U << params->sector_size_kib_shift) * KiB; - flash->size = flash->sector_size * (1U << params->nr_sectors_shift); - flash->erase_cmd = CMD_W25_SE; - flash->status_cmd = CMD_W25_RDSR; - flash->pp_cmd = CMD_W25_PP; - flash->wren_cmd = CMD_W25_WREN; - - flash->flags.dual_spi = params->fast_read_dual_output_support; - - flash->ops = &spi_flash_ops; - flash->prot_ops = &spi_flash_protection_ops; - - return 0; -} +const struct spi_flash_vendor_info spi_flash_winbond_vi = { + .id = VENDOR_ID_WINBOND, + .page_size_shift = 8, + .sector_size_kib_shift = 2, + .match_id_mask = 0xffff, + .ids = flash_table, + .nr_part_ids = ARRAY_SIZE(flash_table), + .desc = &spi_flash_pp_0x20_sector_desc, + .prot_ops = &spi_flash_protection_ops, +}; diff --git a/src/include/spi_flash.h b/src/include/spi_flash.h index ffa66db561..9acff3b104 100644 --- a/src/include/spi_flash.h +++ b/src/include/spi_flash.h @@ -91,6 +91,8 @@ struct spi_flash_protection_ops { }; +struct spi_flash_part_id; + struct spi_flash { struct spi_slave spi; u8 vendor; @@ -113,6 +115,7 @@ struct spi_flash { const struct spi_flash_ops *ops; /* If !NULL all protection callbacks exist. */ const struct spi_flash_protection_ops *prot_ops; + const struct spi_flash_part_id *part; }; void lb_spi_flash(struct lb_header *header); |