diff options
Diffstat (limited to 'drivers/mtd/devices/m25p80.c')
-rw-r--r-- | drivers/mtd/devices/m25p80.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 98df5bcc02f3..25efd331ef28 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) |
@@ -151,7 +159,7 @@ static int wait_till_ready(struct m25p *flash) | |||
151 | static int erase_sector(struct m25p *flash, u32 offset) | 159 | static int erase_sector(struct m25p *flash, u32 offset) |
152 | { | 160 | { |
153 | DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n", | 161 | DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n", |
154 | flash->spi->dev.bus_id, __FUNCTION__, | 162 | flash->spi->dev.bus_id, __func__, |
155 | flash->mtd.erasesize / 1024, offset); | 163 | flash->mtd.erasesize / 1024, offset); |
156 | 164 | ||
157 | /* Wait until finished previous write command. */ | 165 | /* Wait until finished previous write command. */ |
@@ -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 | } |
@@ -188,7 +196,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
188 | u32 addr,len; | 196 | u32 addr,len; |
189 | 197 | ||
190 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n", | 198 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n", |
191 | flash->spi->dev.bus_id, __FUNCTION__, "at", | 199 | flash->spi->dev.bus_id, __func__, "at", |
192 | (u32)instr->addr, instr->len); | 200 | (u32)instr->addr, instr->len); |
193 | 201 | ||
194 | /* sanity checks */ | 202 | /* sanity checks */ |
@@ -240,7 +248,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
240 | struct spi_message m; | 248 | struct spi_message m; |
241 | 249 | ||
242 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | 250 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", |
243 | flash->spi->dev.bus_id, __FUNCTION__, "from", | 251 | flash->spi->dev.bus_id, __func__, "from", |
244 | (u32)from, len); | 252 | (u32)from, len); |
245 | 253 | ||
246 | /* sanity checks */ | 254 | /* sanity checks */ |
@@ -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 | ||
@@ -308,7 +320,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
308 | struct spi_message m; | 320 | struct spi_message m; |
309 | 321 | ||
310 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | 322 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", |
311 | flash->spi->dev.bus_id, __FUNCTION__, "to", | 323 | flash->spi->dev.bus_id, __func__, "to", |
312 | (u32)to, len); | 324 | (u32)to, len); |
313 | 325 | ||
314 | if (retlen) | 326 | if (retlen) |
@@ -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 | ||
@@ -435,6 +446,7 @@ static struct flash_info __devinitdata m25p_data [] = { | |||
435 | { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, }, | 446 | { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, }, |
436 | 447 | ||
437 | { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, }, | 448 | { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, }, |
449 | { "at25df641", 0x1f4800, 64 * 1024, 128, SECT_4K, }, | ||
438 | 450 | ||
439 | { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, }, | 451 | { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, }, |
440 | { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, }, | 452 | { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, }, |