diff options
Diffstat (limited to 'drivers/mtd/spi')
-rw-r--r-- | drivers/mtd/spi/sandbox.c | 114 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_params.c | 4 | ||||
-rw-r--r-- | drivers/mtd/spi/spi_spl_load.c | 6 |
3 files changed, 46 insertions, 78 deletions
diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c index a62ef4c..98e0a34 100644 --- a/drivers/mtd/spi/sandbox.c +++ b/drivers/mtd/spi/sandbox.c @@ -51,46 +51,7 @@ static const char *sandbox_sf_state_name(enum sandbox_sf_state state) /* Assume all SPI flashes have 3 byte addresses since they do atm */ #define SF_ADDR_LEN 3 -struct sandbox_spi_flash_erase_commands { - u8 cmd; - u32 size; -}; -#define IDCODE_LEN 5 -#define MAX_ERASE_CMDS 3 -struct sandbox_spi_flash_data { - const char *name; - u8 idcode[IDCODE_LEN]; - u32 size; - const struct sandbox_spi_flash_erase_commands - erase_cmds[MAX_ERASE_CMDS]; -}; - -/* Structure describing all the flashes we know how to emulate */ -static const struct sandbox_spi_flash_data sandbox_sf_flashes[] = { - { - "M25P16", { 0x20, 0x20, 0x15 }, (2 << 20), - { /* erase commands */ - { 0xd8, (64 << 10), }, /* sector */ - { 0xc7, (2 << 20), }, /* bulk */ - }, - }, - { - "W25Q32", { 0xef, 0x40, 0x16 }, (4 << 20), - { /* erase commands */ - { 0x20, (4 << 10), }, /* 4KB */ - { 0xd8, (64 << 10), }, /* sector */ - { 0xc7, (4 << 20), }, /* bulk */ - }, - }, - { - "W25Q128", { 0xef, 0x40, 0x18 }, (16 << 20), - { /* erase commands */ - { 0x20, (4 << 10), }, /* 4KB */ - { 0xd8, (64 << 10), }, /* sector */ - { 0xc7, (16 << 20), }, /* bulk */ - }, - }, -}; +#define IDCODE_LEN 3 /* Used to quickly bulk erase backing store */ static u8 sandbox_sf_0xff[0x1000]; @@ -109,7 +70,8 @@ struct sandbox_spi_flash { */ enum sandbox_sf_state state; uint cmd; - const void *cmd_data; + /* Erase size of current erase command */ + uint erase_size; /* Current position in the flash; used when reading/writing/etc... */ uint off; /* How many address bytes we've consumed */ @@ -117,7 +79,7 @@ struct sandbox_spi_flash { /* The current flash status (see STAT_XXX defines above) */ u16 status; /* Data describing the flash we're emulating */ - const struct sandbox_spi_flash_data *data; + const struct spi_flash_params *data; /* The file on disk to serv up data from */ int fd; }; @@ -127,8 +89,8 @@ static int sandbox_sf_setup(void **priv, const char *spec) /* spec = idcode:file */ struct sandbox_spi_flash *sbsf; const char *file; - size_t i, len, idname_len; - const struct sandbox_spi_flash_data *data; + size_t len, idname_len; + const struct spi_flash_params *data; file = strchr(spec, ':'); if (!file) { @@ -138,15 +100,14 @@ static int sandbox_sf_setup(void **priv, const char *spec) idname_len = file - spec; ++file; - for (i = 0; i < ARRAY_SIZE(sandbox_sf_flashes); ++i) { - data = &sandbox_sf_flashes[i]; + for (data = spi_flash_params_table; data->name; data++) { len = strlen(data->name); if (idname_len != len) continue; if (!memcmp(spec, data->name, len)) break; } - if (i == ARRAY_SIZE(sandbox_sf_flashes)) { + if (!data->name) { printf("sandbox_sf: unknown flash '%*s'\n", (int)idname_len, spec); goto error; @@ -223,7 +184,6 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, sbsf->pad_addr_bytes = 1; case CMD_READ_ARRAY_SLOW: case CMD_PAGE_PROGRAM: - state_addr: sbsf->state = SF_ADDR; break; case CMD_WRITE_DISABLE: @@ -241,24 +201,25 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, sbsf->status |= STAT_WEL; break; default: { - size_t i; - - /* handle erase commands first */ - for (i = 0; i < MAX_ERASE_CMDS; ++i) { - const struct sandbox_spi_flash_erase_commands * - erase_cmd = &sbsf->data->erase_cmds[i]; - - if (erase_cmd->cmd == 0x00) - continue; - if (sbsf->cmd != erase_cmd->cmd) - continue; - - sbsf->cmd_data = erase_cmd; - goto state_addr; + int flags = sbsf->data->flags; + + /* we only support erase here */ + if (sbsf->cmd == CMD_ERASE_CHIP) { + sbsf->erase_size = sbsf->data->sector_size * + sbsf->data->nr_sectors; + } else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) { + sbsf->erase_size = 4 << 10; + } else if (sbsf->cmd == CMD_ERASE_32K && (flags & SECT_32K)) { + sbsf->erase_size = 32 << 10; + } else if (sbsf->cmd == CMD_ERASE_64K && + !(flags & (SECT_4K | SECT_32K))) { + sbsf->erase_size = 64 << 10; + } else { + debug(" cmd unknown: %#x\n", sbsf->cmd); + return 1; } - - debug(" cmd unknown: %#x\n", sbsf->cmd); - return 1; + sbsf->state = SF_ADDR; + break; } } @@ -309,11 +270,14 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx, u8 id; debug(" id: off:%u tx:", sbsf->off); - if (sbsf->off < IDCODE_LEN) - id = sbsf->data->idcode[sbsf->off]; - else + if (sbsf->off < IDCODE_LEN) { + /* Extract correct byte from ID 0x00aabbcc */ + id = sbsf->data->jedec >> + (8 * (IDCODE_LEN - 1 - sbsf->off)); + } else { id = 0; - debug("%02x\n", id); + } + debug("%d %02x\n", sbsf->off, id); tx[pos++] = id; ++sbsf->off; break; @@ -406,24 +370,22 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx, break; case SF_ERASE: case_sf_erase: { - const struct sandbox_spi_flash_erase_commands * - erase_cmd = sbsf->cmd_data; - if (!(sbsf->status & STAT_WEL)) { puts("sandbox_sf: write enable not set before erase\n"); goto done; } /* verify address is aligned */ - if (sbsf->off & (erase_cmd->size - 1)) { + if (sbsf->off & (sbsf->erase_size - 1)) { debug(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", - erase_cmd->cmd, erase_cmd->size, + sbsf->cmd, sbsf->erase_size, sbsf->off); sbsf->status &= ~STAT_WEL; goto done; } - debug(" sector erase addr: %u\n", sbsf->off); + debug(" sector erase addr: %u, size: %u\n", sbsf->off, + sbsf->erase_size); cnt = bytes - pos; sandbox_spi_tristate(&tx[pos], cnt); @@ -433,7 +395,7 @@ static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx, * TODO(vapier@gentoo.org): latch WIP in status, and * delay before clearing it ? */ - ret = sandbox_erase_part(sbsf, erase_cmd->size); + ret = sandbox_erase_part(sbsf, sbsf->erase_size); sbsf->status &= ~STAT_WEL; if (ret) { debug("sandbox_sf: Erase failed\n"); diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c index ac886fd..453edf0 100644 --- a/drivers/mtd/spi/sf_params.c +++ b/drivers/mtd/spi/sf_params.c @@ -68,9 +68,12 @@ const struct spi_flash_params spi_flash_params_table[] = { {"M25P40", 0x202013, 0x0, 64 * 1024, 8, 0, 0}, {"M25P80", 0x202014, 0x0, 64 * 1024, 16, 0, 0}, {"M25P16", 0x202015, 0x0, 64 * 1024, 32, 0, 0}, + {"M25PE16", 0x208015, 0x1000, 64 * 1024, 32, 0, 0}, + {"M25PX16", 0x207115, 0x1000, 64 * 1024, 32, RD_EXTN, 0}, {"M25P32", 0x202016, 0x0, 64 * 1024, 64, 0, 0}, {"M25P64", 0x202017, 0x0, 64 * 1024, 128, 0, 0}, {"M25P128", 0x202018, 0x0, 256 * 1024, 64, 0, 0}, + {"M25PX64", 0x207117, 0x0, 64 * 1024, 128, 0, SECT_4K}, {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, @@ -116,6 +119,7 @@ const struct spi_flash_params spi_flash_params_table[] = { {"W25Q64DW", 0xef6017, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, {"W25Q128FW", 0xef6018, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP | SECT_4K}, #endif + {}, /* Empty entry to terminate the list */ /* * Note: * Below paired flash devices has similar spi_flash params. diff --git a/drivers/mtd/spi/spi_spl_load.c b/drivers/mtd/spi/spi_spl_load.c index 1954b7e..59cca0f 100644 --- a/drivers/mtd/spi/spi_spl_load.c +++ b/drivers/mtd/spi/spi_spl_load.c @@ -56,8 +56,10 @@ void spl_spi_load_image(void) * Load U-Boot image from SPI flash into RAM */ - flash = spi_flash_probe(CONFIG_SPL_SPI_BUS, CONFIG_SPL_SPI_CS, - CONFIG_SF_DEFAULT_SPEED, SPI_MODE_3); + flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, + CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, + CONFIG_SF_DEFAULT_MODE); if (!flash) { puts("SPI probe failed.\n"); hang(); |