From 7c14b894f1884bf7915417ce8b747b11b6f603c6 Mon Sep 17 00:00:00 2001 From: Mark Marshall Date: Wed, 31 Jul 2013 15:26:12 +0200 Subject: [PATCH 45/96] m25p80: Use the 4-byte address read command It is better for some hardware platforms if we use the dedicated 4-byte address SPI read command when reading from SPI Flash chips > 16 MB (rather than converting the 3-byte address command to take 4 address bytes). The problem that we had is that on reset the boot loader tries to use the 3-byte address command which, doesn't work if the Flash has not been reset and Linux has converted it to accept 4-byte addresses. --- drivers/mtd/devices/m25p80.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index fa0f2c0..2d87aad 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -62,6 +62,11 @@ #define OPCODE_OTP_WRITE 0x42 /* Write to the OTP region */ #define OPCODE_OTP_READ 0x4b /* Read from the OTP region */ +#define OPCODE_FAST_READ4B 0x0c /* Read data, 4 byte addr (hi freq.) */ +#define OPCODE_NORM_READ4B 0x13 /* Read data, 4 byte addr (lo freq.) */ +#define OPCODE_PP4B 0x12 /* Page program (up to 256 bytes) */ +#define OPCODE_SE4B 0xdc /* Sector erase (usually 256KiB) */ + /* Status Register bits. */ #define SR_WIP 1 /* Write in progress */ #define SR_WEL 2 /* Write enable latch */ @@ -77,9 +82,11 @@ #ifdef CONFIG_M25PXX_USE_FAST_READ #define OPCODE_READ OPCODE_FAST_READ +#define OPCODE_READ4B OPCODE_FAST_READ4B #define FAST_READ_DUMMY_BYTE 1 #else #define OPCODE_READ OPCODE_NORM_READ +#define OPCODE_READ4B OPCODE_NORM_READ4B #define FAST_READ_DUMMY_BYTE 0 #endif @@ -94,6 +101,8 @@ struct m25p { u16 page_size; u16 addr_width; u8 erase_opcode; + u8 read_opcode; + u8 write_opcode; u8 *command; }; @@ -173,10 +182,20 @@ static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; return spi_write(flash->spi, flash->command, 1); default: - /* Spansion style */ - flash->command[0] = OPCODE_BRWR; - flash->command[1] = enable << 7; - return spi_write(flash->spi, flash->command, 2); + switch (jedec_id) { + case 0x010219: /* s25fl256s0/s25fl256s1 */ + case 0x010220: /* s25fl512s */ + case 0x010221: /* s70fl01gs */ + flash->read_opcode = OPCODE_READ4B; + flash->write_opcode = OPCODE_PP4B; + flash->erase_opcode = OPCODE_SE4B; + return 0; + default: + /* Spansion style */ + flash->command[0] = OPCODE_BRWR; + flash->command[1] = enable << 7; + return spi_write(flash->spi, flash->command, 2); + } } } @@ -402,7 +421,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, */ /* Set up the write data buffer. */ - flash->command[0] = OPCODE_READ; + flash->command[0] = flash->read_opcode; m25p_addr2cmd(flash, from + done, flash->command); spi_sync(flash->spi, &m); @@ -462,7 +481,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, write_enable(flash); /* Set up the opcode in the write buffer. */ - flash->command[0] = OPCODE_PP; + flash->command[0] = flash->write_opcode; m25p_addr2cmd(flash, to, flash->command); page_offset = to & (flash->page_size - 1); @@ -944,7 +963,7 @@ static const struct spi_device_id m25p_ids[] = { { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, 0) }, { "s25fl512s", INFOP(0x010220, 0x4d00, 256 * 1024, 256, 512, M25P_OTP) }, - { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, + { "s70fl01gs", INFOP(0x010221, 0x4d00, 256 * 1024, 256, 512, 0) }, { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, @@ -1172,6 +1191,9 @@ static int __devinit m25p_probe(struct spi_device *spi) flash->mtd.erasesize = info->sector_size; } + flash->read_opcode = OPCODE_READ; + flash->write_opcode = OPCODE_PP; + if (info->flags & M25P_NO_ERASE) flash->mtd.flags |= MTD_NO_ERASE; -- 1.7.9.5