diff options
Diffstat (limited to 'drivers/mtd/devices/m25p80.c')
-rw-r--r-- | drivers/mtd/devices/m25p80.c | 69 |
1 files changed, 40 insertions, 29 deletions
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 47486fbd7777..e6892851e813 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -709,6 +709,14 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | |||
709 | jedec = jedec << 8; | 709 | jedec = jedec << 8; |
710 | jedec |= id[2]; | 710 | jedec |= id[2]; |
711 | 711 | ||
712 | /* | ||
713 | * Some chips (like Numonyx M25P80) have JEDEC and non-JEDEC variants, | ||
714 | * which depend on technology process. Officially RDID command doesn't | ||
715 | * exist for non-JEDEC chips, but for compatibility they return ID 0. | ||
716 | */ | ||
717 | if (jedec == 0) | ||
718 | return NULL; | ||
719 | |||
712 | ext_jedec = id[3] << 8 | id[4]; | 720 | ext_jedec = id[3] << 8 | id[4]; |
713 | 721 | ||
714 | for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) { | 722 | for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) { |
@@ -730,7 +738,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) | |||
730 | */ | 738 | */ |
731 | static int __devinit m25p_probe(struct spi_device *spi) | 739 | static int __devinit m25p_probe(struct spi_device *spi) |
732 | { | 740 | { |
733 | const struct spi_device_id *id; | 741 | const struct spi_device_id *id = spi_get_device_id(spi); |
734 | struct flash_platform_data *data; | 742 | struct flash_platform_data *data; |
735 | struct m25p *flash; | 743 | struct m25p *flash; |
736 | struct flash_info *info; | 744 | struct flash_info *info; |
@@ -743,41 +751,44 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
743 | */ | 751 | */ |
744 | data = spi->dev.platform_data; | 752 | data = spi->dev.platform_data; |
745 | if (data && data->type) { | 753 | if (data && data->type) { |
754 | const struct spi_device_id *plat_id; | ||
755 | |||
746 | for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) { | 756 | for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) { |
747 | id = &m25p_ids[i]; | 757 | plat_id = &m25p_ids[i]; |
748 | info = (void *)m25p_ids[i].driver_data; | 758 | if (strcmp(data->type, plat_id->name)) |
749 | if (strcmp(data->type, id->name)) | ||
750 | continue; | 759 | continue; |
751 | break; | 760 | break; |
752 | } | 761 | } |
753 | 762 | ||
754 | /* unrecognized chip? */ | 763 | if (plat_id) |
755 | if (i == ARRAY_SIZE(m25p_ids) - 1) { | 764 | id = plat_id; |
756 | DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n", | 765 | else |
757 | dev_name(&spi->dev), data->type); | 766 | dev_warn(&spi->dev, "unrecognized id %s\n", data->type); |
758 | info = NULL; | ||
759 | |||
760 | /* recognized; is that chip really what's there? */ | ||
761 | } else if (info->jedec_id) { | ||
762 | id = jedec_probe(spi); | ||
763 | |||
764 | if (id != &m25p_ids[i]) { | ||
765 | dev_warn(&spi->dev, "found %s, expected %s\n", | ||
766 | id ? id->name : "UNKNOWN", | ||
767 | m25p_ids[i].name); | ||
768 | info = NULL; | ||
769 | } | ||
770 | } | ||
771 | } else { | ||
772 | id = jedec_probe(spi); | ||
773 | if (!id) | ||
774 | id = spi_get_device_id(spi); | ||
775 | |||
776 | info = (void *)id->driver_data; | ||
777 | } | 767 | } |
778 | 768 | ||
779 | if (!info) | 769 | info = (void *)id->driver_data; |
780 | return -ENODEV; | 770 | |
771 | if (info->jedec_id) { | ||
772 | const struct spi_device_id *jid; | ||
773 | |||
774 | jid = jedec_probe(spi); | ||
775 | if (!jid) { | ||
776 | dev_info(&spi->dev, "non-JEDEC variant of %s\n", | ||
777 | id->name); | ||
778 | } else if (jid != id) { | ||
779 | /* | ||
780 | * JEDEC knows better, so overwrite platform ID. We | ||
781 | * can't trust partitions any longer, but we'll let | ||
782 | * mtd apply them anyway, since some partitions may be | ||
783 | * marked read-only, and we don't want to lose that | ||
784 | * information, even if it's not 100% accurate. | ||
785 | */ | ||
786 | dev_warn(&spi->dev, "found %s, expected %s\n", | ||
787 | jid->name, id->name); | ||
788 | id = jid; | ||
789 | info = (void *)jid->driver_data; | ||
790 | } | ||
791 | } | ||
781 | 792 | ||
782 | flash = kzalloc(sizeof *flash, GFP_KERNEL); | 793 | flash = kzalloc(sizeof *flash, GFP_KERNEL); |
783 | if (!flash) | 794 | if (!flash) |