diff options
author | Bryan Wu <cooloney@kernel.org> | 2008-04-25 00:07:32 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2008-04-25 04:13:52 -0400 |
commit | 2230b76b3838a37167f80487c694d8691248da9f (patch) | |
tree | 99b64457ad80e52b4eddd56e566818c189c7a722 /drivers/mtd | |
parent | afc4bca63941746f1d49394620d294074150e664 (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')
-rw-r--r-- | drivers/mtd/devices/Kconfig | 7 | ||||
-rw-r--r-- | drivers/mtd/devices/m25p80.c | 31 |
2 files changed, 28 insertions, 10 deletions
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 811d56fd890f..35ed1103dbb2 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
@@ -77,6 +77,13 @@ config MTD_M25P80 | |||
77 | if you want to specify device partitioning or to use a device which | 77 | if you want to specify device partitioning or to use a device which |
78 | doesn't support the JEDEC ID instruction. | 78 | doesn't support the JEDEC ID instruction. |
79 | 79 | ||
80 | config M25PXX_USE_FAST_READ | ||
81 | bool "Use FAST_READ OPCode allowing SPI CLK <= 50MHz" | ||
82 | depends on MTD_M25P80 | ||
83 | default y | ||
84 | help | ||
85 | This option enables FAST_READ access supported by ST M25Pxx. | ||
86 | |||
80 | config MTD_SLRAM | 87 | config MTD_SLRAM |
81 | tristate "Uncached system RAM" | 88 | tristate "Uncached system RAM" |
82 | help | 89 | help |
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 | ||
74 | static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) | 82 | static 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 | ||