diff options
Diffstat (limited to 'src/drivers/spi/spansion.c')
-rw-r--r-- | src/drivers/spi/spansion.c | 218 |
1 files changed, 75 insertions, 143 deletions
diff --git a/src/drivers/spi/spansion.c b/src/drivers/spi/spansion.c index 3d2f39d6df..b4fca4f8b3 100644 --- a/src/drivers/spi/spansion.c +++ b/src/drivers/spi/spansion.c @@ -34,7 +34,6 @@ #define CMD_S25FLXX_DP 0xb9 /* Deep Power-down */ #define CMD_S25FLXX_RES 0xab /* Release from DP, and Read Signature */ -#define SPSN_MANUFACTURER_ID_S25FL_K 0x01 #define SPSN_ID_S25FL008A 0x0213 #define SPSN_ID_S25FL016A 0x0214 #define SPSN_ID_S25FL032A 0x0215 @@ -50,171 +49,87 @@ #define SPSN_EXT_ID_S25FL032P 0x4d00 #define SPSN_EXT_ID_S25FLXXS_64KB 0x4d01 -struct spansion_spi_flash_params { - u8 idcode0; - u16 idcode1; - u16 idcode2; - int (*identify) (const struct spansion_spi_flash_params *params, - u8 *idcode); - u16 page_size; - u16 pages_per_sector; - u16 nr_sectors; - const char *name; -}; - -/* - * returns non-zero if the given idcode matches the ID of the chip. this is for - * chips which use 2nd, 3rd, 4th, and 5th byte. - */ -static int identify_2345(const struct spansion_spi_flash_params *params, - u8 *idcode) -{ - u16 jedec = idcode[1] << 8 | idcode[2]; - u16 ext_jedec = idcode[3] << 8 | idcode[4]; - return (params->idcode1 == jedec) && (params->idcode2 == ext_jedec); -} - -/* - * returns non-zero if the given idcode matches the ID of the chip. this is for - * chips which use 1st, 2nd, and 3rd byte. - */ -static int identify_123(const struct spansion_spi_flash_params *params, - u8 *idcode) -{ - u16 jedec = idcode[1] << 8 | idcode[2]; - return (params->idcode0 == idcode[0]) && (params->idcode1 == jedec); -} - -static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { +static const struct spi_flash_part_id flash_table_ext[] = { { - .idcode0 = 0, - .idcode1 = SPSN_ID_S25FL008A, - .idcode2 = 0, - .identify = identify_2345, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 16, + .id = SPSN_ID_S25FL008A, .name = "S25FL008A", + .nr_sectors_shift = 4, + .sector_size_kib_shift = 6, }, { - .idcode0 = 0, - .idcode1 = SPSN_ID_S25FL016A, - .idcode2 = 0, - .identify = identify_2345, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 32, + .id = SPSN_ID_S25FL016A, .name = "S25FL016A", + .nr_sectors_shift = 5, + .sector_size_kib_shift = 6, }, { - .idcode0 = 0, - .idcode1 = SPSN_ID_S25FL032A, - .idcode2 = 0, - .identify = identify_2345, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 64, + .id = SPSN_ID_S25FL032A, .name = "S25FL032A", + .nr_sectors_shift = 6, + .sector_size_kib_shift = 6, }, { - .idcode0 = 0, - .idcode1 = SPSN_ID_S25FL064A, - .idcode2 = 0, - .identify = identify_2345, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 128, + .id = SPSN_ID_S25FL064A, .name = "S25FL064A", + .nr_sectors_shift = 7, + .sector_size_kib_shift = 6, }, { - .idcode0 = 0, - .idcode1 = SPSN_ID_S25FL128P, - .idcode2 = SPSN_EXT_ID_S25FL128P_64KB, - .identify = identify_2345, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 256, + .id = (SPSN_EXT_ID_S25FL128P_64KB << 16) | SPSN_ID_S25FL128P, .name = "S25FL128P_64K", + .nr_sectors_shift = 8, + .sector_size_kib_shift = 6, }, { - .idcode0 = 0, - .idcode1 = SPSN_ID_S25FL128P, - .idcode2 = SPSN_EXT_ID_S25FL128P_256KB, - .identify = identify_2345, - .page_size = 256, - .pages_per_sector = 1024, - .nr_sectors = 64, + .id = (SPSN_EXT_ID_S25FL128P_256KB << 16) | SPSN_ID_S25FL128P, .name = "S25FL128P_256K", + .nr_sectors_shift = 6, + .sector_size_kib_shift = 8, }, { - .idcode0 = 0, - .idcode1 = SPSN_ID_S25FL128S, - .idcode2 = SPSN_EXT_ID_S25FLXXS_64KB, - .identify = identify_2345, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 512, + .id = (SPSN_EXT_ID_S25FLXXS_64KB << 16) | SPSN_ID_S25FL128S, .name = "S25FL128S_256K", + .nr_sectors_shift = 9, + .sector_size_kib_shift = 6, }, { - .idcode0 = 0, - .idcode1 = SPSN_ID_S25FL032A, - .idcode2 = SPSN_EXT_ID_S25FL032P, - .identify = identify_2345, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 64, + .id = (SPSN_EXT_ID_S25FL032P << 16) | SPSN_ID_S25FL032A, .name = "S25FL032P", + .nr_sectors_shift = 6, + .sector_size_kib_shift = 6, }, { - .idcode0 = 0, - .idcode1 = SPSN_ID_S25FL128P, - .idcode2 = SPSN_EXT_ID_S25FLXXS_64KB, - .identify = identify_2345, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 256, + .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[] = { { - .idcode0 = SPSN_MANUFACTURER_ID_S25FL_K, - .idcode1 = SPSN_ID_S25FL208K, - .idcode2 = 0, - .identify = identify_123, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 16, + .id = SPSN_ID_S25FL208K, .name = "S25FL208K", + .nr_sectors_shift = 4, + .sector_size_kib_shift = 6, }, { - .idcode0 = SPSN_MANUFACTURER_ID_S25FL_K, - .idcode1 = SPSN_ID_S25FL116K, - .idcode2 = 0, - .identify = identify_123, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 32, + .id = SPSN_ID_S25FL116K, .name = "S25FL116K_16M", + .nr_sectors_shift = 5, + .sector_size_kib_shift = 6, }, { - .idcode0 = SPSN_MANUFACTURER_ID_S25FL_K, - .idcode1 = SPSN_ID_S25FL132K, - .idcode2 = 0, - .identify = identify_123, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 64, + .id = SPSN_ID_S25FL132K, .name = "S25FL132K", + .nr_sectors_shift = 6, + .sector_size_kib_shift = 6, }, { - .idcode0 = SPSN_MANUFACTURER_ID_S25FL_K, - .idcode1 = SPSN_ID_S25FL164K, - .idcode2 = 0, - .identify = identify_123, - .page_size = 256, - .pages_per_sector = 256, - .nr_sectors = 128, + .id = SPSN_ID_S25FL164K, .name = "S25FL164K", + .nr_sectors_shift = 7, + .sector_size_kib_shift = 6, }, }; @@ -225,30 +140,28 @@ static const struct spi_flash_ops spi_flash_ops = { .status = spi_flash_cmd_status, }; -int spi_flash_probe_spansion(const struct spi_slave *spi, u8 *idcode, - struct spi_flash *flash) + +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 spansion_spi_flash_params *params; + const struct spi_flash_part_id *params = NULL; unsigned int i; - for (i = 0; i < ARRAY_SIZE(spansion_spi_flash_table); i++) { - params = &spansion_spi_flash_table[i]; - if (params->identify(params, idcode)) - break; + for (i = 0; i < num_parts; i++) { + if (parts[i].id != id) + continue; + params = &parts[i]; + break; } - if (i == ARRAY_SIZE(spansion_spi_flash_table)) { - printk(BIOS_WARNING, - "SF: Unsupported SPANSION ID %02x %02x %02x %02x %02x\n", - idcode[0], idcode[1], idcode[2], idcode[3], idcode[4]); + if (params == NULL) return -1; - } memcpy(&flash->spi, spi, sizeof(*spi)); flash->name = params->name; - flash->page_size = params->page_size; - flash->sector_size = params->page_size * params->pages_per_sector; - flash->size = flash->sector_size * params->nr_sectors; + 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; @@ -258,3 +171,22 @@ int spi_flash_probe_spansion(const struct spi_slave *spi, u8 *idcode, 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; +} |