summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/spi/stmicro.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/src/drivers/spi/stmicro.c b/src/drivers/spi/stmicro.c
index 40bce31983..fda6124ac0 100644
--- a/src/drivers/spi/stmicro.c
+++ b/src/drivers/spi/stmicro.c
@@ -40,6 +40,7 @@
#define CMD_M25PXX_READ 0x03 /* Read Data Bytes */
#define CMD_M25PXX_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
#define CMD_M25PXX_PP 0x02 /* Page Program */
+#define CMD_M25PXX_SSE 0x20 /* Subsector Erase */
#define CMD_M25PXX_SE 0xd8 /* Sector Erase */
#define CMD_M25PXX_BE 0xc7 /* Bulk Erase */
#define CMD_M25PXX_DP 0xb9 /* Deep Power-down */
@@ -53,9 +54,17 @@
#define STM_ID_M25P64 0x17
#define STM_ID_M25P80 0x14
#define STM_ID_M25P128 0x18
+#define STM_ID_USE_ALT_ID 0xFF
+/* Some SPI flash share the same .idcode1 (idcode[2]). To handle this without
+ * (possibly) breaking existing implementations, add the new device at the top
+ * of the flash table array and set its .idcode1 = STM_ID_USE_ALT_ID. The .id
+ * is then (idcode[1] << 8 | idcode[2]).
+ */
struct stmicro_spi_flash_params {
u8 idcode1;
+ u8 op_erase;
+ u16 id;
u16 page_size;
u16 pages_per_sector;
u16 nr_sectors;
@@ -76,7 +85,17 @@ static inline struct stmicro_spi_flash *to_stmicro_spi_flash(struct spi_flash
static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
{
+ .idcode1 = STM_ID_USE_ALT_ID,
+ .id = 0xbb18,
+ .op_erase = CMD_M25PXX_SSE,
+ .page_size = 256,
+ .pages_per_sector = 16,
+ .nr_sectors = 4096,
+ .name = "N25Q128",
+ },
+ {
.idcode1 = STM_ID_M25P10,
+ .op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 128,
.nr_sectors = 4,
@@ -84,6 +103,7 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
},
{
.idcode1 = STM_ID_M25P16,
+ .op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 32,
@@ -91,6 +111,7 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
},
{
.idcode1 = STM_ID_M25P20,
+ .op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 4,
@@ -98,6 +119,7 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
},
{
.idcode1 = STM_ID_M25P32,
+ .op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 64,
@@ -105,6 +127,7 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
},
{
.idcode1 = STM_ID_M25P40,
+ .op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 8,
@@ -112,6 +135,7 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
},
{
.idcode1 = STM_ID_M25P64,
+ .op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 128,
@@ -119,6 +143,7 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
},
{
.idcode1 = STM_ID_M25P80,
+ .op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 256,
.nr_sectors = 16,
@@ -126,6 +151,7 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
},
{
.idcode1 = STM_ID_M25P128,
+ .op_erase = CMD_M25PXX_SE,
.page_size = 256,
.pages_per_sector = 1024,
.nr_sectors = 64,
@@ -202,7 +228,9 @@ out:
static int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len)
{
- return spi_flash_cmd_erase(flash, CMD_M25PXX_SE, offset, 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)
@@ -226,7 +254,12 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
for (i = 0; i < ARRAY_SIZE(stmicro_spi_flash_table); i++) {
params = &stmicro_spi_flash_table[i];
- if (params->idcode1 == idcode[2]) {
+ if (params->idcode1 == STM_ID_USE_ALT_ID) {
+ if (params->id == ((idcode[1] << 8) | idcode[2])) {
+ break;
+ }
+ }
+ else if (params->idcode1 == idcode[2]) {
break;
}
}