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/devices | |
| 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/devices')
| -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 | ||
