Skip to content
Snippets Groups Projects
Commit eb179907 authored by Troy Kisky's avatar Troy Kisky
Browse files

mtd: spi: fix at45db041d

parent ec4d2822
No related branches found
No related tags found
No related merge requests found
...@@ -38,6 +38,7 @@ enum spi_nor_option_flags { ...@@ -38,6 +38,7 @@ enum spi_nor_option_flags {
#define SPI_FLASH_CFI_MFR_ATMEL 0x1f #define SPI_FLASH_CFI_MFR_ATMEL 0x1f
/* Erase commands */ /* Erase commands */
#define CMD_ERASE_2K 0x50
#define CMD_ERASE_4K 0x20 #define CMD_ERASE_4K 0x20
#define CMD_ERASE_CHIP 0xc7 #define CMD_ERASE_CHIP 0xc7
#define CMD_ERASE_64K 0xd8 #define CMD_ERASE_64K 0xd8
...@@ -45,6 +46,10 @@ enum spi_nor_option_flags { ...@@ -45,6 +46,10 @@ enum spi_nor_option_flags {
/* Write commands */ /* Write commands */
#define CMD_WRITE_STATUS 0x01 #define CMD_WRITE_STATUS 0x01
#define CMD_PAGE_PROGRAM 0x02 #define CMD_PAGE_PROGRAM 0x02
/* 0x84 followed by 3byte offset into buffer */
#define CMD_BUFFER1_WRITE 0x84
/* 0x88 followed by 2 byte page #, and 1 dummy byte */
#define CMD_BUFFER1_PROGRAM 0x88
#define CMD_WRITE_DISABLE 0x04 #define CMD_WRITE_DISABLE 0x04
#define CMD_WRITE_ENABLE 0x06 #define CMD_WRITE_ENABLE 0x06
#define CMD_QUAD_PAGE_PROGRAM 0x32 #define CMD_QUAD_PAGE_PROGRAM 0x32
...@@ -59,6 +64,7 @@ enum spi_nor_option_flags { ...@@ -59,6 +64,7 @@ enum spi_nor_option_flags {
#define CMD_READ_ID 0x9f #define CMD_READ_ID 0x9f
#define CMD_READ_STATUS 0x05 #define CMD_READ_STATUS 0x05
#define CMD_READ_STATUS1 0x35 #define CMD_READ_STATUS1 0x35
#define CMD_READ_STATUS2 0xd7
#define CMD_READ_CONFIG 0x35 #define CMD_READ_CONFIG 0x35
#define CMD_FLAG_STATUS 0x70 #define CMD_FLAG_STATUS 0x70
...@@ -75,6 +81,7 @@ enum spi_nor_option_flags { ...@@ -75,6 +81,7 @@ enum spi_nor_option_flags {
#define STATUS_QEB_WINSPAN BIT(1) #define STATUS_QEB_WINSPAN BIT(1)
#define STATUS_QEB_MXIC BIT(6) #define STATUS_QEB_MXIC BIT(6)
#define STATUS_PEC BIT(7) #define STATUS_PEC BIT(7)
#define STATUS2_READY BIT(7)
#define SR_BP0 BIT(2) /* Block protect 0 */ #define SR_BP0 BIT(2) /* Block protect 0 */
#define SR_BP1 BIT(3) /* Block protect 1 */ #define SR_BP1 BIT(3) /* Block protect 1 */
#define SR_BP2 BIT(4) /* Block protect 2 */ #define SR_BP2 BIT(4) /* Block protect 2 */
...@@ -143,6 +150,8 @@ struct spi_flash_info { ...@@ -143,6 +150,8 @@ struct spi_flash_info {
#define RD_DUAL BIT(5) /* use Dual Read */ #define RD_DUAL BIT(5) /* use Dual Read */
#define RD_QUADIO BIT(6) /* use Quad IO Read */ #define RD_QUADIO BIT(6) /* use Quad IO Read */
#define RD_DUALIO BIT(7) /* use Dual IO Read */ #define RD_DUALIO BIT(7) /* use Dual IO Read */
#define ATMEL_REGS BIT(8)
#define SECT_2K BIT(9) /* CMD_ERASE_2K works */
#define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) #define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO)
}; };
......
...@@ -31,15 +31,12 @@ static void spi_flash_addr(u32 addr, u8 *cmd) ...@@ -31,15 +31,12 @@ static void spi_flash_addr(u32 addr, u8 *cmd)
static int read_sr(struct spi_flash *flash, u8 *rs) static int read_sr(struct spi_flash *flash, u8 *rs)
{ {
int ret; int ret;
u8 cmd;
cmd = CMD_READ_STATUS; ret = spi_flash_read_common(flash, &flash->status_cmd, 1, rs, 1);
ret = spi_flash_read_common(flash, &cmd, 1, rs, 1);
if (ret < 0) { if (ret < 0) {
debug("SF: fail to read status register\n"); debug("SF: fail to read status register\n");
return ret; return ret;
} }
return 0; return 0;
} }
...@@ -215,8 +212,7 @@ static int spi_flash_sr_ready(struct spi_flash *flash) ...@@ -215,8 +212,7 @@ static int spi_flash_sr_ready(struct spi_flash *flash)
ret = read_sr(flash, &sr); ret = read_sr(flash, &sr);
if (ret < 0) if (ret < 0)
return ret; return ret;
return (sr & flash->status_ready_mask) == flash->status_ready_level;
return !(sr & STATUS_WIP);
} }
static int spi_flash_fsr_ready(struct spi_flash *flash) static int spi_flash_fsr_ready(struct spi_flash *flash)
...@@ -428,6 +424,50 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, ...@@ -428,6 +424,50 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
return ret; return ret;
} }
#ifdef CONFIG_SPI_FLASH_ATMEL
int spi_flash_cmd_write_ops_atmel(struct spi_flash *flash, u32 offset,
size_t len, const void *buf)
{
unsigned long byte_addr, page_size;
size_t actual;
u8 cmd[4];
int ret = -1;
page_size = flash->page_size;
byte_addr = offset % page_size;
if (byte_addr)
return -EINVAL;
for (actual = 0; actual < len; actual += page_size) {
cmd[0] = CMD_BUFFER1_WRITE;
cmd[1] = 0;
cmd[2] = 0;
cmd[3] = 0;
ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
buf + actual, page_size);
if (ret < 0) {
debug("SF: write failed\n");
break;
}
cmd[0] = CMD_BUFFER1_PROGRAM;
spi_flash_addr(offset, cmd);
ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
buf + actual, page_size);
if (ret < 0) {
debug("SF: write failed\n");
break;
}
offset += page_size;
}
return ret;
}
#endif
int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
size_t cmd_len, void *data, size_t data_len) size_t cmd_len, void *data, size_t data_len)
{ {
...@@ -1176,6 +1216,19 @@ int spi_flash_scan(struct spi_flash *flash) ...@@ -1176,6 +1216,19 @@ int spi_flash_scan(struct spi_flash *flash)
flash->write = sst_write_wp; flash->write = sst_write_wp;
} }
#endif #endif
flash->status_cmd = CMD_READ_STATUS;
flash->status_ready_mask = STATUS_WIP;
flash->status_ready_level = 0;
#ifdef CONFIG_SPI_FLASH_ATMEL
if (info->flags & ATMEL_REGS) {
flash->write = spi_flash_cmd_write_ops_atmel;
flash->status_cmd = CMD_READ_STATUS2;
flash->status_ready_mask = STATUS2_READY;
flash->status_ready_level = STATUS2_READY;
}
#endif
flash->erase = spi_flash_cmd_erase_ops; flash->erase = spi_flash_cmd_erase_ops;
flash->read = spi_flash_cmd_read_ops; flash->read = spi_flash_cmd_read_ops;
#endif #endif
...@@ -1227,6 +1280,9 @@ int spi_flash_scan(struct spi_flash *flash) ...@@ -1227,6 +1280,9 @@ int spi_flash_scan(struct spi_flash *flash)
if (info->flags & SECT_4K) { if (info->flags & SECT_4K) {
flash->erase_cmd = CMD_ERASE_4K; flash->erase_cmd = CMD_ERASE_4K;
flash->erase_size = 4096 << flash->shift; flash->erase_size = 4096 << flash->shift;
} else if (info->flags & SECT_2K) {
flash->erase_cmd = CMD_ERASE_2K;
flash->erase_size = 2048 << flash->shift;
} else } else
#endif #endif
{ {
...@@ -1253,6 +1309,12 @@ int spi_flash_scan(struct spi_flash *flash) ...@@ -1253,6 +1309,12 @@ int spi_flash_scan(struct spi_flash *flash)
/* Go for default supported write cmd */ /* Go for default supported write cmd */
flash->write_cmd = CMD_PAGE_PROGRAM; flash->write_cmd = CMD_PAGE_PROGRAM;
/* Flash powers up read-only, so clear BP# bits */
if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_ATMEL ||
JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_MACRONIX ||
JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST)
write_sr(flash, 0);
/* Set the quad enable bit - only for quad commands */ /* Set the quad enable bit - only for quad commands */
if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
(flash->read_cmd == CMD_READ_QUAD_IO_FAST) || (flash->read_cmd == CMD_READ_QUAD_IO_FAST) ||
......
...@@ -46,7 +46,7 @@ const struct spi_flash_info spi_flash_ids[] = { ...@@ -46,7 +46,7 @@ const struct spi_flash_info spi_flash_ids[] = {
#ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */
{"at45db011d", INFO(0x1f2200, 0x0, 64 * 1024, 4, SECT_4K) }, {"at45db011d", INFO(0x1f2200, 0x0, 64 * 1024, 4, SECT_4K) },
{"at45db021d", INFO(0x1f2300, 0x0, 64 * 1024, 8, SECT_4K) }, {"at45db021d", INFO(0x1f2300, 0x0, 64 * 1024, 8, SECT_4K) },
{"at45db041d", INFO(0x1f2400, 0x0, 64 * 1024, 8, SECT_4K) }, {"at45db041d", INFO(0x1f2400, 0x0, 64 * 1024, 8, SECT_2K | ATMEL_REGS) },
{"at45db081d", INFO(0x1f2500, 0x0, 64 * 1024, 16, SECT_4K) }, {"at45db081d", INFO(0x1f2500, 0x0, 64 * 1024, 16, SECT_4K) },
{"at45db161d", INFO(0x1f2600, 0x0, 64 * 1024, 32, SECT_4K) }, {"at45db161d", INFO(0x1f2600, 0x0, 64 * 1024, 32, SECT_4K) },
{"at45db321d", INFO(0x1f2700, 0x0, 64 * 1024, 64, SECT_4K) }, {"at45db321d", INFO(0x1f2700, 0x0, 64 * 1024, 64, SECT_4K) },
......
...@@ -83,6 +83,11 @@ struct spi_flash { ...@@ -83,6 +83,11 @@ struct spi_flash {
u8 write_cmd; u8 write_cmd;
u8 dummy_byte; u8 dummy_byte;
u8 status_cmd;
u8 status_ready_mask;
u8 status_ready_level;
u8 spare1;
void *memory_map; void *memory_map;
int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment