aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices
diff options
context:
space:
mode:
authorAnton Vorontsov <avorontsov@ru.mvista.com>2009-10-12 12:24:40 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-11-30 06:29:00 -0500
commit837479d25e221ba616de2c734f58e1decd8cdb95 (patch)
treed92d2c78579ffe6faf5d6b9bf8341044956f5d07 /drivers/mtd/devices
parent18c6182bae0acca220ed6611f741034d563cd19f (diff)
mtd: m25p80: Add support for CAT25xxx serial EEPROMs
CAT25 chips (as manufactured by On Semiconductor, previously Catalyst Semiconductor) are similar to the original M25Px0 chips, except: - Address width can vary (1-2 bytes, in contrast to 3 bytes in M25P chips). So, implement convenient m25p_addr2cmd() and m25p_cmdsz() calls, and place address width information into flash_info struct; - Page size can vary, therefore we shouldn't hardcode it, so get rid of FLASH_PAGESIZE definition, and place the page size information into flash_info struct; - CAT25 EEPROMs don't need to be erased, so add NO_ERASE flag, and propagate it to the mtd subsystem. [dwmw2: Fix up for conflicts with DMA safety patch] Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r--drivers/mtd/devices/m25p80.c114
1 files changed, 69 insertions, 45 deletions
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index e6892851e813..8f8c249d7c46 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -29,9 +29,6 @@
29#include <linux/spi/spi.h> 29#include <linux/spi/spi.h>
30#include <linux/spi/flash.h> 30#include <linux/spi/flash.h>
31 31
32
33#define FLASH_PAGESIZE 256
34
35/* Flash opcodes. */ 32/* Flash opcodes. */
36#define OPCODE_WREN 0x06 /* Write enable */ 33#define OPCODE_WREN 0x06 /* Write enable */
37#define OPCODE_RDSR 0x05 /* Read status register */ 34#define OPCODE_RDSR 0x05 /* Read status register */
@@ -61,7 +58,7 @@
61 58
62/* Define max times to check status register before we give up. */ 59/* Define max times to check status register before we give up. */
63#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ 60#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */
64#define CMD_SIZE 4 61#define MAX_CMD_SIZE 4
65 62
66#ifdef CONFIG_M25PXX_USE_FAST_READ 63#ifdef CONFIG_M25PXX_USE_FAST_READ
67#define OPCODE_READ OPCODE_FAST_READ 64#define OPCODE_READ OPCODE_FAST_READ
@@ -78,6 +75,8 @@ struct m25p {
78 struct mutex lock; 75 struct mutex lock;
79 struct mtd_info mtd; 76 struct mtd_info mtd;
80 unsigned partitioned:1; 77 unsigned partitioned:1;
78 u16 page_size;
79 u16 addr_width;
81 u8 erase_opcode; 80 u8 erase_opcode;
82 u8 *command; 81 u8 *command;
83}; 82};
@@ -198,6 +197,19 @@ static int erase_chip(struct m25p *flash)
198 return 0; 197 return 0;
199} 198}
200 199
200static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd)
201{
202 /* opcode is in cmd[0] */
203 cmd[1] = addr >> (flash->addr_width * 8 - 8);
204 cmd[2] = addr >> (flash->addr_width * 8 - 16);
205 cmd[3] = addr >> (flash->addr_width * 8 - 24);
206}
207
208static int m25p_cmdsz(struct m25p *flash)
209{
210 return 1 + flash->addr_width;
211}
212
201/* 213/*
202 * Erase one sector of flash memory at offset ``offset'' which is any 214 * Erase one sector of flash memory at offset ``offset'' which is any
203 * address within the sector which should be erased. 215 * address within the sector which should be erased.
@@ -219,11 +231,9 @@ static int erase_sector(struct m25p *flash, u32 offset)
219 231
220 /* Set up command buffer. */ 232 /* Set up command buffer. */
221 flash->command[0] = flash->erase_opcode; 233 flash->command[0] = flash->erase_opcode;
222 flash->command[1] = offset >> 16; 234 m25p_addr2cmd(flash, offset, flash->command);
223 flash->command[2] = offset >> 8;
224 flash->command[3] = offset;
225 235
226 spi_write(flash->spi, flash->command, CMD_SIZE); 236 spi_write(flash->spi, flash->command, m25p_cmdsz(flash));
227 237
228 return 0; 238 return 0;
229} 239}
@@ -325,7 +335,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
325 * Should add 1 byte DUMMY_BYTE. 335 * Should add 1 byte DUMMY_BYTE.
326 */ 336 */
327 t[0].tx_buf = flash->command; 337 t[0].tx_buf = flash->command;
328 t[0].len = CMD_SIZE + FAST_READ_DUMMY_BYTE; 338 t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE;
329 spi_message_add_tail(&t[0], &m); 339 spi_message_add_tail(&t[0], &m);
330 340
331 t[1].rx_buf = buf; 341 t[1].rx_buf = buf;
@@ -352,13 +362,11 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
352 362
353 /* Set up the write data buffer. */ 363 /* Set up the write data buffer. */
354 flash->command[0] = OPCODE_READ; 364 flash->command[0] = OPCODE_READ;
355 flash->command[1] = from >> 16; 365 m25p_addr2cmd(flash, from, flash->command);
356 flash->command[2] = from >> 8;
357 flash->command[3] = from;
358 366
359 spi_sync(flash->spi, &m); 367 spi_sync(flash->spi, &m);
360 368
361 *retlen = m.actual_length - CMD_SIZE - FAST_READ_DUMMY_BYTE; 369 *retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE;
362 370
363 mutex_unlock(&flash->lock); 371 mutex_unlock(&flash->lock);
364 372
@@ -396,7 +404,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
396 memset(t, 0, (sizeof t)); 404 memset(t, 0, (sizeof t));
397 405
398 t[0].tx_buf = flash->command; 406 t[0].tx_buf = flash->command;
399 t[0].len = CMD_SIZE; 407 t[0].len = m25p_cmdsz(flash);
400 spi_message_add_tail(&t[0], &m); 408 spi_message_add_tail(&t[0], &m);
401 409
402 t[1].tx_buf = buf; 410 t[1].tx_buf = buf;
@@ -414,41 +422,36 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
414 422
415 /* Set up the opcode in the write buffer. */ 423 /* Set up the opcode in the write buffer. */
416 flash->command[0] = OPCODE_PP; 424 flash->command[0] = OPCODE_PP;
417 flash->command[1] = to >> 16; 425 m25p_addr2cmd(flash, to, flash->command);
418 flash->command[2] = to >> 8;
419 flash->command[3] = to;
420 426
421 /* what page do we start with? */ 427 page_offset = to & (flash->page_size - 1);
422 page_offset = to % FLASH_PAGESIZE;
423 428
424 /* do all the bytes fit onto one page? */ 429 /* do all the bytes fit onto one page? */
425 if (page_offset + len <= FLASH_PAGESIZE) { 430 if (page_offset + len <= flash->page_size) {
426 t[1].len = len; 431 t[1].len = len;
427 432
428 spi_sync(flash->spi, &m); 433 spi_sync(flash->spi, &m);
429 434
430 *retlen = m.actual_length - CMD_SIZE; 435 *retlen = m.actual_length - m25p_cmdsz(flash);
431 } else { 436 } else {
432 u32 i; 437 u32 i;
433 438
434 /* the size of data remaining on the first page */ 439 /* the size of data remaining on the first page */
435 page_size = FLASH_PAGESIZE - page_offset; 440 page_size = flash->page_size - page_offset;
436 441
437 t[1].len = page_size; 442 t[1].len = page_size;
438 spi_sync(flash->spi, &m); 443 spi_sync(flash->spi, &m);
439 444
440 *retlen = m.actual_length - CMD_SIZE; 445 *retlen = m.actual_length - m25p_cmdsz(flash);
441 446
442 /* write everything in PAGESIZE chunks */ 447 /* write everything in flash->page_size chunks */
443 for (i = page_size; i < len; i += page_size) { 448 for (i = page_size; i < len; i += page_size) {
444 page_size = len - i; 449 page_size = len - i;
445 if (page_size > FLASH_PAGESIZE) 450 if (page_size > flash->page_size)
446 page_size = FLASH_PAGESIZE; 451 page_size = flash->page_size;
447 452
448 /* write the next page to flash */ 453 /* write the next page to flash */
449 flash->command[1] = (to + i) >> 16; 454 m25p_addr2cmd(flash, to + i, flash->command);
450 flash->command[2] = (to + i) >> 8;
451 flash->command[3] = (to + i);
452 455
453 t[1].tx_buf = buf + i; 456 t[1].tx_buf = buf + i;
454 t[1].len = page_size; 457 t[1].len = page_size;
@@ -460,7 +463,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
460 spi_sync(flash->spi, &m); 463 spi_sync(flash->spi, &m);
461 464
462 if (retlen) 465 if (retlen)
463 *retlen += m.actual_length - CMD_SIZE; 466 *retlen += m.actual_length - m25p_cmdsz(flash);
464 } 467 }
465 } 468 }
466 469
@@ -492,7 +495,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
492 memset(t, 0, (sizeof t)); 495 memset(t, 0, (sizeof t));
493 496
494 t[0].tx_buf = flash->command; 497 t[0].tx_buf = flash->command;
495 t[0].len = CMD_SIZE; 498 t[0].len = m25p_cmdsz(flash);
496 spi_message_add_tail(&t[0], &m); 499 spi_message_add_tail(&t[0], &m);
497 500
498 t[1].tx_buf = buf; 501 t[1].tx_buf = buf;
@@ -511,9 +514,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
511 /* Start write from odd address. */ 514 /* Start write from odd address. */
512 if (actual) { 515 if (actual) {
513 flash->command[0] = OPCODE_BP; 516 flash->command[0] = OPCODE_BP;
514 flash->command[1] = to >> 16; 517 m25p_addr2cmd(flash, to, flash->command);
515 flash->command[2] = to >> 8;
516 flash->command[3] = to;
517 518
518 /* write one byte. */ 519 /* write one byte. */
519 t[1].len = 1; 520 t[1].len = 1;
@@ -521,17 +522,15 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
521 ret = wait_till_ready(flash); 522 ret = wait_till_ready(flash);
522 if (ret) 523 if (ret)
523 goto time_out; 524 goto time_out;
524 *retlen += m.actual_length - CMD_SIZE; 525 *retlen += m.actual_length - m25p_cmdsz(flash);
525 } 526 }
526 to += actual; 527 to += actual;
527 528
528 flash->command[0] = OPCODE_AAI_WP; 529 flash->command[0] = OPCODE_AAI_WP;
529 flash->command[1] = to >> 16; 530 m25p_addr2cmd(flash, to, flash->command);
530 flash->command[2] = to >> 8;
531 flash->command[3] = to;
532 531
533 /* Write out most of the data here. */ 532 /* Write out most of the data here. */
534 cmd_sz = CMD_SIZE; 533 cmd_sz = m25p_cmdsz(flash);
535 for (; actual < len - 1; actual += 2) { 534 for (; actual < len - 1; actual += 2) {
536 t[0].len = cmd_sz; 535 t[0].len = cmd_sz;
537 /* write two bytes. */ 536 /* write two bytes. */
@@ -555,10 +554,8 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
555 if (actual != len) { 554 if (actual != len) {
556 write_enable(flash); 555 write_enable(flash);
557 flash->command[0] = OPCODE_BP; 556 flash->command[0] = OPCODE_BP;
558 flash->command[1] = to >> 16; 557 m25p_addr2cmd(flash, to, flash->command);
559 flash->command[2] = to >> 8; 558 t[0].len = m25p_cmdsz(flash);
560 flash->command[3] = to;
561 t[0].len = CMD_SIZE;
562 t[1].len = 1; 559 t[1].len = 1;
563 t[1].tx_buf = buf + actual; 560 t[1].tx_buf = buf + actual;
564 561
@@ -566,7 +563,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
566 ret = wait_till_ready(flash); 563 ret = wait_till_ready(flash);
567 if (ret) 564 if (ret)
568 goto time_out; 565 goto time_out;
569 *retlen += m.actual_length - CMD_SIZE; 566 *retlen += m.actual_length - m25p_cmdsz(flash);
570 write_disable(flash); 567 write_disable(flash);
571 } 568 }
572 569
@@ -595,8 +592,12 @@ struct flash_info {
595 unsigned sector_size; 592 unsigned sector_size;
596 u16 n_sectors; 593 u16 n_sectors;
597 594
595 u16 page_size;
596 u16 addr_width;
597
598 u16 flags; 598 u16 flags;
599#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ 599#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
600#define M25P_NO_ERASE 0x02 /* No erase command needed */
600}; 601};
601 602
602#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ 603#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
@@ -605,9 +606,20 @@ struct flash_info {
605 .ext_id = (_ext_id), \ 606 .ext_id = (_ext_id), \
606 .sector_size = (_sector_size), \ 607 .sector_size = (_sector_size), \
607 .n_sectors = (_n_sectors), \ 608 .n_sectors = (_n_sectors), \
609 .page_size = 256, \
610 .addr_width = 3, \
608 .flags = (_flags), \ 611 .flags = (_flags), \
609 }) 612 })
610 613
614#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width) \
615 ((kernel_ulong_t)&(struct flash_info) { \
616 .sector_size = (_sector_size), \
617 .n_sectors = (_n_sectors), \
618 .page_size = (_page_size), \
619 .addr_width = (_addr_width), \
620 .flags = M25P_NO_ERASE, \
621 })
622
611/* NOTE: double check command sets and memory organization when you add 623/* NOTE: double check command sets and memory organization when you add
612 * more flash chips. This current list focusses on newer chips, which 624 * more flash chips. This current list focusses on newer chips, which
613 * have been converging on command sets which including JEDEC ID. 625 * have been converging on command sets which including JEDEC ID.
@@ -680,6 +692,13 @@ static const struct spi_device_id m25p_ids[] = {
680 { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, 692 { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
681 { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, 693 { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
682 { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, 694 { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
695
696 /* Catalyst / On Semiconductor -- non-JEDEC */
697 { "cat25c11", CAT25_INFO( 16, 8, 16, 1) },
698 { "cat25c03", CAT25_INFO( 32, 8, 16, 2) },
699 { "cat25c09", CAT25_INFO( 128, 8, 32, 2) },
700 { "cat25c17", CAT25_INFO( 256, 8, 32, 2) },
701 { "cat25128", CAT25_INFO(2048, 8, 64, 2) },
683 { }, 702 { },
684}; 703};
685MODULE_DEVICE_TABLE(spi, m25p_ids); 704MODULE_DEVICE_TABLE(spi, m25p_ids);
@@ -793,7 +812,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
793 flash = kzalloc(sizeof *flash, GFP_KERNEL); 812 flash = kzalloc(sizeof *flash, GFP_KERNEL);
794 if (!flash) 813 if (!flash)
795 return -ENOMEM; 814 return -ENOMEM;
796 flash->command = kmalloc(CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL); 815 flash->command = kmalloc(MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL);
797 if (!flash->command) { 816 if (!flash->command) {
798 kfree(flash); 817 kfree(flash);
799 return -ENOMEM; 818 return -ENOMEM;
@@ -841,7 +860,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
841 flash->mtd.erasesize = info->sector_size; 860 flash->mtd.erasesize = info->sector_size;
842 } 861 }
843 862
863 if (info->flags & M25P_NO_ERASE)
864 flash->mtd.flags |= MTD_NO_ERASE;
865
844 flash->mtd.dev.parent = &spi->dev; 866 flash->mtd.dev.parent = &spi->dev;
867 flash->page_size = info->page_size;
868 flash->addr_width = info->addr_width;
845 869
846 dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name, 870 dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
847 (long long)flash->mtd.size >> 10); 871 (long long)flash->mtd.size >> 10);