summaryrefslogtreecommitdiff
path: root/src/drivers/spi/spansion.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/spi/spansion.c')
-rw-r--r--src/drivers/spi/spansion.c218
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;
+}