aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgrmoore@altera.com <grmoore@altera.com>2014-04-29 11:29:51 -0400
committerBrian Norris <computersforpeace@gmail.com>2014-07-11 22:10:35 -0400
commitc14deddec1fbd8c9757c53a49dbfd2dc83265f21 (patch)
tree32b8abbae0d7c3ebfdc205b7bb3a8ee45da37e87
parentfdf43a420f5c2b737b0e65c4c3330867903b098a (diff)
mtd: spi-nor: add support for flag status register on Micron chips
Some new Micron flash chips require reading the flag status register to determine when operations have completed. Furthermore, chips with multi-die stacks of the 65nm 256Mb QSPI also require reading the status register before reading the flag status register. This patch adds support for the flag status register in the n25q512ax3 and n25q00 Micron QSPI flash chips. Signed-off-by: Graham Moore <grmoore@altera.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c52
-rw-r--r--include/linux/mtd/spi-nor.h4
2 files changed, 56 insertions, 0 deletions
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index c713c8656710..7da3a7067c35 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -48,6 +48,25 @@ static int read_sr(struct spi_nor *nor)
48} 48}
49 49
50/* 50/*
51 * Read the flag status register, returning its value in the location
52 * Return the status register value.
53 * Returns negative if error occurred.
54 */
55static int read_fsr(struct spi_nor *nor)
56{
57 int ret;
58 u8 val;
59
60 ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1);
61 if (ret < 0) {
62 pr_err("error %d reading FSR\n", ret);
63 return ret;
64 }
65
66 return val;
67}
68
69/*
51 * Read configuration register, returning its value in the 70 * Read configuration register, returning its value in the
52 * location. Return the configuration register value. 71 * location. Return the configuration register value.
53 * Returns negative if error occured. 72 * Returns negative if error occured.
@@ -165,6 +184,32 @@ static int spi_nor_wait_till_ready(struct spi_nor *nor)
165 return -ETIMEDOUT; 184 return -ETIMEDOUT;
166} 185}
167 186
187static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor)
188{
189 unsigned long deadline;
190 int sr;
191 int fsr;
192
193 deadline = jiffies + MAX_READY_WAIT_JIFFIES;
194
195 do {
196 cond_resched();
197
198 sr = read_sr(nor);
199 if (sr < 0) {
200 break;
201 } else if (!(sr & SR_WIP)) {
202 fsr = read_fsr(nor);
203 if (fsr < 0)
204 break;
205 if (fsr & FSR_READY)
206 return 0;
207 }
208 } while (!time_after_eq(jiffies, deadline));
209
210 return -ETIMEDOUT;
211}
212
168/* 213/*
169 * Service routine to read status register until ready, or timeout occurs. 214 * Service routine to read status register until ready, or timeout occurs.
170 * Returns non-zero if error. 215 * Returns non-zero if error.
@@ -402,6 +447,7 @@ struct flash_info {
402#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ 447#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */
403#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ 448#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */
404#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ 449#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */
450#define USE_FSR 0x80 /* use flag status register */
405}; 451};
406 452
407#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ 453#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
@@ -488,6 +534,8 @@ const struct spi_device_id spi_nor_ids[] = {
488 { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, 534 { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
489 { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, 535 { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
490 { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, 536 { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) },
537 { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) },
538 { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) },
491 539
492 /* PMC */ 540 /* PMC */
493 { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, 541 { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
@@ -965,6 +1013,10 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,
965 else 1013 else
966 mtd->_write = spi_nor_write; 1014 mtd->_write = spi_nor_write;
967 1015
1016 if ((info->flags & USE_FSR) &&
1017 nor->wait_till_ready == spi_nor_wait_till_ready)
1018 nor->wait_till_ready = spi_nor_wait_till_fsr_ready;
1019
968 /* prefer "small sector" erase if possible */ 1020 /* prefer "small sector" erase if possible */
969 if (info->flags & SECT_4K) { 1021 if (info->flags & SECT_4K) {
970 nor->erase_opcode = SPINOR_OP_BE_4K; 1022 nor->erase_opcode = SPINOR_OP_BE_4K;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 53241842a7ab..9e6294f32ba8 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -34,6 +34,7 @@
34#define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */ 34#define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */
35#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */ 35#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */
36#define SPINOR_OP_RDCR 0x35 /* Read configuration register */ 36#define SPINOR_OP_RDCR 0x35 /* Read configuration register */
37#define SPINOR_OP_RDFSR 0x70 /* Read flag status register */
37 38
38/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ 39/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
39#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */ 40#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */
@@ -66,6 +67,9 @@
66 67
67#define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ 68#define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */
68 69
70/* Flag Status Register bits */
71#define FSR_READY 0x80
72
69/* Configuration Register bits. */ 73/* Configuration Register bits. */
70#define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */ 74#define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */
71 75