diff options
-rw-r--r-- | drivers/mtd/spi/sf_internal.h | 11 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_ops.c | 74 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_params.c | 1 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_probe.c | 14 |
4 files changed, 98 insertions, 2 deletions
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 785f7a9..8987ad9 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -43,8 +43,12 @@ enum { SST_BP = 1 << 3, SST_WP = 1 << 4, WR_QPP = 1 << 5, + SECT_2K = 1 << 6, }; +#define SPI_FLASH_PAGE_256 (1 << 0) +#define SPI_FLASH_PAGE_264 (1 << 1) + #define SST_WR (SST_BP | SST_WP) #define SPI_FLASH_3B_ADDR_LEN 3 @@ -58,6 +62,7 @@ enum { #define SPI_FLASH_CFI_MFR_WINBOND 0xef /* Erase commands */ +#define CMD_ERASE_2K 0x50 #define CMD_ERASE_4K 0x20 #define CMD_ERASE_32K 0x52 #define CMD_ERASE_CHIP 0xc7 @@ -67,7 +72,11 @@ enum { #define CMD_WRITE_STATUS 0x01 #define CMD_PAGE_PROGRAM 0x02 #define CMD_WRITE_DISABLE 0x04 -#define CMD_READ_STATUS 0x05 +#ifdef CONFIG_SPI_FLASH_ATMEL +#define CMD_READ_STATUS 0xd7 +#else +#define CMD_READ_STATUS 0x05 +#endif #define CMD_QUAD_PAGE_PROGRAM 0x32 #define CMD_READ_STATUS1 0x35 #define CMD_WRITE_ENABLE 0x06 diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 34bc54e..0e75331 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -55,6 +55,75 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws) return 0; } +#if defined(CONFIG_SPI_FLASH_ATMEL) +/* + * For the AT45DB021E, there are an extra eight bytes + * of memory in each page for a total of an extra 8KB + * (64-Kbits) of user-accessible memory. + * In order to be compatible with spi framework, we use 256bytes. + */ + +int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc) +{ + u8 data[3]; + u8 cmd; + int ret; + + ret = spi_flash_cmd_read_status(flash, &data[0]); + if (ret < 0) + return ret; + + /* + * PAGE SIZE Page Size, bit 0. + * 0 Device is configured for standard DataFlash page size (264 bytes). + * 1 Device is configured for “power of 2” binary page size (256 bytes). + */ + if (wc == SPI_FLASH_PAGE_256) { + /* Already 256? */ + if (data[0] & 1) + return 0; + } else if (wc == SPI_FLASH_PAGE_264) { + /* Already 264? */ + if ((data[0] & 1) == 0) + return 0; + } else { + debug("Unsupport page configuration!\n"); + return -1; + } + + /* + * 3D, 2A, 80, A6 command seq will configure flash page size 256. + * 3D, 2A, 80, A7 command seq will configure flash page size 264. + */ + cmd = 0x3D; + if (wc == SPI_FLASH_PAGE_256) + data[2] = 0xA6; + else if (wc == SPI_FLASH_PAGE_264) + data[2] = 0xA7; + data[1] = 0x80; + data[0] = 0x2A; + ret = spi_flash_write_common(flash, &cmd, 1, data, 3); + if (ret) { + debug("SF: fail to write config register\n"); + return ret; + } + + /* Check again */ + ret = spi_flash_cmd_read_status(flash, &data[0]); + if (ret < 0) + return ret; + + /* Means failed to configure page size */ + if (((wc == SPI_FLASH_PAGE_256) && ((data[0] & 1) == 0)) || + ((wc == SPI_FLASH_PAGE_264) && (data[0] & 1))) { + debug("Failed to configure page size!\n"); + return -1; + } + + return 0; +} +#endif + #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc) { @@ -170,6 +239,11 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) check_status = poll_bit; } +#ifdef CONFIG_SPI_FLASH_ATMEL + poll_bit = STATUS_PEC; + check_status = 1 << 7; +#endif + #ifdef CONFIG_SF_DUAL_FLASH if (spi->flags & SPI_XFER_U_PAGE) flags |= SPI_XFER_U_PAGE; diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c index c12e8c6..a5cdf11 100644 --- a/drivers/mtd/spi/sf_params.c +++ b/drivers/mtd/spi/sf_params.c @@ -16,6 +16,7 @@ const struct spi_flash_params spi_flash_params_table[] = { #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, RD_NORM, SECT_4K}, + {"AT45DB021E", 0x1f2300, 0x100, 32 * 1024, 8, 0, SECT_2K}, {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K}, diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 689af3a..2ba1500 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -172,7 +172,10 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, #endif /* Compute erase sector and command */ - if (params->flags & SECT_4K) { + if (params->flags & SECT_2K) { + flash->erase_cmd = CMD_ERASE_2K; + flash->erase_size = 2048 << flash->shift; + } else if (params->flags & SECT_4K) { flash->erase_cmd = CMD_ERASE_4K; flash->erase_size = 4096 << flash->shift; } else if (params->flags & SECT_32K) { @@ -396,6 +399,15 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash) if (spi_enable_wp_pin(flash)) puts("Enable WP pin failed\n"); + +#if defined(CONFIG_SPI_FLASH_ATMEL) + /* + * Default configure the page size to 256bytes to + * be compatible with the mtd/spi framework + */ + spi_flash_cmd_write_config(flash, SPI_FLASH_PAGE_256); +#endif + /* Release spi bus */ spi_release_bus(spi); |