aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Vorontsov <avorontsov@ru.mvista.com>2009-10-12 12:24:35 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-11-30 06:26:08 -0500
commitb34bc037b26e621e5fc13466767e4da110a7b3d3 (patch)
treed76ff3b4377ef8d028f1b8a1ec5f30ca78fbda9a
parent4c2b8a62bb0e35f2db0f713b4101b265be7fa985 (diff)
mtd: m25p80: Convert to device table matching
This patch converts the m25p80 driver so that now it uses .id_table for device matching, making it properly detect devices on OpenFirmware platforms (prior to this patch the driver misdetected non-JEDEC chips, seeing all chips as "m25p80"). Also, now jedec_probe() only does jedec probing, nothing else. If it is not able to detect a chip, NULL is returned and the driver fall backs to the information specified by the platform (platform_data, or exact ID). Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--drivers/mtd/devices/m25p80.c164
1 files changed, 89 insertions, 75 deletions
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 291d5d91892d..47486fbd7777 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -21,6 +21,7 @@
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <linux/math64.h> 23#include <linux/math64.h>
24#include <linux/mod_devicetable.h>
24 25
25#include <linux/mtd/mtd.h> 26#include <linux/mtd/mtd.h>
26#include <linux/mtd/partitions.h> 27#include <linux/mtd/partitions.h>
@@ -581,8 +582,6 @@ time_out:
581 */ 582 */
582 583
583struct flash_info { 584struct flash_info {
584 char *name;
585
586 /* JEDEC id zero means "no ID" (most older chips); otherwise it has 585 /* JEDEC id zero means "no ID" (most older chips); otherwise it has
587 * a high byte of zero plus three data bytes: the manufacturer id, 586 * a high byte of zero plus three data bytes: the manufacturer id,
588 * then a two byte device id. 587 * then a two byte device id.
@@ -600,83 +599,92 @@ struct flash_info {
600#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ 599#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
601}; 600};
602 601
602#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
603 ((kernel_ulong_t)&(struct flash_info) { \
604 .jedec_id = (_jedec_id), \
605 .ext_id = (_ext_id), \
606 .sector_size = (_sector_size), \
607 .n_sectors = (_n_sectors), \
608 .flags = (_flags), \
609 })
603 610
604/* NOTE: double check command sets and memory organization when you add 611/* NOTE: double check command sets and memory organization when you add
605 * more flash chips. This current list focusses on newer chips, which 612 * more flash chips. This current list focusses on newer chips, which
606 * have been converging on command sets which including JEDEC ID. 613 * have been converging on command sets which including JEDEC ID.
607 */ 614 */
608static struct flash_info __devinitdata m25p_data [] = { 615static const struct spi_device_id m25p_ids[] = {
609
610 /* Atmel -- some are (confusingly) marketed as "DataFlash" */ 616 /* Atmel -- some are (confusingly) marketed as "DataFlash" */
611 { "at25fs010", 0x1f6601, 0, 32 * 1024, 4, SECT_4K, }, 617 { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) },
612 { "at25fs040", 0x1f6604, 0, 64 * 1024, 8, SECT_4K, }, 618 { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) },
613 619
614 { "at25df041a", 0x1f4401, 0, 64 * 1024, 8, SECT_4K, }, 620 { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) },
615 { "at25df641", 0x1f4800, 0, 64 * 1024, 128, SECT_4K, }, 621 { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
616 622
617 { "at26f004", 0x1f0400, 0, 64 * 1024, 8, SECT_4K, }, 623 { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) },
618 { "at26df081a", 0x1f4501, 0, 64 * 1024, 16, SECT_4K, }, 624 { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) },
619 { "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, }, 625 { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
620 { "at26df321", 0x1f4701, 0, 64 * 1024, 64, SECT_4K, }, 626 { "at26df321", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
621 627
622 /* Macronix */ 628 /* Macronix */
623 { "mx25l3205d", 0xc22016, 0, 64 * 1024, 64, }, 629 { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) },
624 { "mx25l6405d", 0xc22017, 0, 64 * 1024, 128, }, 630 { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) },
625 { "mx25l12805d", 0xc22018, 0, 64 * 1024, 256, }, 631 { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
626 { "mx25l12855e", 0xc22618, 0, 64 * 1024, 256, }, 632 { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
627 633
628 /* Spansion -- single (large) sector size only, at least 634 /* Spansion -- single (large) sector size only, at least
629 * for the chips listed here (without boot sectors). 635 * for the chips listed here (without boot sectors).
630 */ 636 */
631 { "s25sl004a", 0x010212, 0, 64 * 1024, 8, }, 637 { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
632 { "s25sl008a", 0x010213, 0, 64 * 1024, 16, }, 638 { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) },
633 { "s25sl016a", 0x010214, 0, 64 * 1024, 32, }, 639 { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
634 { "s25sl032a", 0x010215, 0, 64 * 1024, 64, }, 640 { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) },
635 { "s25sl064a", 0x010216, 0, 64 * 1024, 128, }, 641 { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) },
636 { "s25sl12800", 0x012018, 0x0300, 256 * 1024, 64, }, 642 { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
637 { "s25sl12801", 0x012018, 0x0301, 64 * 1024, 256, }, 643 { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
638 { "s25fl129p0", 0x012018, 0x4d00, 256 * 1024, 64, }, 644 { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) },
639 { "s25fl129p1", 0x012018, 0x4d01, 64 * 1024, 256, }, 645 { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) },
640 646
641 /* SST -- large erase sizes are "overlays", "sectors" are 4K */ 647 /* SST -- large erase sizes are "overlays", "sectors" are 4K */
642 { "sst25vf040b", 0xbf258d, 0, 64 * 1024, 8, SECT_4K, }, 648 { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) },
643 { "sst25vf080b", 0xbf258e, 0, 64 * 1024, 16, SECT_4K, }, 649 { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K) },
644 { "sst25vf016b", 0xbf2541, 0, 64 * 1024, 32, SECT_4K, }, 650 { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K) },
645 { "sst25vf032b", 0xbf254a, 0, 64 * 1024, 64, SECT_4K, }, 651 { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K) },
646 { "sst25wf512", 0xbf2501, 0, 64 * 1024, 1, SECT_4K, }, 652 { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K) },
647 { "sst25wf010", 0xbf2502, 0, 64 * 1024, 2, SECT_4K, }, 653 { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K) },
648 { "sst25wf020", 0xbf2503, 0, 64 * 1024, 4, SECT_4K, }, 654 { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K) },
649 { "sst25wf040", 0xbf2504, 0, 64 * 1024, 8, SECT_4K, }, 655 { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K) },
650 656
651 /* ST Microelectronics -- newer production may have feature updates */ 657 /* ST Microelectronics -- newer production may have feature updates */
652 { "m25p05", 0x202010, 0, 32 * 1024, 2, }, 658 { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) },
653 { "m25p10", 0x202011, 0, 32 * 1024, 4, }, 659 { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) },
654 { "m25p20", 0x202012, 0, 64 * 1024, 4, }, 660 { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) },
655 { "m25p40", 0x202013, 0, 64 * 1024, 8, }, 661 { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) },
656 { "m25p80", 0, 0, 64 * 1024, 16, }, 662 { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) },
657 { "m25p16", 0x202015, 0, 64 * 1024, 32, }, 663 { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) },
658 { "m25p32", 0x202016, 0, 64 * 1024, 64, }, 664 { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) },
659 { "m25p64", 0x202017, 0, 64 * 1024, 128, }, 665 { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) },
660 { "m25p128", 0x202018, 0, 256 * 1024, 64, }, 666 { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) },
661 667
662 { "m45pe10", 0x204011, 0, 64 * 1024, 2, }, 668 { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) },
663 { "m45pe80", 0x204014, 0, 64 * 1024, 16, }, 669 { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) },
664 { "m45pe16", 0x204015, 0, 64 * 1024, 32, }, 670 { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) },
665 671
666 { "m25pe80", 0x208014, 0, 64 * 1024, 16, }, 672 { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) },
667 { "m25pe16", 0x208015, 0, 64 * 1024, 32, SECT_4K, }, 673 { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) },
668 674
669 /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ 675 /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
670 { "w25x10", 0xef3011, 0, 64 * 1024, 2, SECT_4K, }, 676 { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) },
671 { "w25x20", 0xef3012, 0, 64 * 1024, 4, SECT_4K, }, 677 { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) },
672 { "w25x40", 0xef3013, 0, 64 * 1024, 8, SECT_4K, }, 678 { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) },
673 { "w25x80", 0xef3014, 0, 64 * 1024, 16, SECT_4K, }, 679 { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) },
674 { "w25x16", 0xef3015, 0, 64 * 1024, 32, SECT_4K, }, 680 { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
675 { "w25x32", 0xef3016, 0, 64 * 1024, 64, SECT_4K, }, 681 { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
676 { "w25x64", 0xef3017, 0, 64 * 1024, 128, SECT_4K, }, 682 { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
683 { },
677}; 684};
685MODULE_DEVICE_TABLE(spi, m25p_ids);
678 686
679static struct flash_info *__devinit jedec_probe(struct spi_device *spi) 687static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
680{ 688{
681 int tmp; 689 int tmp;
682 u8 code = OPCODE_RDID; 690 u8 code = OPCODE_RDID;
@@ -703,16 +711,14 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
703 711
704 ext_jedec = id[3] << 8 | id[4]; 712 ext_jedec = id[3] << 8 | id[4];
705 713
706 for (tmp = 0, info = m25p_data; 714 for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
707 tmp < ARRAY_SIZE(m25p_data); 715 info = (void *)m25p_ids[tmp].driver_data;
708 tmp++, info++) {
709 if (info->jedec_id == jedec) { 716 if (info->jedec_id == jedec) {
710 if (info->ext_id != 0 && info->ext_id != ext_jedec) 717 if (info->ext_id != 0 && info->ext_id != ext_jedec)
711 continue; 718 continue;
712 return info; 719 return &m25p_ids[tmp];
713 } 720 }
714 } 721 }
715 dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
716 return NULL; 722 return NULL;
717} 723}
718 724
@@ -724,6 +730,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
724 */ 730 */
725static int __devinit m25p_probe(struct spi_device *spi) 731static int __devinit m25p_probe(struct spi_device *spi)
726{ 732{
733 const struct spi_device_id *id;
727 struct flash_platform_data *data; 734 struct flash_platform_data *data;
728 struct m25p *flash; 735 struct m25p *flash;
729 struct flash_info *info; 736 struct flash_info *info;
@@ -736,32 +743,38 @@ static int __devinit m25p_probe(struct spi_device *spi)
736 */ 743 */
737 data = spi->dev.platform_data; 744 data = spi->dev.platform_data;
738 if (data && data->type) { 745 if (data && data->type) {
739 for (i = 0, info = m25p_data; 746 for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) {
740 i < ARRAY_SIZE(m25p_data); 747 id = &m25p_ids[i];
741 i++, info++) { 748 info = (void *)m25p_ids[i].driver_data;
742 if (strcmp(data->type, info->name) == 0) 749 if (strcmp(data->type, id->name))
743 break; 750 continue;
751 break;
744 } 752 }
745 753
746 /* unrecognized chip? */ 754 /* unrecognized chip? */
747 if (i == ARRAY_SIZE(m25p_data)) { 755 if (i == ARRAY_SIZE(m25p_ids) - 1) {
748 DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n", 756 DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
749 dev_name(&spi->dev), data->type); 757 dev_name(&spi->dev), data->type);
750 info = NULL; 758 info = NULL;
751 759
752 /* recognized; is that chip really what's there? */ 760 /* recognized; is that chip really what's there? */
753 } else if (info->jedec_id) { 761 } else if (info->jedec_id) {
754 struct flash_info *chip = jedec_probe(spi); 762 id = jedec_probe(spi);
755 763
756 if (!chip || chip != info) { 764 if (id != &m25p_ids[i]) {
757 dev_warn(&spi->dev, "found %s, expected %s\n", 765 dev_warn(&spi->dev, "found %s, expected %s\n",
758 chip ? chip->name : "UNKNOWN", 766 id ? id->name : "UNKNOWN",
759 info->name); 767 m25p_ids[i].name);
760 info = NULL; 768 info = NULL;
761 } 769 }
762 } 770 }
763 } else 771 } else {
764 info = jedec_probe(spi); 772 id = jedec_probe(spi);
773 if (!id)
774 id = spi_get_device_id(spi);
775
776 info = (void *)id->driver_data;
777 }
765 778
766 if (!info) 779 if (!info)
767 return -ENODEV; 780 return -ENODEV;
@@ -819,7 +832,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
819 832
820 flash->mtd.dev.parent = &spi->dev; 833 flash->mtd.dev.parent = &spi->dev;
821 834
822 dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name, 835 dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
823 (long long)flash->mtd.size >> 10); 836 (long long)flash->mtd.size >> 10);
824 837
825 DEBUG(MTD_DEBUG_LEVEL2, 838 DEBUG(MTD_DEBUG_LEVEL2,
@@ -907,6 +920,7 @@ static struct spi_driver m25p80_driver = {
907 .bus = &spi_bus_type, 920 .bus = &spi_bus_type,
908 .owner = THIS_MODULE, 921 .owner = THIS_MODULE,
909 }, 922 },
923 .id_table = m25p_ids,
910 .probe = m25p_probe, 924 .probe = m25p_probe,
911 .remove = __devexit_p(m25p_remove), 925 .remove = __devexit_p(m25p_remove),
912 926