summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/spi/sf_internal.h11
-rw-r--r--drivers/mtd/spi/sf_ops.c74
-rw-r--r--drivers/mtd/spi/sf_params.c1
-rw-r--r--drivers/mtd/spi/sf_probe.c14
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);