aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices/m25p80.c
diff options
context:
space:
mode:
authorBryan Wu <cooloney@kernel.org>2008-04-25 00:07:32 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2008-04-25 04:13:52 -0400
commit2230b76b3838a37167f80487c694d8691248da9f (patch)
tree99b64457ad80e52b4eddd56e566818c189c7a722 /drivers/mtd/devices/m25p80.c
parentafc4bca63941746f1d49394620d294074150e664 (diff)
[MTD] m25p80: add FAST_READ access support to M25Pxx
Signed-off-by: Bryan Wu <cooloney@kernel.org> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/mtd/devices/m25p80.c')
-rw-r--r--drivers/mtd/devices/m25p80.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 60408c955a13..3f5041d39f24 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -33,7 +33,7 @@
33/* Flash opcodes. */ 33/* Flash opcodes. */
34#define OPCODE_WREN 0x06 /* Write enable */ 34#define OPCODE_WREN 0x06 /* Write enable */
35#define OPCODE_RDSR 0x05 /* Read status register */ 35#define OPCODE_RDSR 0x05 /* Read status register */
36#define OPCODE_READ 0x03 /* Read data bytes (low frequency) */ 36#define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */
37#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ 37#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
38#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ 38#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
39#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ 39#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
@@ -52,7 +52,15 @@
52 52
53/* Define max times to check status register before we give up. */ 53/* Define max times to check status register before we give up. */
54#define MAX_READY_WAIT_COUNT 100000 54#define MAX_READY_WAIT_COUNT 100000
55#define CMD_SIZE 4
55 56
57#ifdef CONFIG_M25PXX_USE_FAST_READ
58#define OPCODE_READ OPCODE_FAST_READ
59#define FAST_READ_DUMMY_BYTE 1
60#else
61#define OPCODE_READ OPCODE_NORM_READ
62#define FAST_READ_DUMMY_BYTE 0
63#endif
56 64
57#ifdef CONFIG_MTD_PARTITIONS 65#ifdef CONFIG_MTD_PARTITIONS
58#define mtd_has_partitions() (1) 66#define mtd_has_partitions() (1)
@@ -68,7 +76,7 @@ struct m25p {
68 struct mtd_info mtd; 76 struct mtd_info mtd;
69 unsigned partitioned:1; 77 unsigned partitioned:1;
70 u8 erase_opcode; 78 u8 erase_opcode;
71 u8 command[4]; 79 u8 command[CMD_SIZE + FAST_READ_DUMMY_BYTE];
72}; 80};
73 81
74static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) 82static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -167,7 +175,7 @@ static int erase_sector(struct m25p *flash, u32 offset)
167 flash->command[2] = offset >> 8; 175 flash->command[2] = offset >> 8;
168 flash->command[3] = offset; 176 flash->command[3] = offset;
169 177
170 spi_write(flash->spi, flash->command, sizeof(flash->command)); 178 spi_write(flash->spi, flash->command, CMD_SIZE);
171 179
172 return 0; 180 return 0;
173} 181}
@@ -253,8 +261,12 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
253 spi_message_init(&m); 261 spi_message_init(&m);
254 memset(t, 0, (sizeof t)); 262 memset(t, 0, (sizeof t));
255 263
264 /* NOTE:
265 * OPCODE_FAST_READ (if available) is faster.
266 * Should add 1 byte DUMMY_BYTE.
267 */
256 t[0].tx_buf = flash->command; 268 t[0].tx_buf = flash->command;
257 t[0].len = sizeof(flash->command); 269 t[0].len = CMD_SIZE + FAST_READ_DUMMY_BYTE;
258 spi_message_add_tail(&t[0], &m); 270 spi_message_add_tail(&t[0], &m);
259 271
260 t[1].rx_buf = buf; 272 t[1].rx_buf = buf;
@@ -287,7 +299,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
287 299
288 spi_sync(flash->spi, &m); 300 spi_sync(flash->spi, &m);
289 301
290 *retlen = m.actual_length - sizeof(flash->command); 302 *retlen = m.actual_length - CMD_SIZE - FAST_READ_DUMMY_BYTE;
291 303
292 mutex_unlock(&flash->lock); 304 mutex_unlock(&flash->lock);
293 305
@@ -325,7 +337,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
325 memset(t, 0, (sizeof t)); 337 memset(t, 0, (sizeof t));
326 338
327 t[0].tx_buf = flash->command; 339 t[0].tx_buf = flash->command;
328 t[0].len = sizeof(flash->command); 340 t[0].len = CMD_SIZE;
329 spi_message_add_tail(&t[0], &m); 341 spi_message_add_tail(&t[0], &m);
330 342
331 t[1].tx_buf = buf; 343 t[1].tx_buf = buf;
@@ -354,7 +366,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
354 366
355 spi_sync(flash->spi, &m); 367 spi_sync(flash->spi, &m);
356 368
357 *retlen = m.actual_length - sizeof(flash->command); 369 *retlen = m.actual_length - CMD_SIZE;
358 } else { 370 } else {
359 u32 i; 371 u32 i;
360 372
@@ -364,7 +376,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
364 t[1].len = page_size; 376 t[1].len = page_size;
365 spi_sync(flash->spi, &m); 377 spi_sync(flash->spi, &m);
366 378
367 *retlen = m.actual_length - sizeof(flash->command); 379 *retlen = m.actual_length - CMD_SIZE;
368 380
369 /* write everything in PAGESIZE chunks */ 381 /* write everything in PAGESIZE chunks */
370 for (i = page_size; i < len; i += page_size) { 382 for (i = page_size; i < len; i += page_size) {
@@ -387,8 +399,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
387 spi_sync(flash->spi, &m); 399 spi_sync(flash->spi, &m);
388 400
389 if (retlen) 401 if (retlen)
390 *retlen += m.actual_length 402 *retlen += m.actual_length - CMD_SIZE;
391 - sizeof(flash->command);
392 } 403 }
393 } 404 }
394 405