From patchwork Tue Sep 22 23:53:01 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Morton X-Patchwork-Id: 34111 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 92920B7B76 for ; Wed, 23 Sep 2009 09:55:20 +1000 (EST) Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux)) id 1MqFAw-00036k-TZ; Tue, 22 Sep 2009 23:53:38 +0000 Received: from smtp1.linux-foundation.org ([140.211.169.13]) by bombadil.infradead.org with esmtps (Exim 4.69 #1 (Red Hat Linux)) id 1MqFAn-00033s-Np for linux-mtd@lists.infradead.org; Tue, 22 Sep 2009 23:53:37 +0000 Received: from imap1.linux-foundation.org (imap1.linux-foundation.org [140.211.169.55]) by smtp1.linux-foundation.org (8.14.2/8.13.5/Debian-3ubuntu1.1) with ESMTP id n8MNr1mY031283 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 22 Sep 2009 16:53:02 -0700 Received: from localhost.localdomain (localhost [127.0.0.1]) by imap1.linux-foundation.org (8.13.5.20060308/8.13.5/Debian-3ubuntu1.1) with ESMTP id n8MNr1Eg029863; Tue, 22 Sep 2009 16:53:01 -0700 Message-Id: <200909222353.n8MNr1Eg029863@imap1.linux-foundation.org> Subject: [patch 1/3] mtd: m25p80: convert to device table matching To: dwmw2@infradead.org From: akpm@linux-foundation.org Date: Tue, 22 Sep 2009 16:53:01 -0700 MIME-Version: 1.0 X-Spam-Status: No, hits=-3.513 required=5 tests=AWL, BAYES_00, OSDL_HEADER_SUBJECT_BRACKETED X-Spam-Checker-Version: SpamAssassin 3.2.4-osdl_revision__1.47__ X-MIMEDefang-Filter: lf$Revision: 1.188 $ X-Scanned-By: MIMEDefang 2.63 on 140.211.169.13 X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.5 (LGPL) ) MR-646709E3 X-CRM114-CacheID: sfid-20090922_195330_156481_E18C11CF X-CRM114-Status: GOOD ( 22.83 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- _SUMMARY_ Cc: dbrownell@users.sourceforge.net, benh@kernel.crashing.org, grant.likely@secretlab.ca, linux-mtd@lists.infradead.org, ben-linux@fluff.org, khali@linux-fr.org, akpm@linux-foundation.org, avorontsov@ru.mvista.com X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Anton Vorontsov Convert 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 Cc: David Brownell Cc: David Woodhouse Cc: Grant Likely Cc: Jean Delvare Cc: Ben Dooks Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton --- drivers/mtd/devices/m25p80.c | 150 ++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 68 deletions(-) diff -puN drivers/mtd/devices/m25p80.c~mtd-m25p80-convert-to-device-table-matching drivers/mtd/devices/m25p80.c --- a/drivers/mtd/devices/m25p80.c~mtd-m25p80-convert-to-device-table-matching +++ a/drivers/mtd/devices/m25p80.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -462,8 +463,6 @@ static int m25p80_write(struct mtd_info */ struct flash_info { - char *name; - /* JEDEC id zero means "no ID" (most older chips); otherwise it has * a high byte of zero plus three data bytes: the manufacturer id, * then a two byte device id. @@ -481,77 +480,86 @@ struct flash_info { #define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ }; +#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + ((kernel_ulong_t)&(struct flash_info) { \ + .jedec_id = (_jedec_id), \ + .ext_id = (_ext_id), \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .flags = (_flags), \ + }) /* NOTE: double check command sets and memory organization when you add * more flash chips. This current list focusses on newer chips, which * have been converging on command sets which including JEDEC ID. */ -static struct flash_info __devinitdata m25p_data [] = { - +static const struct spi_device_id m25p_ids[] = { /* Atmel -- some are (confusingly) marketed as "DataFlash" */ - { "at25fs010", 0x1f6601, 0, 32 * 1024, 4, SECT_4K, }, - { "at25fs040", 0x1f6604, 0, 64 * 1024, 8, SECT_4K, }, + { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) }, + { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, - { "at25df041a", 0x1f4401, 0, 64 * 1024, 8, SECT_4K, }, - { "at25df641", 0x1f4800, 0, 64 * 1024, 128, SECT_4K, }, + { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) }, + { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) }, - { "at26f004", 0x1f0400, 0, 64 * 1024, 8, SECT_4K, }, - { "at26df081a", 0x1f4501, 0, 64 * 1024, 16, SECT_4K, }, - { "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, }, - { "at26df321", 0x1f4701, 0, 64 * 1024, 64, SECT_4K, }, + { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, + { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) }, + { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, + { "at26df321", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, /* Macronix */ - { "mx25l3205d", 0xc22016, 0, 64 * 1024, 64, }, - { "mx25l6405d", 0xc22017, 0, 64 * 1024, 128, }, - { "mx25l12805d", 0xc22018, 0, 64 * 1024, 256, }, - { "mx25l12855e", 0xc22618, 0, 64 * 1024, 256, }, + { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, + { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, + { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, + { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, /* Spansion -- single (large) sector size only, at least * for the chips listed here (without boot sectors). */ - { "s25sl004a", 0x010212, 0, 64 * 1024, 8, }, - { "s25sl008a", 0x010213, 0, 64 * 1024, 16, }, - { "s25sl016a", 0x010214, 0, 64 * 1024, 32, }, - { "s25sl032a", 0x010215, 0, 64 * 1024, 64, }, - { "s25sl064a", 0x010216, 0, 64 * 1024, 128, }, - { "s25sl12800", 0x012018, 0x0300, 256 * 1024, 64, }, - { "s25sl12801", 0x012018, 0x0301, 64 * 1024, 256, }, + { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, + { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, + { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, + { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, + { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, + { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, + { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, /* SST -- large erase sizes are "overlays", "sectors" are 4K */ - { "sst25vf040b", 0xbf258d, 0, 64 * 1024, 8, SECT_4K, }, - { "sst25vf080b", 0xbf258e, 0, 64 * 1024, 16, SECT_4K, }, - { "sst25vf016b", 0xbf2541, 0, 64 * 1024, 32, SECT_4K, }, - { "sst25vf032b", 0xbf254a, 0, 64 * 1024, 64, SECT_4K, }, + { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) }, + { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K) }, + { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K) }, + { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K) }, /* ST Microelectronics -- newer production may have feature updates */ - { "m25p05", 0x202010, 0, 32 * 1024, 2, }, - { "m25p10", 0x202011, 0, 32 * 1024, 4, }, - { "m25p20", 0x202012, 0, 64 * 1024, 4, }, - { "m25p40", 0x202013, 0, 64 * 1024, 8, }, - { "m25p80", 0, 0, 64 * 1024, 16, }, - { "m25p16", 0x202015, 0, 64 * 1024, 32, }, - { "m25p32", 0x202016, 0, 64 * 1024, 64, }, - { "m25p64", 0x202017, 0, 64 * 1024, 128, }, - { "m25p128", 0x202018, 0, 256 * 1024, 64, }, - - { "m45pe10", 0x204011, 0, 64 * 1024, 2, }, - { "m45pe80", 0x204014, 0, 64 * 1024, 16, }, - { "m45pe16", 0x204015, 0, 64 * 1024, 32, }, + { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, + { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) }, + { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) }, + { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) }, + { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) }, + { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) }, + { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, + { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, + { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, + + { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) }, + { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) }, + { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) }, - { "m25pe80", 0x208014, 0, 64 * 1024, 16, }, - { "m25pe16", 0x208015, 0, 64 * 1024, 32, SECT_4K, }, + { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) }, + { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ - { "w25x10", 0xef3011, 0, 64 * 1024, 2, SECT_4K, }, - { "w25x20", 0xef3012, 0, 64 * 1024, 4, SECT_4K, }, - { "w25x40", 0xef3013, 0, 64 * 1024, 8, SECT_4K, }, - { "w25x80", 0xef3014, 0, 64 * 1024, 16, SECT_4K, }, - { "w25x16", 0xef3015, 0, 64 * 1024, 32, SECT_4K, }, - { "w25x32", 0xef3016, 0, 64 * 1024, 64, SECT_4K, }, - { "w25x64", 0xef3017, 0, 64 * 1024, 128, SECT_4K, }, + { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, + { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, + { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, + { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, + { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, + { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, + { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, + { }, }; +MODULE_DEVICE_TABLE(spi, m25p_ids); -static struct flash_info *__devinit jedec_probe(struct spi_device *spi) +static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi) { int tmp; u8 code = OPCODE_RDID; @@ -578,16 +586,14 @@ static struct flash_info *__devinit jede ext_jedec = id[3] << 8 | id[4]; - for (tmp = 0, info = m25p_data; - tmp < ARRAY_SIZE(m25p_data); - tmp++, info++) { + for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) { + info = (void *)m25p_ids[tmp].driver_data; if (info->jedec_id == jedec) { if (info->ext_id != 0 && info->ext_id != ext_jedec) continue; - return info; + return &m25p_ids[tmp]; } } - dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec); return NULL; } @@ -599,6 +605,7 @@ static struct flash_info *__devinit jede */ static int __devinit m25p_probe(struct spi_device *spi) { + const struct spi_device_id *id; struct flash_platform_data *data; struct m25p *flash; struct flash_info *info; @@ -611,32 +618,38 @@ static int __devinit m25p_probe(struct s */ data = spi->dev.platform_data; if (data && data->type) { - for (i = 0, info = m25p_data; - i < ARRAY_SIZE(m25p_data); - i++, info++) { - if (strcmp(data->type, info->name) == 0) - break; + for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) { + id = &m25p_ids[i]; + info = (void *)m25p_ids[i].driver_data; + if (strcmp(data->type, id->name)) + continue; + break; } /* unrecognized chip? */ - if (i == ARRAY_SIZE(m25p_data)) { + if (i == ARRAY_SIZE(m25p_ids) - 1) { DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n", dev_name(&spi->dev), data->type); info = NULL; /* recognized; is that chip really what's there? */ } else if (info->jedec_id) { - struct flash_info *chip = jedec_probe(spi); + id = jedec_probe(spi); - if (!chip || chip != info) { + if (id != &m25p_ids[i]) { dev_warn(&spi->dev, "found %s, expected %s\n", - chip ? chip->name : "UNKNOWN", - info->name); + id ? id->name : "UNKNOWN", + m25p_ids[i].name); info = NULL; } } - } else - info = jedec_probe(spi); + } else { + id = jedec_probe(spi); + if (!id) + id = spi_get_device_id(spi); + + info = (void *)id->driver_data; + } if (!info) return -ENODEV; @@ -683,7 +696,7 @@ static int __devinit m25p_probe(struct s flash->mtd.dev.parent = &spi->dev; - dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name, + dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name, (long long)flash->mtd.size >> 10); DEBUG(MTD_DEBUG_LEVEL2, @@ -769,6 +782,7 @@ static struct spi_driver m25p80_driver = .bus = &spi_bus_type, .owner = THIS_MODULE, }, + .id_table = m25p_ids, .probe = m25p_probe, .remove = __devexit_p(m25p_remove),