diff options
author | Sourav Poddar <sourav.poddar@ti.com> | 2013-11-06 09:35:35 -0500 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2014-01-03 14:22:07 -0500 |
commit | 3487a63955c34ea508bcf4ca5131ddd953876e2d (patch) | |
tree | cc97a964acf1ef342cad455250784e624d87bfc6 | |
parent | 8552b439aba7f32063755d23f79ca27b4d0a3115 (diff) |
drivers: mtd: m25p80: add quad read support
Some flash also support quad read mode. Adding support for quad read
mode in m25p80 for Spansion and Macronix flash.
[Tweaked by Brian]
With this patch, quad-read support will override fast-read and
normal-read, if the SPI controller and flash chip both support it.
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
Tested-by: Sourav Poddar <sourav.poddar@ti.com>
Reviewed-by: Marek Vasut <marex@denx.de>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
-rw-r--r-- | drivers/mtd/devices/m25p80.c | 139 |
1 files changed, 137 insertions, 2 deletions
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 04f8a245ffef..7dc2c147720a 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #define OPCODE_WRSR 0x01 /* Write status register 1 byte */ | 41 | #define OPCODE_WRSR 0x01 /* Write status register 1 byte */ |
42 | #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ | 42 | #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ |
43 | #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ | 43 | #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ |
44 | #define OPCODE_QUAD_READ 0x6b /* Read data bytes */ | ||
44 | #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ | 45 | #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ |
45 | #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ | 46 | #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ |
46 | #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ | 47 | #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ |
@@ -48,10 +49,12 @@ | |||
48 | #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ | 49 | #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ |
49 | #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ | 50 | #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ |
50 | #define OPCODE_RDID 0x9f /* Read JEDEC ID */ | 51 | #define OPCODE_RDID 0x9f /* Read JEDEC ID */ |
52 | #define OPCODE_RDCR 0x35 /* Read configuration register */ | ||
51 | 53 | ||
52 | /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ | 54 | /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ |
53 | #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ | 55 | #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ |
54 | #define OPCODE_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */ | 56 | #define OPCODE_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */ |
57 | #define OPCODE_QUAD_READ_4B 0x6c /* Read data bytes */ | ||
55 | #define OPCODE_PP_4B 0x12 /* Page program (up to 256 bytes) */ | 58 | #define OPCODE_PP_4B 0x12 /* Page program (up to 256 bytes) */ |
56 | #define OPCODE_SE_4B 0xdc /* Sector erase (usually 64KiB) */ | 59 | #define OPCODE_SE_4B 0xdc /* Sector erase (usually 64KiB) */ |
57 | 60 | ||
@@ -76,6 +79,11 @@ | |||
76 | #define SR_BP2 0x10 /* Block protect 2 */ | 79 | #define SR_BP2 0x10 /* Block protect 2 */ |
77 | #define SR_SRWD 0x80 /* SR write protect */ | 80 | #define SR_SRWD 0x80 /* SR write protect */ |
78 | 81 | ||
82 | #define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ | ||
83 | |||
84 | /* Configuration Register bits. */ | ||
85 | #define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */ | ||
86 | |||
79 | /* Define max times to check status register before we give up. */ | 87 | /* Define max times to check status register before we give up. */ |
80 | #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ | 88 | #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ |
81 | #define MAX_CMD_SIZE 6 | 89 | #define MAX_CMD_SIZE 6 |
@@ -87,6 +95,7 @@ | |||
87 | enum read_type { | 95 | enum read_type { |
88 | M25P80_NORMAL = 0, | 96 | M25P80_NORMAL = 0, |
89 | M25P80_FAST, | 97 | M25P80_FAST, |
98 | M25P80_QUAD, | ||
90 | }; | 99 | }; |
91 | 100 | ||
92 | struct m25p { | 101 | struct m25p { |
@@ -136,6 +145,26 @@ static int read_sr(struct m25p *flash) | |||
136 | } | 145 | } |
137 | 146 | ||
138 | /* | 147 | /* |
148 | * Read configuration register, returning its value in the | ||
149 | * location. Return the configuration register value. | ||
150 | * Returns negative if error occured. | ||
151 | */ | ||
152 | static int read_cr(struct m25p *flash) | ||
153 | { | ||
154 | u8 code = OPCODE_RDCR; | ||
155 | int ret; | ||
156 | u8 val; | ||
157 | |||
158 | ret = spi_write_then_read(flash->spi, &code, 1, &val, 1); | ||
159 | if (ret < 0) { | ||
160 | dev_err(&flash->spi->dev, "error %d reading CR\n", ret); | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | return val; | ||
165 | } | ||
166 | |||
167 | /* | ||
139 | * Write status register 1 byte | 168 | * Write status register 1 byte |
140 | * Returns negative if error occurred. | 169 | * Returns negative if error occurred. |
141 | */ | 170 | */ |
@@ -225,6 +254,93 @@ static int wait_till_ready(struct m25p *flash) | |||
225 | } | 254 | } |
226 | 255 | ||
227 | /* | 256 | /* |
257 | * Write status Register and configuration register with 2 bytes | ||
258 | * The first byte will be written to the status register, while the | ||
259 | * second byte will be written to the configuration register. | ||
260 | * Return negative if error occured. | ||
261 | */ | ||
262 | static int write_sr_cr(struct m25p *flash, u16 val) | ||
263 | { | ||
264 | flash->command[0] = OPCODE_WRSR; | ||
265 | flash->command[1] = val & 0xff; | ||
266 | flash->command[2] = (val >> 8); | ||
267 | |||
268 | return spi_write(flash->spi, flash->command, 3); | ||
269 | } | ||
270 | |||
271 | static int macronix_quad_enable(struct m25p *flash) | ||
272 | { | ||
273 | int ret, val; | ||
274 | u8 cmd[2]; | ||
275 | cmd[0] = OPCODE_WRSR; | ||
276 | |||
277 | val = read_sr(flash); | ||
278 | cmd[1] = val | SR_QUAD_EN_MX; | ||
279 | write_enable(flash); | ||
280 | |||
281 | spi_write(flash->spi, &cmd, 2); | ||
282 | |||
283 | if (wait_till_ready(flash)) | ||
284 | return 1; | ||
285 | |||
286 | ret = read_sr(flash); | ||
287 | if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { | ||
288 | dev_err(&flash->spi->dev, "Macronix Quad bit not set\n"); | ||
289 | return -EINVAL; | ||
290 | } | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static int spansion_quad_enable(struct m25p *flash) | ||
296 | { | ||
297 | int ret; | ||
298 | int quad_en = CR_QUAD_EN_SPAN << 8; | ||
299 | |||
300 | write_enable(flash); | ||
301 | |||
302 | ret = write_sr_cr(flash, quad_en); | ||
303 | if (ret < 0) { | ||
304 | dev_err(&flash->spi->dev, | ||
305 | "error while writing configuration register\n"); | ||
306 | return -EINVAL; | ||
307 | } | ||
308 | |||
309 | /* read back and check it */ | ||
310 | ret = read_cr(flash); | ||
311 | if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { | ||
312 | dev_err(&flash->spi->dev, "Spansion Quad bit not set\n"); | ||
313 | return -EINVAL; | ||
314 | } | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int set_quad_mode(struct m25p *flash, u32 jedec_id) | ||
320 | { | ||
321 | int status; | ||
322 | |||
323 | switch (JEDEC_MFR(jedec_id)) { | ||
324 | case CFI_MFR_MACRONIX: | ||
325 | status = macronix_quad_enable(flash); | ||
326 | if (status) { | ||
327 | dev_err(&flash->spi->dev, | ||
328 | "Macronix quad-read not enabled\n"); | ||
329 | return -EINVAL; | ||
330 | } | ||
331 | return status; | ||
332 | default: | ||
333 | status = spansion_quad_enable(flash); | ||
334 | if (status) { | ||
335 | dev_err(&flash->spi->dev, | ||
336 | "Spansion quad-read not enabled\n"); | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | return status; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | /* | ||
228 | * Erase the whole flash memory | 344 | * Erase the whole flash memory |
229 | * | 345 | * |
230 | * Returns 0 if successful, non-zero otherwise. | 346 | * Returns 0 if successful, non-zero otherwise. |
@@ -363,6 +479,7 @@ static inline int m25p80_dummy_cycles_read(struct m25p *flash) | |||
363 | { | 479 | { |
364 | switch (flash->flash_read) { | 480 | switch (flash->flash_read) { |
365 | case M25P80_FAST: | 481 | case M25P80_FAST: |
482 | case M25P80_QUAD: | ||
366 | return 1; | 483 | return 1; |
367 | case M25P80_NORMAL: | 484 | case M25P80_NORMAL: |
368 | return 0; | 485 | return 0; |
@@ -727,6 +844,7 @@ struct flash_info { | |||
727 | #define SST_WRITE 0x04 /* use SST byte programming */ | 844 | #define SST_WRITE 0x04 /* use SST byte programming */ |
728 | #define M25P_NO_FR 0x08 /* Can't do fastread */ | 845 | #define M25P_NO_FR 0x08 /* Can't do fastread */ |
729 | #define SECT_4K_PMC 0x10 /* OPCODE_BE_4K_PMC works uniformly */ | 846 | #define SECT_4K_PMC 0x10 /* OPCODE_BE_4K_PMC works uniformly */ |
847 | #define M25P80_QUAD_READ 0x20 /* Flash supports Quad Read */ | ||
730 | }; | 848 | }; |
731 | 849 | ||
732 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ | 850 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ |
@@ -804,7 +922,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
804 | { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, | 922 | { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, |
805 | { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, | 923 | { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, |
806 | { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, | 924 | { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, |
807 | { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) }, | 925 | { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, M25P80_QUAD_READ) }, |
808 | 926 | ||
809 | /* Micron */ | 927 | /* Micron */ |
810 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, | 928 | { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, |
@@ -824,7 +942,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
824 | { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, 0) }, | 942 | { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, 0) }, |
825 | { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, | 943 | { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, |
826 | { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, | 944 | { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, |
827 | { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, 0) }, | 945 | { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, M25P80_QUAD_READ) }, |
828 | { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) }, | 946 | { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) }, |
829 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, | 947 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, |
830 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, | 948 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, |
@@ -966,6 +1084,7 @@ static int m25p_probe(struct spi_device *spi) | |||
966 | unsigned i; | 1084 | unsigned i; |
967 | struct mtd_part_parser_data ppdata; | 1085 | struct mtd_part_parser_data ppdata; |
968 | struct device_node *np = spi->dev.of_node; | 1086 | struct device_node *np = spi->dev.of_node; |
1087 | int ret; | ||
969 | 1088 | ||
970 | /* Platform data helps sort out which chip type we have, as | 1089 | /* Platform data helps sort out which chip type we have, as |
971 | * well as how this board partitions it. If we don't have | 1090 | * well as how this board partitions it. If we don't have |
@@ -1093,8 +1212,21 @@ static int m25p_probe(struct spi_device *spi) | |||
1093 | if (info->flags & M25P_NO_FR) | 1212 | if (info->flags & M25P_NO_FR) |
1094 | flash->flash_read = M25P80_NORMAL; | 1213 | flash->flash_read = M25P80_NORMAL; |
1095 | 1214 | ||
1215 | /* Quad-read mode takes precedence over fast/normal */ | ||
1216 | if (spi->mode & SPI_RX_QUAD && info->flags & M25P80_QUAD_READ) { | ||
1217 | ret = set_quad_mode(flash, info->jedec_id); | ||
1218 | if (ret) { | ||
1219 | dev_err(&flash->spi->dev, "quad mode not supported\n"); | ||
1220 | return ret; | ||
1221 | } | ||
1222 | flash->flash_read = M25P80_QUAD; | ||
1223 | } | ||
1224 | |||
1096 | /* Default commands */ | 1225 | /* Default commands */ |
1097 | switch (flash->flash_read) { | 1226 | switch (flash->flash_read) { |
1227 | case M25P80_QUAD: | ||
1228 | flash->read_opcode = OPCODE_QUAD_READ; | ||
1229 | break; | ||
1098 | case M25P80_FAST: | 1230 | case M25P80_FAST: |
1099 | flash->read_opcode = OPCODE_FAST_READ; | 1231 | flash->read_opcode = OPCODE_FAST_READ; |
1100 | break; | 1232 | break; |
@@ -1116,6 +1248,9 @@ static int m25p_probe(struct spi_device *spi) | |||
1116 | if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { | 1248 | if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { |
1117 | /* Dedicated 4-byte command set */ | 1249 | /* Dedicated 4-byte command set */ |
1118 | switch (flash->flash_read) { | 1250 | switch (flash->flash_read) { |
1251 | case M25P80_QUAD: | ||
1252 | flash->read_opcode = OPCODE_QUAD_READ; | ||
1253 | break; | ||
1119 | case M25P80_FAST: | 1254 | case M25P80_FAST: |
1120 | flash->read_opcode = OPCODE_FAST_READ_4B; | 1255 | flash->read_opcode = OPCODE_FAST_READ_4B; |
1121 | break; | 1256 | break; |