summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Cernekee <cernekee@gmail.com>2010-10-30 21:11:03 -0700
committerJavier Jardón <jjardon@gnome.org>2015-05-06 16:15:36 +0100
commit856b0f757f2011eed19170984a084d82747a3d7c (patch)
tree8e6808f067f4689868bfa3cee8057aee4e092ce3
parent5842f4785d19e212b89e48ef66970b843f6032f0 (diff)
downloadlinux-stable-856b0f757f2011eed19170984a084d82747a3d7c.tar.gz
mtd: m25p80: Add support for Macronix MX25L25635E
This is a 256Mbit (32MiB) part so minor changes were made to support 4-byte addressing. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> (cherry picked from commit 4b7f7422b0331e802f8b7c593e058ccee981cff5) Conflicts: drivers/mtd/devices/m25p80.c
-rw-r--r--drivers/mtd/devices/m25p80.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 686aff7f4c3b..0e754894505a 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -46,6 +46,10 @@
#define OPCODE_WRDI 0x04 /* Write disable */
#define OPCODE_AAI_WP 0xad /* Auto address increment word program */
+/* Used for Macronix flashes only. */
+#define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */
+#define OPCODE_EX4B 0xe9 /* Exit 4-byte mode */
+
/* Status Register bits. */
#define SR_WIP 1 /* Write in progress */
#define SR_WEL 2 /* Write enable latch */
@@ -57,7 +61,7 @@
/* Define max times to check status register before we give up. */
#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */
-#define MAX_CMD_SIZE 4
+#define MAX_CMD_SIZE 5
#ifdef CONFIG_M25PXX_USE_FAST_READ
#define OPCODE_READ OPCODE_FAST_READ
@@ -153,6 +157,16 @@ static inline int write_disable(struct m25p *flash)
}
/*
+ * Enable/disable 4-byte addressing mode.
+ */
+static inline int set_4byte(struct m25p *flash, int enable)
+{
+ u8 code = enable ? OPCODE_EN4B : OPCODE_EX4B;
+
+ return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
+}
+
+/*
* Service routine to read status register until ready, or timeout occurs.
* Returns non-zero if error.
*/
@@ -208,6 +222,7 @@ static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd)
cmd[1] = addr >> (flash->addr_width * 8 - 8);
cmd[2] = addr >> (flash->addr_width * 8 - 16);
cmd[3] = addr >> (flash->addr_width * 8 - 24);
+ cmd[4] = addr >> (flash->addr_width * 8 - 32);
}
static int m25p_cmdsz(struct m25p *flash)
@@ -608,7 +623,7 @@ struct flash_info {
};
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
- _jedec_id, _ext_id, _sector_size, _n_sectors, 256, 3, _flags
+ _jedec_id, _ext_id, _sector_size, _n_sectors, 256, _flags
#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width) \
0, 0, _sector_size, _n_sectors, _page_size, _addr_width, M25P_NO_ERASE
@@ -831,7 +846,17 @@ static int __devinit m25p_probe(struct spi_device *spi)
flash->mtd.flags |= MTD_NO_ERASE;
flash->page_size = info->page_size;
- flash->addr_width = info->addr_width;
+
+ if (info->addr_width)
+ flash->addr_width = info->addr_width;
+ else {
+ /* enable 4-byte addressing if the device exceeds 16MiB */
+ if (flash->mtd.size > 0x1000000) {
+ flash->addr_width = 4;
+ set_4byte(flash, 1);
+ } else
+ flash->addr_width = 3;
+ }
dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
(long long)flash->mtd.size >> 10);