summaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
commit62b8c978ee6b8d135d9e7953221de58000dba986 (patch)
tree683b04b2e627f6710c22c151b23c8cc9a165315e /drivers/mtd
parent78fd82238d0e5716578c326404184a27ba67fd6e (diff)
downloadlinux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/bcm47xxpart.c23
-rw-r--r--drivers/mtd/devices/Kconfig7
-rw-r--r--drivers/mtd/devices/block2mtd.c1
-rw-r--r--drivers/mtd/devices/docg3.c2
-rw-r--r--drivers/mtd/devices/m25p80.c82
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c4
-rw-r--r--drivers/mtd/devices/phram.c66
-rw-r--r--drivers/mtd/devices/sst25l.c13
-rw-r--r--drivers/mtd/inftlcore.c2
-rw-r--r--drivers/mtd/lpddr/lpddr_cmds.c2
-rw-r--r--drivers/mtd/maps/intel_vr_nor.c1
-rw-r--r--drivers/mtd/maps/pci.c1
-rw-r--r--drivers/mtd/maps/plat-ram.c18
-rw-r--r--drivers/mtd/maps/scb2_flash.c1
-rw-r--r--drivers/mtd/mtdblock.c3
-rw-r--r--drivers/mtd/mtdblock_ro.c3
-rw-r--r--drivers/mtd/mtdchar.c7
-rw-r--r--drivers/mtd/mtdcore.c3
-rw-r--r--drivers/mtd/mtdsuper.c1
-rw-r--r--drivers/mtd/nand/Kconfig40
-rw-r--r--drivers/mtd/nand/atmel_nand.c83
-rw-r--r--drivers/mtd/nand/bcm47xxnflash/main.c38
-rw-r--r--drivers/mtd/nand/denali.c4
-rw-r--r--drivers/mtd/nand/denali_pci.c1
-rw-r--r--drivers/mtd/nand/diskonchip.c2
-rw-r--r--drivers/mtd/nand/docg4.c18
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c3
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c135
-rw-r--r--drivers/mtd/nand/fsl_upm.c1
-rw-r--r--drivers/mtd/nand/fsmc_nand.c2
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-lib.c13
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c66
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-regs.h3
-rw-r--r--drivers/mtd/nand/lpc32xx_mlc.c2
-rw-r--r--drivers/mtd/nand/lpc32xx_slc.c10
-rw-r--r--drivers/mtd/nand/mpc5121_nfc.c2
-rw-r--r--drivers/mtd/nand/mxc_nand.c5
-rw-r--r--drivers/mtd/nand/nand_base.c305
-rw-r--r--drivers/mtd/nand/nand_bbt.c38
-rw-r--r--drivers/mtd/nand/nandsim.c4
-rw-r--r--drivers/mtd/nand/ndfc.c1
-rw-r--r--drivers/mtd/nand/omap2.c642
-rw-r--r--drivers/mtd/nand/pasemi_nand.c2
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c56
-rw-r--r--drivers/mtd/nand/r852.c2
-rw-r--r--drivers/mtd/nand/socrates_nand.c15
-rw-r--r--drivers/mtd/nand/tmio_nand.c3
-rw-r--r--drivers/mtd/nftlcore.c2
-rw-r--r--drivers/mtd/onenand/omap2.c32
-rw-r--r--drivers/mtd/onenand/onenand_base.c17
-rw-r--r--drivers/mtd/ssfdc.c2
-rw-r--r--drivers/mtd/tests/nandbiterrs.c2
-rw-r--r--drivers/mtd/tests/oobtest.c2
-rw-r--r--drivers/mtd/tests/pagetest.c2
-rw-r--r--drivers/mtd/tests/subpagetest.c2
-rw-r--r--drivers/mtd/ubi/attach.c11
-rw-r--r--drivers/mtd/ubi/build.c1
-rw-r--r--drivers/mtd/ubi/fastmap.c41
-rw-r--r--drivers/mtd/ubi/wl.c4
59 files changed, 971 insertions, 883 deletions
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c
index 7a6384b..9279a91 100644
--- a/drivers/mtd/bcm47xxpart.c
+++ b/drivers/mtd/bcm47xxpart.c
@@ -27,13 +27,11 @@
/* Magics */
#define BOARD_DATA_MAGIC 0x5246504D /* MPFR */
-#define FACTORY_MAGIC 0x59544346 /* FCTY */
#define POT_MAGIC1 0x54544f50 /* POTT */
#define POT_MAGIC2 0x504f /* OP */
#define ML_MAGIC1 0x39685a42
#define ML_MAGIC2 0x26594131
#define TRX_MAGIC 0x30524448
-#define SQSH_MAGIC 0x71736873 /* shsq */
struct trx_header {
uint32_t magic;
@@ -73,14 +71,7 @@ static int bcm47xxpart_parse(struct mtd_info *master,
/* Alloc */
parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS,
GFP_KERNEL);
- if (!parts)
- return -ENOMEM;
-
buf = kzalloc(BCM47XXPART_BYTES_TO_READ, GFP_KERNEL);
- if (!buf) {
- kfree(parts);
- return -ENOMEM;
- }
/* Parse block by block looking for magics */
for (offset = 0; offset <= master->size - blocksize;
@@ -119,13 +110,6 @@ static int bcm47xxpart_parse(struct mtd_info *master,
continue;
}
- /* Found on Huawei E970 */
- if (buf[0x000 / 4] == FACTORY_MAGIC) {
- bcm47xxpart_add_part(&parts[curr_part++], "factory",
- offset, MTD_WRITEABLE);
- continue;
- }
-
/* POT(TOP) */
if (buf[0x000 / 4] == POT_MAGIC1 &&
(buf[0x004 / 4] & 0xFFFF) == POT_MAGIC2) {
@@ -183,13 +167,6 @@ static int bcm47xxpart_parse(struct mtd_info *master,
offset = rounddown(offset + trx->length, blocksize);
continue;
}
-
- /* Squashfs on devices not using TRX */
- if (buf[0x000 / 4] == SQSH_MAGIC) {
- bcm47xxpart_add_part(&parts[curr_part++], "rootfs",
- offset, 0);
- continue;
- }
}
/* Look for NVRAM at the end of the last block. */
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 0128138..74ab4b7 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -95,6 +95,13 @@ config MTD_M25P80
if you want to specify device partitioning or to use a device which
doesn't support the JEDEC ID instruction.
+config M25PXX_USE_FAST_READ
+ bool "Use FAST_READ OPCode allowing SPI CLK >= 50MHz"
+ depends on MTD_M25P80
+ default y
+ help
+ This option enables FAST_READ access supported by ST M25Pxx.
+
config MTD_SPEAR_SMI
tristate "SPEAR MTD NOR Support through SMI controller"
depends on PLAT_SPEAR
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index d9fd87a..5cb4c04 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -20,7 +20,6 @@
#include <linux/mutex.h>
#include <linux/mount.h>
#include <linux/slab.h>
-#include <linux/major.h>
/* Info for the block device */
struct block2mtd_dev {
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index 4f091c1..3e1b0a0 100644
--- a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -2097,7 +2097,7 @@ notfound:
ret = -ENODEV;
dev_info(dev, "No supported DiskOnChip found\n");
err_probe:
- free_bch(cascade->bch);
+ kfree(cascade->bch);
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
if (cascade->floors[floor])
doc_release_device(cascade->floors[floor]);
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 7eda71d..6bc9618 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -78,7 +78,7 @@
/* Define max times to check status register before we give up. */
#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */
-#define MAX_CMD_SIZE 6
+#define MAX_CMD_SIZE 5
#define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16)
@@ -367,6 +367,10 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
spi_message_init(&m);
memset(t, 0, (sizeof t));
+ /* NOTE:
+ * OPCODE_FAST_READ (if available) is faster.
+ * Should add 1 byte DUMMY_BYTE.
+ */
t[0].tx_buf = flash->command;
t[0].len = m25p_cmdsz(flash) + (flash->fast_read ? 1 : 0);
spi_message_add_tail(&t[0], &m);
@@ -384,6 +388,11 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
return 1;
}
+ /* FIXME switch to OPCODE_FAST_READ. It's required for higher
+ * clocks; and at this writing, every chip this driver handles
+ * supports that opcode.
+ */
+
/* Set up the write data buffer. */
opcode = flash->read_opcode;
flash->command[0] = opcode;
@@ -740,19 +749,16 @@ static const struct spi_device_id m25p_ids[] = {
{ "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) },
/* EON -- en25xxx */
- { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
- { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
- { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
- { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
- { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
- { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
-
- /* ESMT */
- { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) },
+ { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
+ { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
+ { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
+ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
+ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
+ { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
/* Everspin */
- { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, M25P_NO_ERASE | M25P_NO_FR) },
- { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, M25P_NO_ERASE | M25P_NO_FR) },
+ { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, M25P_NO_ERASE | M25P_NO_FR) },
+ { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, M25P_NO_ERASE | M25P_NO_FR) },
/* GigaDevice */
{ "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) },
@@ -769,7 +775,6 @@ static const struct spi_device_id m25p_ids[] = {
{ "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
{ "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) },
{ "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) },
- { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
{ "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) },
{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
@@ -778,16 +783,15 @@ static const struct spi_device_id m25p_ids[] = {
{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) },
/* Micron */
- { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
- { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
- { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
- { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
- { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) },
+ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
+ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
+ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
/* PMC */
- { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
- { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
- { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) },
+ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
+ { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
+ { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) },
/* Spansion -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
@@ -936,7 +940,12 @@ static int m25p_probe(struct spi_device *spi)
struct flash_info *info;
unsigned i;
struct mtd_part_parser_data ppdata;
- struct device_node *np = spi->dev.of_node;
+ struct device_node __maybe_unused *np = spi->dev.of_node;
+
+#ifdef CONFIG_MTD_OF_PARTS
+ if (!of_device_is_available(np))
+ return -ENODEV;
+#endif
/* Platform data helps sort out which chip type we have, as
* well as how this board partitions it. If we don't have
@@ -983,13 +992,15 @@ static int m25p_probe(struct spi_device *spi)
}
}
- flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL);
+ flash = kzalloc(sizeof *flash, GFP_KERNEL);
if (!flash)
return -ENOMEM;
-
- flash->command = devm_kzalloc(&spi->dev, MAX_CMD_SIZE, GFP_KERNEL);
- if (!flash->command)
+ flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0),
+ GFP_KERNEL);
+ if (!flash->command) {
+ kfree(flash);
return -ENOMEM;
+ }
flash->spi = spi;
mutex_init(&flash->lock);
@@ -1051,14 +1062,13 @@ static int m25p_probe(struct spi_device *spi)
flash->page_size = info->page_size;
flash->mtd.writebufsize = flash->page_size;
- if (np)
- /* If we were instantiated by DT, use it */
- flash->fast_read = of_property_read_bool(np, "m25p,fast-read");
- else
- /* If we weren't instantiated by DT, default to fast-read */
+ flash->fast_read = false;
+ if (np && of_property_read_bool(np, "m25p,fast-read"))
flash->fast_read = true;
- /* Some devices cannot do fast-read, no matter what DT tells us */
+#ifdef CONFIG_M25PXX_USE_FAST_READ
+ flash->fast_read = true;
+#endif
if (info->flags & M25P_NO_FR)
flash->fast_read = false;
@@ -1123,9 +1133,15 @@ static int m25p_probe(struct spi_device *spi)
static int m25p_remove(struct spi_device *spi)
{
struct m25p *flash = spi_get_drvdata(spi);
+ int status;
/* Clean up MTD stuff. */
- return mtd_device_unregister(&flash->mtd);
+ status = mtd_device_unregister(&flash->mtd);
+ if (status == 0) {
+ kfree(flash->command);
+ kfree(flash);
+ }
+ return 0;
}
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 4a47b02..0e8cbfe 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -88,6 +88,8 @@ struct dataflash {
uint8_t command[4];
char name[24];
+ unsigned partitioned:1;
+
unsigned short page_offset; /* offset in flash address */
unsigned int page_size; /* of bytes per page */
@@ -879,7 +881,7 @@ static int dataflash_probe(struct spi_device *spi)
break;
/* obsolete AT45DB1282 not (yet?) supported */
default:
- dev_info(&spi->dev, "unsupported device (%x)\n",
+ pr_debug("%s: unsupported device (%x)\n", dev_name(&spi->dev),
status & 0x3c);
status = -ENODEV;
}
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index e1f2aeb..67823de 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -94,7 +94,7 @@ static void unregister_devices(void)
}
}
-static int register_device(char *name, phys_addr_t start, size_t len)
+static int register_device(char *name, unsigned long start, unsigned long len)
{
struct phram_mtd_list *new;
int ret = -ENOMEM;
@@ -141,35 +141,35 @@ out0:
return ret;
}
-static int parse_num64(uint64_t *num64, char *token)
+static int ustrtoul(const char *cp, char **endp, unsigned int base)
{
- size_t len;
- int shift = 0;
- int ret;
-
- len = strlen(token);
+ unsigned long result = simple_strtoul(cp, endp, base);
+
+ switch (**endp) {
+ case 'G':
+ result *= 1024;
+ case 'M':
+ result *= 1024;
+ case 'k':
+ result *= 1024;
/* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */
- if (len > 2) {
- if (token[len - 1] == 'i') {
- switch (token[len - 2]) {
- case 'G':
- shift += 10;
- case 'M':
- shift += 10;
- case 'k':
- shift += 10;
- token[len - 2] = 0;
- break;
- default:
- return -EINVAL;
- }
- }
+ if ((*endp)[1] == 'i')
+ (*endp) += 2;
}
+ return result;
+}
- ret = kstrtou64(token, 0, num64);
- *num64 <<= shift;
+static int parse_num32(uint32_t *num32, const char *token)
+{
+ char *endp;
+ unsigned long n;
- return ret;
+ n = ustrtoul(token, &endp, 0);
+ if (*endp)
+ return -EINVAL;
+
+ *num32 = n;
+ return 0;
}
static int parse_name(char **pname, const char *token)
@@ -209,19 +209,19 @@ static inline void kill_final_newline(char *str)
* This shall contain the module parameter if any. It is of the form:
* - phram=<device>,<address>,<size> for module case
* - phram.phram=<device>,<address>,<size> for built-in case
- * We leave 64 bytes for the device name, 20 for the address and 20 for the
+ * We leave 64 bytes for the device name, 12 for the address and 12 for the
* size.
* Example: phram.phram=rootfs,0xa0000000,512Mi
*/
-static __initdata char phram_paramline[64 + 20 + 20];
+static __initdata char phram_paramline[64+12+12];
static int __init phram_setup(const char *val)
{
- char buf[64 + 20 + 20], *str = buf;
+ char buf[64+12+12], *str = buf;
char *token[3];
char *name;
- uint64_t start;
- uint64_t len;
+ uint32_t start;
+ uint32_t len;
int i, ret;
if (strnlen(val, sizeof(buf)) >= sizeof(buf))
@@ -243,13 +243,13 @@ static int __init phram_setup(const char *val)
if (ret)
return ret;
- ret = parse_num64(&start, token[1]);
+ ret = parse_num32(&start, token[1]);
if (ret) {
kfree(name);
parse_err("illegal start address\n");
}
- ret = parse_num64(&len, token[2]);
+ ret = parse_num32(&len, token[2]);
if (ret) {
kfree(name);
parse_err("illegal device length\n");
@@ -257,7 +257,7 @@ static int __init phram_setup(const char *val)
ret = register_device(name, start, len);
if (!ret)
- pr_info("%s device: %#llx at %#llx\n", name, len, start);
+ pr_info("%s device: %#x at %#x\n", name, len, start);
else
kfree(name);
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index 687bf27..a42f1f0 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -364,7 +364,7 @@ static int sst25l_probe(struct spi_device *spi)
if (!flash_info)
return -ENODEV;
- flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL);
+ flash = kzalloc(sizeof(struct sst25l_flash), GFP_KERNEL);
if (!flash)
return -ENOMEM;
@@ -402,8 +402,11 @@ static int sst25l_probe(struct spi_device *spi)
ret = mtd_device_parse_register(&flash->mtd, NULL, NULL,
data ? data->parts : NULL,
data ? data->nr_parts : 0);
- if (ret)
+ if (ret) {
+ kfree(flash);
+ spi_set_drvdata(spi, NULL);
return -ENODEV;
+ }
return 0;
}
@@ -411,8 +414,12 @@ static int sst25l_probe(struct spi_device *spi)
static int sst25l_remove(struct spi_device *spi)
{
struct sst25l_flash *flash = spi_get_drvdata(spi);
+ int ret;
- return mtd_device_unregister(&flash->mtd);
+ ret = mtd_device_unregister(&flash->mtd);
+ if (ret == 0)
+ kfree(flash);
+ return ret;
}
static struct spi_driver sst25l_driver = {
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index b66b541..3af3514 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -50,7 +50,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
struct INFTLrecord *inftl;
unsigned long temp;
- if (!mtd_type_is_nand(mtd) || mtd->size > UINT_MAX)
+ if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX)
return;
/* OK, this is moderately ugly. But probably safe. Alternatives? */
if (memcmp(mtd->name, "DiskOnChip", 10))
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c
index 2ef19aa..d3cfe26b 100644
--- a/drivers/mtd/lpddr/lpddr_cmds.c
+++ b/drivers/mtd/lpddr/lpddr_cmds.c
@@ -703,7 +703,7 @@ static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr)
#define DO_XXLOCK_LOCK 1
#define DO_XXLOCK_UNLOCK 2
-static int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk)
+int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk)
{
int ret = 0;
struct map_info *map = mtd->priv;
diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
index 46d195f..f581ac1 100644
--- a/drivers/mtd/maps/intel_vr_nor.c
+++ b/drivers/mtd/maps/intel_vr_nor.c
@@ -180,6 +180,7 @@ static void vr_nor_pci_remove(struct pci_dev *dev)
{
struct vr_nor_mtd *p = pci_get_drvdata(dev);
+ pci_set_drvdata(dev, NULL);
vr_nor_destroy_partitions(p);
vr_nor_destroy_mtd_setup(p);
vr_nor_destroy_maps(p);
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
index 36da518..c2604f8 100644
--- a/drivers/mtd/maps/pci.c
+++ b/drivers/mtd/maps/pci.c
@@ -316,6 +316,7 @@ static void mtd_pci_remove(struct pci_dev *dev)
map->exit(dev, map);
kfree(map);
+ pci_set_drvdata(dev, NULL);
pci_release_regions(dev);
}
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 10196f5..6762716 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -55,7 +55,7 @@ struct platram_info {
static inline struct platram_info *to_platram_info(struct platform_device *dev)
{
- return platform_get_drvdata(dev);
+ return (struct platram_info *)platform_get_drvdata(dev);
}
/* platram_setrw
@@ -257,7 +257,21 @@ static struct platform_driver platram_driver = {
},
};
-module_platform_driver(platram_driver);
+/* module init/exit */
+
+static int __init platram_init(void)
+{
+ printk("Generic platform RAM MTD, (c) 2004 Simtec Electronics\n");
+ return platform_driver_register(&platram_driver);
+}
+
+static void __exit platram_exit(void)
+{
+ platform_driver_unregister(&platram_driver);
+}
+
+module_init(platram_init);
+module_exit(platram_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c
index 3051c4c..c77b68c 100644
--- a/drivers/mtd/maps/scb2_flash.c
+++ b/drivers/mtd/maps/scb2_flash.c
@@ -212,6 +212,7 @@ static void scb2_flash_remove(struct pci_dev *dev)
if (!region_fail)
release_mem_region(SCB2_ADDR, SCB2_WINDOW);
+ pci_set_drvdata(dev, NULL);
}
static struct pci_device_id scb2_flash_pci_ids[] = {
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index 485ea75..2aef5dd 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -32,7 +32,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/blktrans.h>
#include <linux/mutex.h>
-#include <linux/major.h>
struct mtdblk_dev {
@@ -374,7 +373,7 @@ static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev)
static struct mtd_blktrans_ops mtdblock_tr = {
.name = "mtdblock",
- .major = MTD_BLOCK_MAJOR,
+ .major = 31,
.part_bits = 0,
.blksize = 512,
.open = mtdblock_open,
diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
index fb5dc89..92759a9 100644
--- a/drivers/mtd/mtdblock_ro.c
+++ b/drivers/mtd/mtdblock_ro.c
@@ -24,7 +24,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/blktrans.h>
#include <linux/module.h>
-#include <linux/major.h>
static int mtdblock_readsect(struct mtd_blktrans_dev *dev,
unsigned long block, char *buf)
@@ -71,7 +70,7 @@ static void mtdblock_remove_dev(struct mtd_blktrans_dev *dev)
static struct mtd_blktrans_ops mtdblock_tr = {
.name = "mtdblock",
- .major = MTD_BLOCK_MAJOR,
+ .major = 31,
.part_bits = 0,
.blksize = 512,
.readsect = mtdblock_readsect,
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 2147e73..684bfa3 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -32,7 +32,6 @@
#include <linux/mount.h>
#include <linux/blkpg.h>
#include <linux/magic.h>
-#include <linux/major.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/map.h>
@@ -1100,7 +1099,7 @@ static unsigned long mtdchar_get_unmapped_area(struct file *file,
return (unsigned long) -EINVAL;
ret = mtd_get_unmapped_area(mtd, len, offset, flags);
- return ret == -EOPNOTSUPP ? -ENODEV : ret;
+ return ret == -EOPNOTSUPP ? -ENOSYS : ret;
}
#endif
@@ -1125,9 +1124,9 @@ static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)
#endif
return vm_iomap_memory(vma, map->phys, map->size);
}
- return -ENODEV;
+ return -ENOSYS;
#else
- return vma->vm_flags & VM_SHARED ? 0 : -EACCES;
+ return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS;
#endif
}
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 92311a5..5e14d54 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -157,9 +157,6 @@ static ssize_t mtd_type_show(struct device *dev,
case MTD_UBIVOLUME:
type = "ubi";
break;
- case MTD_MLCNANDFLASH:
- type = "mlc-nand";
- break;
default:
type = "unknown";
}
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c
index 20c02a3..334da5f 100644
--- a/drivers/mtd/mtdsuper.c
+++ b/drivers/mtd/mtdsuper.c
@@ -17,7 +17,6 @@
#include <linux/export.h>
#include <linux/ctype.h>
#include <linux/slab.h>
-#include <linux/major.h>
/*
* compare superblocks to see if they're equivalent
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 93ae6a6..d885298 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -96,15 +96,43 @@ config MTD_NAND_OMAP2
config MTD_NAND_OMAP_BCH
depends on MTD_NAND && MTD_NAND_OMAP2 && ARCH_OMAP3
- tristate "Support hardware based BCH error correction"
+ tristate "Enable support for hardware BCH error correction"
default n
select BCH
+ select BCH_CONST_PARAMS
help
- This config enables the ELM hardware engine, which can be used to
- locate and correct errors when using BCH ECC scheme. This offloads
- the cpu from doing ECC error searching and correction. However some
- legacy OMAP families like OMAP2xxx, OMAP3xxx do not have ELM engine
- so they should not enable this config symbol.
+ Support for hardware BCH error correction.
+
+choice
+ prompt "BCH error correction capability"
+ depends on MTD_NAND_OMAP_BCH
+
+config MTD_NAND_OMAP_BCH8
+ bool "8 bits / 512 bytes (recommended)"
+ help
+ Support correcting up to 8 bitflips per 512-byte block.
+ This will use 13 bytes of spare area per 512 bytes of page data.
+ This is the recommended mode, as 4-bit mode does not work
+ on some OMAP3 revisions, due to a hardware bug.
+
+config MTD_NAND_OMAP_BCH4
+ bool "4 bits / 512 bytes"
+ help
+ Support correcting up to 4 bitflips per 512-byte block.
+ This will use 7 bytes of spare area per 512 bytes of page data.
+ Note that this mode does not work on some OMAP3 revisions, due to a
+ hardware bug. Please check your OMAP datasheet before selecting this
+ mode.
+
+endchoice
+
+if MTD_NAND_OMAP_BCH
+config BCH_CONST_M
+ default 13
+config BCH_CONST_T
+ default 4 if MTD_NAND_OMAP_BCH4
+ default 8 if MTD_NAND_OMAP_BCH8
+endif
config MTD_NAND_IDS
tristate
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 59f08c4..060feea 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -375,7 +375,8 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
dma_dev = host->dma_chan->device;
- flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+ flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP |
+ DMA_COMPL_SKIP_DEST_UNMAP;
phys_addr = dma_map_single(dma_dev->dev, p, len, dir);
if (dma_mapping_error(dma_dev->dev, phys_addr)) {
@@ -1061,28 +1062,56 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
}
/*
- * Get minimum ecc requirements from NAND.
+ * Get ECC requirement in ONFI parameters, returns -1 if ONFI
+ * parameters is not supported.
+ * return 0 if success to get the ECC requirement.
+ */
+static int get_onfi_ecc_param(struct nand_chip *chip,
+ int *ecc_bits, int *sector_size)
+{
+ *ecc_bits = *sector_size = 0;
+
+ if (chip->onfi_params.ecc_bits == 0xff)
+ /* TODO: the sector_size and ecc_bits need to be find in
+ * extended ecc parameter, currently we don't support it.
+ */
+ return -1;
+
+ *ecc_bits = chip->onfi_params.ecc_bits;
+
+ /* The default sector size (ecc codeword size) is 512 */
+ *sector_size = 512;
+
+ return 0;
+}
+
+/*
+ * Get ecc requirement from ONFI parameters ecc requirement.
* If pmecc-cap, pmecc-sector-size in DTS are not specified, this function
- * will set them according to minimum ecc requirement. Otherwise, use the
+ * will set them according to ONFI ecc requirement. Otherwise, use the
* value in DTS file.
* return 0 if success. otherwise return error code.
*/
static int pmecc_choose_ecc(struct atmel_nand_host *host,
int *cap, int *sector_size)
{
- /* Get minimum ECC requirements */
- if (host->nand_chip.ecc_strength_ds) {
- *cap = host->nand_chip.ecc_strength_ds;
- *sector_size = host->nand_chip.ecc_step_ds;
- dev_info(host->dev, "minimum ECC: %d bits in %d bytes\n",
+ /* Get ECC requirement from ONFI parameters */
+ *cap = *sector_size = 0;
+ if (host->nand_chip.onfi_version) {
+ if (!get_onfi_ecc_param(&host->nand_chip, cap, sector_size))
+ dev_info(host->dev, "ONFI params, minimum required ECC: %d bits in %d bytes\n",
*cap, *sector_size);
+ else
+ dev_info(host->dev, "NAND chip ECC reqirement is in Extended ONFI parameter, we don't support yet.\n");
} else {
+ dev_info(host->dev, "NAND chip is not ONFI compliant, assume ecc_bits is 2 in 512 bytes");
+ }
+ if (*cap == 0 && *sector_size == 0) {
*cap = 2;
*sector_size = 512;
- dev_info(host->dev, "can't detect min. ECC, assume 2 bits in 512 bytes\n");
}
- /* If device tree doesn't specify, use NAND's minimum ECC parameters */
+ /* If dts file doesn't specify then use the one in ONFI parameters */
if (host->pmecc_corr_cap == 0) {
/* use the most fitable ecc bits (the near bigger one ) */
if (*cap <= 2)
@@ -1110,7 +1139,7 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host,
return 0;
}
-static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
+static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
struct atmel_nand_host *host)
{
struct mtd_info *mtd = &host->mtd;
@@ -1420,6 +1449,7 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
}
+#if defined(CONFIG_OF)
static int atmel_of_init_port(struct atmel_nand_host *host,
struct device_node *np)
{
@@ -1427,7 +1457,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
u32 offset[2];
int ecc_mode;
struct atmel_nand_data *board = &host->board;
- enum of_gpio_flags flags = 0;
+ enum of_gpio_flags flags;
if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) {
if (val >= 32) {
@@ -1510,8 +1540,15 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
return 0;
}
+#else
+static int atmel_of_init_port(struct atmel_nand_host *host,
+ struct device_node *np)
+{
+ return -EINVAL;
+}
+#endif
-static int atmel_hw_nand_init_params(struct platform_device *pdev,
+static int __init atmel_hw_nand_init_params(struct platform_device *pdev,
struct atmel_nand_host *host)
{
struct mtd_info *mtd = &host->mtd;
@@ -1950,7 +1987,7 @@ static struct platform_driver atmel_nand_nfc_driver;
/*
* Probe for the NAND device.
*/
-static int atmel_nand_probe(struct platform_device *pdev)
+static int __init atmel_nand_probe(struct platform_device *pdev)
{
struct atmel_nand_host *host;
struct mtd_info *mtd;
@@ -1982,8 +2019,7 @@ static int atmel_nand_probe(struct platform_device *pdev)
mtd = &host->mtd;
nand_chip = &host->nand_chip;
host->dev = &pdev->dev;
- if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
- /* Only when CONFIG_OF is enabled of_node can be parsed */
+ if (pdev->dev.of_node) {
res = atmel_of_init_port(host, pdev->dev.of_node);
if (res)
goto err_nand_ioremap;
@@ -2141,13 +2177,14 @@ err_no_card:
if (host->dma_chan)
dma_release_channel(host->dma_chan);
err_nand_ioremap:
+ platform_driver_unregister(&atmel_nand_nfc_driver);
return res;
}
/*
* Remove a NAND device.
*/
-static int atmel_nand_remove(struct platform_device *pdev)
+static int __exit atmel_nand_remove(struct platform_device *pdev)
{
struct atmel_nand_host *host = platform_get_drvdata(pdev);
struct mtd_info *mtd = &host->mtd;
@@ -2170,12 +2207,14 @@ static int atmel_nand_remove(struct platform_device *pdev)
return 0;
}
+#if defined(CONFIG_OF)
static const struct of_device_id atmel_nand_dt_ids[] = {
{ .compatible = "atmel,at91rm9200-nand" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids);
+#endif
static int atmel_nand_nfc_probe(struct platform_device *pdev)
{
@@ -2214,11 +2253,12 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id atmel_nand_nfc_match[] = {
+#if defined(CONFIG_OF)
+static struct of_device_id atmel_nand_nfc_match[] = {
{ .compatible = "atmel,sama5d3-nfc" },
{ /* sentinel */ }
};
-MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match);
+#endif
static struct platform_driver atmel_nand_nfc_driver = {
.driver = {
@@ -2230,8 +2270,7 @@ static struct platform_driver atmel_nand_nfc_driver = {
};
static struct platform_driver atmel_nand_driver = {
- .probe = atmel_nand_probe,
- .remove = atmel_nand_remove,
+ .remove = __exit_p(atmel_nand_remove),
.driver = {
.name = "atmel_nand",
.owner = THIS_MODULE,
@@ -2239,7 +2278,7 @@ static struct platform_driver atmel_nand_driver = {
},
};
-module_platform_driver(atmel_nand_driver);
+module_platform_driver_probe(atmel_nand_driver, atmel_nand_probe);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rick Bronson");
diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c
index 1074459..7bae569 100644
--- a/drivers/mtd/nand/bcm47xxnflash/main.c
+++ b/drivers/mtd/nand/bcm47xxnflash/main.c
@@ -29,9 +29,11 @@ static int bcm47xxnflash_probe(struct platform_device *pdev)
struct bcm47xxnflash *b47n;
int err = 0;
- b47n = devm_kzalloc(&pdev->dev, sizeof(*b47n), GFP_KERNEL);
- if (!b47n)
- return -ENOMEM;
+ b47n = kzalloc(sizeof(*b47n), GFP_KERNEL);
+ if (!b47n) {
+ err = -ENOMEM;
+ goto out;
+ }
b47n->nand_chip.priv = b47n;
b47n->mtd.owner = THIS_MODULE;
@@ -46,16 +48,22 @@ static int bcm47xxnflash_probe(struct platform_device *pdev)
}
if (err) {
pr_err("Initialization failed: %d\n", err);
- return err;
+ goto err_init;
}
err = mtd_device_parse_register(&b47n->mtd, probes, NULL, NULL, 0);
if (err) {
pr_err("Failed to register MTD device: %d\n", err);
- return err;
+ goto err_dev_reg;
}
return 0;
+
+err_dev_reg:
+err_init:
+ kfree(b47n);
+out:
+ return err;
}
static int bcm47xxnflash_remove(struct platform_device *pdev)
@@ -77,4 +85,22 @@ static struct platform_driver bcm47xxnflash_driver = {
},
};
-module_platform_driver(bcm47xxnflash_driver);
+static int __init bcm47xxnflash_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&bcm47xxnflash_driver);
+ if (err)
+ pr_err("Failed to register bcm47xx nand flash driver: %d\n",
+ err);
+
+ return err;
+}
+
+static void __exit bcm47xxnflash_exit(void)
+{
+ platform_driver_unregister(&bcm47xxnflash_driver);
+}
+
+module_init(bcm47xxnflash_init);
+module_exit(bcm47xxnflash_exit);
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 370b9dd..2ed2bb3 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1394,7 +1394,7 @@ static struct nand_bbt_descr bbt_mirror_descr = {
};
/* initialize driver data structures */
-static void denali_drv_init(struct denali_nand_info *denali)
+void denali_drv_init(struct denali_nand_info *denali)
{
denali->idx = 0;
@@ -1520,7 +1520,7 @@ int denali_init(struct denali_nand_info *denali)
* so just let controller do 15bit ECC for MLC and 8bit ECC for
* SLC if possible.
* */
- if (!nand_is_slc(&denali->nand) &&
+ if (denali->nand.cellinfo & NAND_CI_CELLTYPE_MSK &&
(denali->mtd.oobsize > (denali->bbtskipbytes +
ECC_15BITS * (denali->mtd.writesize /
ECC_SECTOR_SIZE)))) {
diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c
index 033f177..e3e4662 100644
--- a/drivers/mtd/nand/denali_pci.c
+++ b/drivers/mtd/nand/denali_pci.c
@@ -119,6 +119,7 @@ static void denali_pci_remove(struct pci_dev *dev)
iounmap(denali->flash_mem);
pci_release_regions(dev);
pci_disable_device(dev);
+ pci_set_drvdata(dev, NULL);
kfree(denali);
}
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index b68a495..eaa3c29 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -38,7 +38,7 @@
#define CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS 0
#endif
-static unsigned long doc_locations[] __initdata = {
+static unsigned long __initdata doc_locations[] = {
#if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)
#ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH
0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index 1b0265e..548db23 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -44,7 +44,6 @@
#include <linux/mtd/nand.h>
#include <linux/bch.h>
#include <linux/bitrev.h>
-#include <linux/jiffies.h>
/*
* In "reliable mode" consecutive 2k pages are used in parallel (in some
@@ -270,7 +269,7 @@ static int poll_status(struct docg4_priv *doc)
*/
uint16_t flash_status;
- unsigned long timeo;
+ unsigned int timeo;
void __iomem *docptr = doc->virtadr;
dev_dbg(doc->dev, "%s...\n", __func__);
@@ -278,18 +277,22 @@ static int poll_status(struct docg4_priv *doc)
/* hardware quirk requires reading twice initially */
flash_status = readw(docptr + DOC_FLASHCONTROL);
- timeo = jiffies + msecs_to_jiffies(200); /* generous timeout */
+ timeo = 1000;
do {
cpu_relax();
flash_status = readb(docptr + DOC_FLASHCONTROL);
- } while (!(flash_status & DOC_CTRL_FLASHREADY) &&
- time_before(jiffies, timeo));
+ } while (!(flash_status & DOC_CTRL_FLASHREADY) && --timeo);
- if (unlikely(!(flash_status & DOC_CTRL_FLASHREADY))) {
+
+ if (!timeo) {
dev_err(doc->dev, "%s: timed out!\n", __func__);
return NAND_STATUS_FAIL;
}
+ if (unlikely(timeo < 50))
+ dev_warn(doc->dev, "%s: nearly timed out; %d remaining\n",
+ __func__, timeo);
+
return 0;
}
@@ -491,7 +494,7 @@ static uint8_t docg4_read_byte(struct mtd_info *mtd)
return status;
}
- dev_warn(doc->dev, "unexpected call to read_byte()\n");
+ dev_warn(doc->dev, "unexpectd call to read_byte()\n");
return 0;
}
@@ -1236,6 +1239,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
nand->block_markbad = docg4_block_markbad;
nand->read_buf = docg4_read_buf;
nand->write_buf = docg4_write_buf16;
+ nand->scan_bbt = nand_default_bbt;
nand->erase_cmd = docg4_erase_block;
nand->ecc.read_page = docg4_read_page;
nand->ecc.write_page = docg4_write_page;
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index c966fc7..2065720 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -28,7 +28,6 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ioport.h>
-#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -651,6 +650,8 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
chip->page_shift);
dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
chip->phys_erase_shift);
+ dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
+ chip->ecclayout);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
chip->ecc.mode);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index 4335577..317a771 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -24,7 +24,6 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -136,69 +135,6 @@ static struct nand_ecclayout oob_4096_ecc8 = {
.oobfree = { {2, 6}, {136, 82} },
};
-/* 8192-byte page size with 4-bit ECC */
-static struct nand_ecclayout oob_8192_ecc4 = {
- .eccbytes = 128,
- .eccpos = {
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 133, 134, 135,
- },
- .oobfree = { {2, 6}, {136, 208} },
-};
-
-/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
-static struct nand_ecclayout oob_8192_ecc8 = {
- .eccbytes = 256,
- .eccpos = {
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127,
- 128, 129, 130, 131, 132, 133, 134, 135,
- 136, 137, 138, 139, 140, 141, 142, 143,
- 144, 145, 146, 147, 148, 149, 150, 151,
- 152, 153, 154, 155, 156, 157, 158, 159,
- 160, 161, 162, 163, 164, 165, 166, 167,
- 168, 169, 170, 171, 172, 173, 174, 175,
- 176, 177, 178, 179, 180, 181, 182, 183,
- 184, 185, 186, 187, 188, 189, 190, 191,
- 192, 193, 194, 195, 196, 197, 198, 199,
- 200, 201, 202, 203, 204, 205, 206, 207,
- 208, 209, 210, 211, 212, 213, 214, 215,
- 216, 217, 218, 219, 220, 221, 222, 223,
- 224, 225, 226, 227, 228, 229, 230, 231,
- 232, 233, 234, 235, 236, 237, 238, 239,
- 240, 241, 242, 243, 244, 245, 246, 247,
- 248, 249, 250, 251, 252, 253, 254, 255,
- 256, 257, 258, 259, 260, 261, 262, 263,
- },
- .oobfree = { {2, 6}, {264, 80} },
-};
/*
* Generic flash bbt descriptors
@@ -505,29 +441,20 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
if (mtd->writesize > 512) {
nand_fcr0 =
(NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
- (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
- (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
+ (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT);
iowrite32be(
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
- (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
- (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT),
- &ifc->ifc_nand.nand_fir0);
- iowrite32be(
- (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
- (IFC_FIR_OP_RDSTAT <<
- IFC_NAND_FIR1_OP6_SHIFT) |
- (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT),
- &ifc->ifc_nand.nand_fir1);
+ (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+ (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+ (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+ (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
+ (IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT),
+ &ifc->ifc_nand.nand_fir0);
} else {
nand_fcr0 = ((NAND_CMD_PAGEPROG <<
IFC_NAND_FCR0_CMD1_SHIFT) |
(NAND_CMD_SEQIN <<
- IFC_NAND_FCR0_CMD2_SHIFT) |
- (NAND_CMD_STATUS <<
- IFC_NAND_FCR0_CMD3_SHIFT));
+ IFC_NAND_FCR0_CMD2_SHIFT));
iowrite32be(
(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
@@ -536,13 +463,8 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
(IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
(IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT),
&ifc->ifc_nand.nand_fir0);
- iowrite32be(
- (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
- (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
- (IFC_FIR_OP_RDSTAT <<
- IFC_NAND_FIR1_OP7_SHIFT) |
- (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT),
- &ifc->ifc_nand.nand_fir1);
+ iowrite32be(IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT,
+ &ifc->ifc_nand.nand_fir1);
if (column >= mtd->writesize)
nand_fcr0 |=
@@ -796,6 +718,8 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
chip->page_shift);
dev_dbg(priv->dev, "%s: nand->phys_erase_shift = %d\n", __func__,
chip->phys_erase_shift);
+ dev_dbg(priv->dev, "%s: nand->ecclayout = %p\n", __func__,
+ chip->ecclayout);
dev_dbg(priv->dev, "%s: nand->ecc.mode = %d\n", __func__,
chip->ecc.mode);
dev_dbg(priv->dev, "%s: nand->ecc.steps = %d\n", __func__,
@@ -948,25 +872,11 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
} else {
layout = &oob_4096_ecc8;
chip->ecc.bytes = 16;
- chip->ecc.strength = 8;
}
priv->bufnum_mask = 1;
break;
- case CSOR_NAND_PGS_8K:
- if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
- CSOR_NAND_ECC_MODE_4) {
- layout = &oob_8192_ecc4;
- } else {
- layout = &oob_8192_ecc8;
- chip->ecc.bytes = 16;
- chip->ecc.strength = 8;
- }
-
- priv->bufnum_mask = 0;
- break;
-
default:
dev_err(priv->dev, "bad csor %#x: bad page size\n", csor);
return -ENODEV;
@@ -997,6 +907,7 @@ static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv)
iounmap(priv->vbase);
ifc_nand_ctrl->chips[priv->bank] = NULL;
+ dev_set_drvdata(priv->dev, NULL);
return 0;
}
@@ -1171,7 +1082,25 @@ static struct platform_driver fsl_ifc_nand_driver = {
.remove = fsl_ifc_nand_remove,
};
-module_platform_driver(fsl_ifc_nand_driver);
+static int __init fsl_ifc_nand_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&fsl_ifc_nand_driver);
+ if (ret)
+ printk(KERN_ERR "fsl-ifc: Failed to register platform"
+ "driver\n");
+
+ return ret;
+}
+
+static void __exit fsl_ifc_nand_exit(void)
+{
+ platform_driver_unregister(&fsl_ifc_nand_driver);
+}
+
+module_init(fsl_ifc_nand_init);
+module_exit(fsl_ifc_nand_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Freescale");
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 4d203e8..04e0725 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -18,7 +18,6 @@
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/mtd.h>
-#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/io.h>
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 8b27522..3dc1a75 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -573,6 +573,8 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len,
dma_dev = chan->device;
dma_addr = dma_map_single(dma_dev->dev, buffer, len, direction);
+ flags |= DMA_COMPL_SKIP_SRC_UNMAP | DMA_COMPL_SKIP_DEST_UNMAP;
+
if (direction == DMA_TO_DEVICE) {
dma_src = dma_addr;
dma_dst = host->data_pa;
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index aaced29..4f8857f 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -187,12 +187,6 @@ int gpmi_init(struct gpmi_nand_data *this)
/* Select BCH ECC. */
writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET);
- /*
- * Decouple the chip select from dma channel. We use dma0 for all
- * the chips.
- */
- writel(BM_GPMI_CTRL1_DECOUPLE_CS, r->gpmi_regs + HW_GPMI_CTRL1_SET);
-
gpmi_disable_clk(this);
return 0;
err_out:
@@ -1079,13 +1073,6 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
mask = MX23_BM_GPMI_DEBUG_READY0 << chip;
reg = readl(r->gpmi_regs + HW_GPMI_DEBUG);
} else if (GPMI_IS_MX28(this) || GPMI_IS_MX6Q(this)) {
- /*
- * In the imx6, all the ready/busy pins are bound
- * together. So we only need to check chip 0.
- */
- if (GPMI_IS_MX6Q(this))
- chip = 0;
-
/* MX28 shares the same R/B register as MX6Q. */
mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
reg = readl(r->gpmi_regs + HW_GPMI_STAT);
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index dabbc14..a9830ff 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -45,10 +45,7 @@ static struct nand_bbt_descr gpmi_bbt_descr = {
.pattern = scan_ff_pattern
};
-/*
- * We may change the layout if we can get the ECC info from the datasheet,
- * else we will use all the (page + OOB).
- */
+/* We will use all the (page + OOB). */
static struct nand_ecclayout gpmi_hw_ecclayout = {
.eccbytes = 0,
.eccpos = { 0, },
@@ -357,8 +354,9 @@ int common_nfc_set_geometry(struct gpmi_nand_data *this)
struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
{
- /* We use the DMA channel 0 to access all the nand chips. */
- return this->dma_chans[0];
+ int chipnr = this->current_chip;
+
+ return this->dma_chans[chipnr];
}
/* Can we use the upper's buffer directly for DMA? */
@@ -394,6 +392,8 @@ static void dma_irq_callback(void *param)
struct gpmi_nand_data *this = param;
struct completion *dma_c = &this->dma_done;
+ complete(dma_c);
+
switch (this->dma_type) {
case DMA_FOR_COMMAND:
dma_unmap_sg(this->dev, &this->cmd_sgl, 1, DMA_TO_DEVICE);
@@ -418,8 +418,6 @@ static void dma_irq_callback(void *param)
default:
pr_err("in wrong DMA operation.\n");
}
-
- complete(dma_c);
}
int start_dma_without_bch_irq(struct gpmi_nand_data *this,
@@ -1265,22 +1263,14 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
static int
gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
{
- struct nand_oobfree *of = mtd->ecclayout->oobfree;
- int status = 0;
-
- /* Do we have available oob area? */
- if (!of->length)
- return -EPERM;
-
- if (!nand_is_slc(chip))
- return -EPERM;
-
- chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + of->offset, page);
- chip->write_buf(mtd, chip->oob_poi + of->offset, of->length);
- chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
-
- status = chip->waitfunc(mtd, chip);
- return status & NAND_STATUS_FAIL ? -EIO : 0;
+ /*
+ * The BCH will use all the (page + oob).
+ * Our gpmi_hw_ecclayout can only prohibit the JFFS2 to write the oob.
+ * But it can not stop some ioctls such MEMWRITEOOB which uses
+ * MTD_OPS_PLACE_OOB. So We have to implement this function to prohibit
+ * these ioctls too.
+ */
+ return -EPERM;
}
static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
@@ -1578,6 +1568,8 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
static int gpmi_pre_bbt_scan(struct gpmi_nand_data *this)
{
+ int ret;
+
/* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
if (GPMI_IS_MX23(this))
this->swap_block_mark = false;
@@ -1585,8 +1577,12 @@ static int gpmi_pre_bbt_scan(struct gpmi_nand_data *this)
this->swap_block_mark = true;
/* Set up the medium geometry */
- return gpmi_set_geometry(this);
+ ret = gpmi_set_geometry(this);
+ if (ret)
+ return ret;
+ /* NAND boot init, depends on the gpmi_set_geometry(). */
+ return nand_boot_init(this);
}
static void gpmi_nfc_exit(struct gpmi_nand_data *this)
@@ -1668,7 +1664,7 @@ static int gpmi_nfc_init(struct gpmi_nand_data *this)
if (ret)
goto err_out;
- ret = nand_scan_ident(mtd, GPMI_IS_MX6Q(this) ? 2 : 1, NULL);
+ ret = nand_scan_ident(mtd, 1, NULL);
if (ret)
goto err_out;
@@ -1676,16 +1672,10 @@ static int gpmi_nfc_init(struct gpmi_nand_data *this)
if (ret)
goto err_out;
- chip->options |= NAND_SKIP_BBTSCAN;
ret = nand_scan_tail(mtd);
if (ret)
goto err_out;
- ret = nand_boot_init(this);
- if (ret)
- goto err_out;
- chip->scan_bbt(mtd);
-
ppdata.of_node = this->pdev->dev.of_node;
ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
if (ret)
@@ -1701,19 +1691,19 @@ static const struct platform_device_id gpmi_ids[] = {
{ .name = "imx23-gpmi-nand", .driver_data = IS_MX23, },
{ .name = "imx28-gpmi-nand", .driver_data = IS_MX28, },
{ .name = "imx6q-gpmi-nand", .driver_data = IS_MX6Q, },
- {}
+ {},
};
static const struct of_device_id gpmi_nand_id_table[] = {
{
.compatible = "fsl,imx23-gpmi-nand",
- .data = (void *)&gpmi_ids[IS_MX23],
+ .data = (void *)&gpmi_ids[IS_MX23]
}, {
.compatible = "fsl,imx28-gpmi-nand",
- .data = (void *)&gpmi_ids[IS_MX28],
+ .data = (void *)&gpmi_ids[IS_MX28]
}, {
.compatible = "fsl,imx6q-gpmi-nand",
- .data = (void *)&gpmi_ids[IS_MX6Q],
+ .data = (void *)&gpmi_ids[IS_MX6Q]
}, {}
};
MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
@@ -1732,7 +1722,7 @@ static int gpmi_nand_probe(struct platform_device *pdev)
return -ENODEV;
}
- this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL);
+ this = kzalloc(sizeof(*this), GFP_KERNEL);
if (!this) {
pr_err("Failed to allocate per-device memory\n");
return -ENOMEM;
@@ -1762,6 +1752,7 @@ exit_nfc_init:
release_resources(this);
exit_acquire_resources:
dev_err(this->dev, "driver registration failed: %d\n", ret);
+ kfree(this);
return ret;
}
@@ -1772,6 +1763,7 @@ static int gpmi_nand_remove(struct platform_device *pdev)
gpmi_nfc_exit(this);
release_resources(this);
+ kfree(this);
return 0;
}
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-regs.h b/drivers/mtd/nand/gpmi-nand/gpmi-regs.h
index 82114cd..53397cc 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-regs.h
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-regs.h
@@ -108,9 +108,6 @@
#define HW_GPMI_CTRL1_CLR 0x00000068
#define HW_GPMI_CTRL1_TOG 0x0000006c
-#define BP_GPMI_CTRL1_DECOUPLE_CS 24
-#define BM_GPMI_CTRL1_DECOUPLE_CS (1 << BP_GPMI_CTRL1_DECOUPLE_CS)
-
#define BP_GPMI_CTRL1_WRN_DLY_SEL 22
#define BM_GPMI_CTRL1_WRN_DLY_SEL (0x3 << BP_GPMI_CTRL1_WRN_DLY_SEL)
#define BF_GPMI_CTRL1_WRN_DLY_SEL(v) \
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
index 327d96c..f4dd2a8 100644
--- a/drivers/mtd/nand/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_mlc.c
@@ -905,7 +905,7 @@ static struct platform_driver lpc32xx_nand_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
- .of_match_table = lpc32xx_nand_match,
+ .of_match_table = of_match_ptr(lpc32xx_nand_match),
},
};
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
index 23e6974..add7570 100644
--- a/drivers/mtd/nand/lpc32xx_slc.c
+++ b/drivers/mtd/nand/lpc32xx_slc.c
@@ -893,6 +893,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
/* Avoid extra scan if using BBT, setup BBT support */
if (host->ncfg->use_bbt) {
+ chip->options |= NAND_SKIP_BBTSCAN;
chip->bbt_options |= NAND_BBT_USE_FLASH;
/*
@@ -914,6 +915,13 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
goto err_exit3;
}
+ /* Standard layout in FLASH for bad block tables */
+ if (host->ncfg->use_bbt) {
+ if (nand_default_bbt(mtd) < 0)
+ dev_err(&pdev->dev,
+ "Error initializing default bad block tables\n");
+ }
+
mtd->name = "nxp_lpc3220_slc";
ppdata.of_node = pdev->dev.of_node;
res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts,
@@ -1015,7 +1023,7 @@ static struct platform_driver lpc32xx_nand_driver = {
.driver = {
.name = LPC32XX_MODNAME,
.owner = THIS_MODULE,
- .of_match_table = lpc32xx_nand_match,
+ .of_match_table = of_match_ptr(lpc32xx_nand_match),
},
};
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 439bc38..3c60a00 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -36,9 +36,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
-#include <linux/of_address.h>
#include <linux/of_device.h>
-#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/mpc5121.h>
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 9dfdb06..ce8242b 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -32,7 +32,6 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/completion.h>
-#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_mtd.h>
@@ -396,7 +395,7 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
if (useirq) {
if (!host->devtype_data->check_int(host)) {
- reinit_completion(&host->op_completion);
+ INIT_COMPLETION(host->op_completion);
irq_control(host, 1);
wait_for_completion(&host->op_completion);
}
@@ -1508,7 +1507,7 @@ static int mxcnd_probe(struct platform_device *pdev)
host->devtype_data->irq_control(host, 0);
err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq,
- 0, DRIVER_NAME, host);
+ IRQF_DISABLED, DRIVER_NAME, host);
if (err)
return err;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index bd39f7b..d340b2f 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2912,13 +2912,12 @@ static int nand_flash_detect_ext_param_page(struct mtd_info *mtd,
/* get the info we want. */
ecc = (struct onfi_ext_ecc_info *)cursor;
- if (!ecc->codeword_size) {
- pr_debug("Invalid codeword size\n");
- goto ext_out;
+ if (ecc->codeword_size) {
+ chip->ecc_strength_ds = ecc->ecc_bits;
+ chip->ecc_step_ds = 1 << ecc->codeword_size;
}
- chip->ecc_strength_ds = ecc->ecc_bits;
- chip->ecc_step_ds = 1 << ecc->codeword_size;
+ pr_info("ONFI extended param page detected.\n");
ret = 0;
ext_out:
@@ -2936,34 +2935,29 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
int i;
int val;
+ /* ONFI need to be probed in 8 bits mode, and 16 bits should be selected with NAND_BUSWIDTH_AUTO */
+ if (chip->options & NAND_BUSWIDTH_16) {
+ pr_err("Trying ONFI probe in 16 bits mode, aborting !\n");
+ return 0;
+ }
/* Try ONFI for unknown chip or LP */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
return 0;
- /*
- * ONFI must be probed in 8-bit mode or with NAND_BUSWIDTH_AUTO, not
- * with NAND_BUSWIDTH_16
- */
- if (chip->options & NAND_BUSWIDTH_16) {
- pr_err("ONFI cannot be probed in 16-bit mode; aborting\n");
- return 0;
- }
-
chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
for (i = 0; i < 3; i++) {
chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
le16_to_cpu(p->crc)) {
+ pr_info("ONFI param page %d valid\n", i);
break;
}
}
- if (i == 3) {
- pr_err("Could not find valid ONFI parameter page; aborting\n");
+ if (i == 3)
return 0;
- }
/* Check version */
val = le16_to_cpu(p->revision);
@@ -2987,23 +2981,11 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
sanitize_string(p->model, sizeof(p->model));
if (!mtd->name)
mtd->name = p->model;
-
mtd->writesize = le32_to_cpu(p->byte_per_page);
-
- /*
- * pages_per_block and blocks_per_lun may not be a power-of-2 size
- * (don't ask me who thought of this...). MTD assumes that these
- * dimensions will be power-of-2, so just truncate the remaining area.
- */
- mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
- mtd->erasesize *= mtd->writesize;
-
+ mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
-
- /* See erasesize comment */
- chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
+ chip->chipsize = le32_to_cpu(p->blocks_per_lun);
chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
- chip->bits_per_cell = p->bits_per_cell;
if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS)
*busw = NAND_BUSWIDTH_16;
@@ -3027,11 +3009,10 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
/* The Extended Parameter Page is supported since ONFI 2.1. */
if (nand_flash_detect_ext_param_page(mtd, chip, p))
- pr_warn("Failed to detect ONFI extended param page\n");
- } else {
- pr_warn("Could not retrieve ONFI ECC requirements\n");
+ pr_info("Failed to detect the extended param page.\n");
}
+ pr_info("ONFI flash detected\n");
return 1;
}
@@ -3094,16 +3075,6 @@ static int nand_id_len(u8 *id_data, int arrlen)
return arrlen;
}
-/* Extract the bits of per cell from the 3rd byte of the extended ID */
-static int nand_get_bits_per_cell(u8 cellinfo)
-{
- int bits;
-
- bits = cellinfo & NAND_CI_CELLTYPE_MSK;
- bits >>= NAND_CI_CELLTYPE_SHIFT;
- return bits + 1;
-}
-
/*
* Many new NAND share similar device ID codes, which represent the size of the
* chip. The rest of the parameters must be decoded according to generic or
@@ -3114,7 +3085,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
{
int extid, id_len;
/* The 3rd id byte holds MLC / multichip data */
- chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
+ chip->cellinfo = id_data[2];
/* The 4th id byte is the important one */
extid = id_data[3];
@@ -3130,7 +3101,8 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
* ID to decide what to do.
*/
if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
- !nand_is_slc(chip) && id_data[5] != 0x00) {
+ (chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+ id_data[5] != 0x00) {
/* Calc pagesize */
mtd->writesize = 2048 << (extid & 0x03);
extid >>= 2;
@@ -3162,7 +3134,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
(((extid >> 1) & 0x04) | (extid & 0x03));
*busw = 0;
} else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX &&
- !nand_is_slc(chip)) {
+ (chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
unsigned int tmp;
/* Calc pagesize */
@@ -3225,7 +3197,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
* - ID byte 5, bit[7]: 1 -> BENAND, 0 -> raw SLC
*/
if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA &&
- nand_is_slc(chip) &&
+ !(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
(id_data[5] & 0x7) == 0x6 /* 24nm */ &&
!(id_data[4] & 0x80) /* !BENAND */) {
mtd->oobsize = 32 * mtd->writesize >> 9;
@@ -3250,9 +3222,6 @@ static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
mtd->oobsize = mtd->writesize / 32;
*busw = type->options & NAND_BUSWIDTH_16;
- /* All legacy ID NAND are small-page, SLC */
- chip->bits_per_cell = 1;
-
/*
* Check for Spansion/AMD ID + repeating 5th, 6th byte since
* some Spansion chips have erasesize that conflicts with size
@@ -3289,11 +3258,11 @@ static void nand_decode_bbm_options(struct mtd_info *mtd,
* Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
* AMD/Spansion, and Macronix. All others scan only the first page.
*/
- if (!nand_is_slc(chip) &&
+ if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
(maf_id == NAND_MFR_SAMSUNG ||
maf_id == NAND_MFR_HYNIX))
chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
- else if ((nand_is_slc(chip) &&
+ else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
(maf_id == NAND_MFR_SAMSUNG ||
maf_id == NAND_MFR_HYNIX ||
maf_id == NAND_MFR_TOSHIBA ||
@@ -3317,7 +3286,7 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
mtd->erasesize = type->erasesize;
mtd->oobsize = type->oobsize;
- chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
+ chip->cellinfo = id_data[2];
chip->chipsize = (uint64_t)type->chipsize << 20;
chip->options |= type->options;
chip->ecc_strength_ds = NAND_ECC_STRENGTH(type);
@@ -3472,13 +3441,11 @@ ident_done:
if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
chip->cmdfunc = nand_command_lp;
- pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)\n",
+ pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s),"
+ " %dMiB, page size: %d, OOB size: %d\n",
*maf_id, *dev_id, nand_manuf_ids[maf_idx].name,
- chip->onfi_version ? chip->onfi_params.model : type->name);
-
- pr_info("NAND device: %dMiB, %s, page size: %d, OOB size: %d\n",
- (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
- mtd->writesize, mtd->oobsize);
+ chip->onfi_version ? chip->onfi_params.model : type->name,
+ (int)(chip->chipsize >> 20), mtd->writesize, mtd->oobsize);
return type;
}
@@ -3558,7 +3525,6 @@ int nand_scan_tail(struct mtd_info *mtd)
{
int i;
struct nand_chip *chip = mtd->priv;
- struct nand_ecc_ctrl *ecc = &chip->ecc;
/* New bad blocks should be marked in OOB, flash-based BBT, or both */
BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
@@ -3575,19 +3541,19 @@ int nand_scan_tail(struct mtd_info *mtd)
/*
* If no default placement scheme is given, select an appropriate one.
*/
- if (!ecc->layout && (ecc->mode != NAND_ECC_SOFT_BCH)) {
+ if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {
switch (mtd->oobsize) {
case 8:
- ecc->layout = &nand_oob_8;
+ chip->ecc.layout = &nand_oob_8;
break;
case 16:
- ecc->layout = &nand_oob_16;
+ chip->ecc.layout = &nand_oob_16;
break;
case 64:
- ecc->layout = &nand_oob_64;
+ chip->ecc.layout = &nand_oob_64;
break;
case 128:
- ecc->layout = &nand_oob_128;
+ chip->ecc.layout = &nand_oob_128;
break;
default:
pr_warn("No oob scheme defined for oobsize %d\n",
@@ -3604,62 +3570,64 @@ int nand_scan_tail(struct mtd_info *mtd)
* selected and we have 256 byte pagesize fallback to software ECC
*/
- switch (ecc->mode) {
+ switch (chip->ecc.mode) {
case NAND_ECC_HW_OOB_FIRST:
/* Similar to NAND_ECC_HW, but a separate read_page handle */
- if (!ecc->calculate || !ecc->correct || !ecc->hwctl) {
+ if (!chip->ecc.calculate || !chip->ecc.correct ||
+ !chip->ecc.hwctl) {
pr_warn("No ECC functions supplied; "
"hardware ECC not possible\n");
BUG();
}
- if (!ecc->read_page)
- ecc->read_page = nand_read_page_hwecc_oob_first;
+ if (!chip->ecc.read_page)
+ chip->ecc.read_page = nand_read_page_hwecc_oob_first;
case NAND_ECC_HW:
/* Use standard hwecc read page function? */
- if (!ecc->read_page)
- ecc->read_page = nand_read_page_hwecc;
- if (!ecc->write_page)
- ecc->write_page = nand_write_page_hwecc;
- if (!ecc->read_page_raw)
- ecc->read_page_raw = nand_read_page_raw;
- if (!ecc->write_page_raw)
- ecc->write_page_raw = nand_write_page_raw;
- if (!ecc->read_oob)
- ecc->read_oob = nand_read_oob_std;
- if (!ecc->write_oob)
- ecc->write_oob = nand_write_oob_std;
- if (!ecc->read_subpage)
- ecc->read_subpage = nand_read_subpage;
- if (!ecc->write_subpage)
- ecc->write_subpage = nand_write_subpage_hwecc;
+ if (!chip->ecc.read_page)
+ chip->ecc.read_page = nand_read_page_hwecc;
+ if (!chip->ecc.write_page)
+ chip->ecc.write_page = nand_write_page_hwecc;
+ if (!chip->ecc.read_page_raw)
+ chip->ecc.read_page_raw = nand_read_page_raw;
+ if (!chip->ecc.write_page_raw)
+ chip->ecc.write_page_raw = nand_write_page_raw;
+ if (!chip->ecc.read_oob)
+ chip->ecc.read_oob = nand_read_oob_std;
+ if (!chip->ecc.write_oob)
+ chip->ecc.write_oob = nand_write_oob_std;
+ if (!chip->ecc.read_subpage)
+ chip->ecc.read_subpage = nand_read_subpage;
+ if (!chip->ecc.write_subpage)
+ chip->ecc.write_subpage = nand_write_subpage_hwecc;
case NAND_ECC_HW_SYNDROME:
- if ((!ecc->calculate || !ecc->correct || !ecc->hwctl) &&
- (!ecc->read_page ||
- ecc->read_page == nand_read_page_hwecc ||
- !ecc->write_page ||
- ecc->write_page == nand_write_page_hwecc)) {
+ if ((!chip->ecc.calculate || !chip->ecc.correct ||
+ !chip->ecc.hwctl) &&
+ (!chip->ecc.read_page ||
+ chip->ecc.read_page == nand_read_page_hwecc ||
+ !chip->ecc.write_page ||
+ chip->ecc.write_page == nand_write_page_hwecc)) {
pr_warn("No ECC functions supplied; "
"hardware ECC not possible\n");
BUG();
}
/* Use standard syndrome read/write page function? */
- if (!ecc->read_page)
- ecc->read_page = nand_read_page_syndrome;
- if (!ecc->write_page)
- ecc->write_page = nand_write_page_syndrome;
- if (!ecc->read_page_raw)
- ecc->read_page_raw = nand_read_page_raw_syndrome;
- if (!ecc->write_page_raw)
- ecc->write_page_raw = nand_write_page_raw_syndrome;
- if (!ecc->read_oob)
- ecc->read_oob = nand_read_oob_syndrome;
- if (!ecc->write_oob)
- ecc->write_oob = nand_write_oob_syndrome;
-
- if (mtd->writesize >= ecc->size) {
- if (!ecc->strength) {
+ if (!chip->ecc.read_page)
+ chip->ecc.read_page = nand_read_page_syndrome;
+ if (!chip->ecc.write_page)
+ chip->ecc.write_page = nand_write_page_syndrome;
+ if (!chip->ecc.read_page_raw)
+ chip->ecc.read_page_raw = nand_read_page_raw_syndrome;
+ if (!chip->ecc.write_page_raw)
+ chip->ecc.write_page_raw = nand_write_page_raw_syndrome;
+ if (!chip->ecc.read_oob)
+ chip->ecc.read_oob = nand_read_oob_syndrome;
+ if (!chip->ecc.write_oob)
+ chip->ecc.write_oob = nand_write_oob_syndrome;
+
+ if (mtd->writesize >= chip->ecc.size) {
+ if (!chip->ecc.strength) {
pr_warn("Driver must set ecc.strength when using hardware ECC\n");
BUG();
}
@@ -3667,23 +3635,23 @@ int nand_scan_tail(struct mtd_info *mtd)
}
pr_warn("%d byte HW ECC not possible on "
"%d byte page size, fallback to SW ECC\n",
- ecc->size, mtd->writesize);
- ecc->mode = NAND_ECC_SOFT;
+ chip->ecc.size, mtd->writesize);
+ chip->ecc.mode = NAND_ECC_SOFT;
case NAND_ECC_SOFT:
- ecc->calculate = nand_calculate_ecc;
- ecc->correct = nand_correct_data;
- ecc->read_page = nand_read_page_swecc;
- ecc->read_subpage = nand_read_subpage;
- ecc->write_page = nand_write_page_swecc;
- ecc->read_page_raw = nand_read_page_raw;
- ecc->write_page_raw = nand_write_page_raw;
- ecc->read_oob = nand_read_oob_std;
- ecc->write_oob = nand_write_oob_std;
- if (!ecc->size)
- ecc->size = 256;
- ecc->bytes = 3;
- ecc->strength = 1;
+ chip->ecc.calculate = nand_calculate_ecc;
+ chip->ecc.correct = nand_correct_data;
+ chip->ecc.read_page = nand_read_page_swecc;
+ chip->ecc.read_subpage = nand_read_subpage;
+ chip->ecc.write_page = nand_write_page_swecc;
+ chip->ecc.read_page_raw = nand_read_page_raw;
+ chip->ecc.write_page_raw = nand_write_page_raw;
+ chip->ecc.read_oob = nand_read_oob_std;
+ chip->ecc.write_oob = nand_write_oob_std;
+ if (!chip->ecc.size)
+ chip->ecc.size = 256;
+ chip->ecc.bytes = 3;
+ chip->ecc.strength = 1;
break;
case NAND_ECC_SOFT_BCH:
@@ -3691,83 +3659,88 @@ int nand_scan_tail(struct mtd_info *mtd)
pr_warn("CONFIG_MTD_ECC_BCH not enabled\n");
BUG();
}
- ecc->calculate = nand_bch_calculate_ecc;
- ecc->correct = nand_bch_correct_data;
- ecc->read_page = nand_read_page_swecc;
- ecc->read_subpage = nand_read_subpage;
- ecc->write_page = nand_write_page_swecc;
- ecc->read_page_raw = nand_read_page_raw;
- ecc->write_page_raw = nand_write_page_raw;
- ecc->read_oob = nand_read_oob_std;
- ecc->write_oob = nand_write_oob_std;
+ chip->ecc.calculate = nand_bch_calculate_ecc;
+ chip->ecc.correct = nand_bch_correct_data;
+ chip->ecc.read_page = nand_read_page_swecc;
+ chip->ecc.read_subpage = nand_read_subpage;
+ chip->ecc.write_page = nand_write_page_swecc;
+ chip->ecc.read_page_raw = nand_read_page_raw;
+ chip->ecc.write_page_raw = nand_write_page_raw;
+ chip->ecc.read_oob = nand_read_oob_std;
+ chip->ecc.write_oob = nand_write_oob_std;
/*
* Board driver should supply ecc.size and ecc.bytes values to
* select how many bits are correctable; see nand_bch_init()
* for details. Otherwise, default to 4 bits for large page
* devices.
*/
- if (!ecc->size && (mtd->oobsize >= 64)) {
- ecc->size = 512;
- ecc->bytes = 7;
+ if (!chip->ecc.size && (mtd->oobsize >= 64)) {
+ chip->ecc.size = 512;
+ chip->ecc.bytes = 7;
}
- ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes,
- &ecc->layout);
- if (!ecc->priv) {
+ chip->ecc.priv = nand_bch_init(mtd,
+ chip->ecc.size,
+ chip->ecc.bytes,
+ &chip->ecc.layout);
+ if (!chip->ecc.priv) {
pr_warn("BCH ECC initialization failed!\n");
BUG();
}
- ecc->strength = ecc->bytes * 8 / fls(8 * ecc->size);
+ chip->ecc.strength =
+ chip->ecc.bytes * 8 / fls(8 * chip->ecc.size);
break;
case NAND_ECC_NONE:
pr_warn("NAND_ECC_NONE selected by board driver. "
"This is not recommended!\n");
- ecc->read_page = nand_read_page_raw;
- ecc->write_page = nand_write_page_raw;
- ecc->read_oob = nand_read_oob_std;
- ecc->read_page_raw = nand_read_page_raw;
- ecc->write_page_raw = nand_write_page_raw;
- ecc->write_oob = nand_write_oob_std;
- ecc->size = mtd->writesize;
- ecc->bytes = 0;
- ecc->strength = 0;
+ chip->ecc.read_page = nand_read_page_raw;
+ chip->ecc.write_page = nand_write_page_raw;
+ chip->ecc.read_oob = nand_read_oob_std;
+ chip->ecc.read_page_raw = nand_read_page_raw;
+ chip->ecc.write_page_raw = nand_write_page_raw;
+ chip->ecc.write_oob = nand_write_oob_std;
+ chip->ecc.size = mtd->writesize;
+ chip->ecc.bytes = 0;
+ chip->ecc.strength = 0;
break;
default:
- pr_warn("Invalid NAND_ECC_MODE %d\n", ecc->mode);
+ pr_warn("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode);
BUG();
}
/* For many systems, the standard OOB write also works for raw */
- if (!ecc->read_oob_raw)
- ecc->read_oob_raw = ecc->read_oob;
- if (!ecc->write_oob_raw)
- ecc->write_oob_raw = ecc->write_oob;
+ if (!chip->ecc.read_oob_raw)
+ chip->ecc.read_oob_raw = chip->ecc.read_oob;
+ if (!chip->ecc.write_oob_raw)
+ chip->ecc.write_oob_raw = chip->ecc.write_oob;
/*
* The number of bytes available for a client to place data into
* the out of band area.
*/
- ecc->layout->oobavail = 0;
- for (i = 0; ecc->layout->oobfree[i].length
- && i < ARRAY_SIZE(ecc->layout->oobfree); i++)
- ecc->layout->oobavail += ecc->layout->oobfree[i].length;
- mtd->oobavail = ecc->layout->oobavail;
+ chip->ecc.layout->oobavail = 0;
+ for (i = 0; chip->ecc.layout->oobfree[i].length
+ && i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++)
+ chip->ecc.layout->oobavail +=
+ chip->ecc.layout->oobfree[i].length;
+ mtd->oobavail = chip->ecc.layout->oobavail;
/*
* Set the number of read / write steps for one page depending on ECC
* mode.
*/
- ecc->steps = mtd->writesize / ecc->size;
- if (ecc->steps * ecc->size != mtd->writesize) {
+ chip->ecc.steps = mtd->writesize / chip->ecc.size;
+ if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
pr_warn("Invalid ECC parameters\n");
BUG();
}
- ecc->total = ecc->steps * ecc->bytes;
+ chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
/* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
- if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) {
- switch (ecc->steps) {
+ if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
+ !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
+ switch (chip->ecc.steps) {
case 2:
mtd->subpage_sft = 1;
break;
@@ -3787,11 +3760,11 @@ int nand_scan_tail(struct mtd_info *mtd)
chip->pagebuf = -1;
/* Large page NAND with SOFT_ECC should support subpage reads */
- if ((ecc->mode == NAND_ECC_SOFT) && (chip->page_shift > 9))
+ if ((chip->ecc.mode == NAND_ECC_SOFT) && (chip->page_shift > 9))
chip->options |= NAND_SUBPAGE_READ;
/* Fill in remaining MTD driver data */
- mtd->type = nand_is_slc(chip) ? MTD_NANDFLASH : MTD_MLCNANDFLASH;
+ mtd->type = MTD_NANDFLASH;
mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :
MTD_CAP_NANDFLASH;
mtd->_erase = nand_erase;
@@ -3812,9 +3785,9 @@ int nand_scan_tail(struct mtd_info *mtd)
mtd->writebufsize = mtd->writesize;
/* propagate ecc info to mtd_info */
- mtd->ecclayout = ecc->layout;
- mtd->ecc_strength = ecc->strength;
- mtd->ecc_step_size = ecc->size;
+ mtd->ecclayout = chip->ecc.layout;
+ mtd->ecc_strength = chip->ecc.strength;
+ mtd->ecc_step_size = chip->ecc.size;
/*
* Initialize bitflip_threshold to its default prior scan_bbt() call.
* scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index c0615d1..bc06196 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -412,6 +412,25 @@ static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
}
}
+/* Scan a given block full */
+static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
+ loff_t offs, uint8_t *buf, size_t readlen,
+ int scanlen, int numpages)
+{
+ int ret, j;
+
+ ret = scan_read_oob(mtd, buf, offs, readlen);
+ /* Ignore ECC errors when checking for BBM */
+ if (ret && !mtd_is_bitflip_or_eccerr(ret))
+ return ret;
+
+ for (j = 0; j < numpages; j++, buf += scanlen) {
+ if (check_pattern(buf, scanlen, mtd->writesize, bd))
+ return 1;
+ }
+ return 0;
+}
+
/* Scan a given block partially */
static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
loff_t offs, uint8_t *buf, int numpages)
@@ -458,17 +477,24 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
struct nand_bbt_descr *bd, int chip)
{
struct nand_chip *this = mtd->priv;
- int i, numblocks, numpages;
+ int i, numblocks, numpages, scanlen;
int startblock;
loff_t from;
+ size_t readlen;
pr_info("Scanning device for bad blocks\n");
- if (bd->options & NAND_BBT_SCAN2NDPAGE)
+ if (bd->options & NAND_BBT_SCANALLPAGES)
+ numpages = 1 << (this->bbt_erase_shift - this->page_shift);
+ else if (bd->options & NAND_BBT_SCAN2NDPAGE)
numpages = 2;
else
numpages = 1;
+ /* We need only read few bytes from the OOB area */
+ scanlen = 0;
+ readlen = bd->len;
+
if (chip == -1) {
numblocks = mtd->size >> this->bbt_erase_shift;
startblock = 0;
@@ -493,7 +519,12 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
BUG_ON(bd->options & NAND_BBT_NO_OOB);
- ret = scan_block_fast(mtd, bd, from, buf, numpages);
+ if (bd->options & NAND_BBT_SCANALLPAGES)
+ ret = scan_block_full(mtd, bd, from, buf, readlen,
+ scanlen, numpages);
+ else
+ ret = scan_block_fast(mtd, bd, from, buf, numpages);
+
if (ret < 0)
return ret;
@@ -1361,3 +1392,4 @@ int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
}
EXPORT_SYMBOL(nand_scan_bbt);
+EXPORT_SYMBOL(nand_default_bbt);
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 42e8a77..bdc1d15 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -575,7 +575,7 @@ static int alloc_device(struct nandsim *ns)
cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);
if (IS_ERR(cfile))
return PTR_ERR(cfile);
- if (!cfile->f_op->read && !cfile->f_op->aio_read) {
+ if (!cfile->f_op || (!cfile->f_op->read && !cfile->f_op->aio_read)) {
NS_ERR("alloc_device: cache file not readable\n");
err = -EINVAL;
goto err_close;
@@ -2372,7 +2372,7 @@ static int __init ns_init_module(void)
if ((retval = init_nandsim(nsmtd)) != 0)
goto err_exit;
- if ((retval = chip->scan_bbt(nsmtd)) != 0)
+ if ((retval = nand_default_bbt(nsmtd)) != 0)
goto err_exit;
if ((retval = parse_badblocks(nand, nsmtd)) != 0)
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 69eaba6..8e148f1 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -30,7 +30,6 @@
#include <linux/mtd/ndfc.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
-#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <asm/io.h>
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index f777250..4ecf0e5 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -25,8 +25,10 @@
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/mtd/nand_bch.h>
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+#include <linux/bch.h>
#include <linux/platform_data/elm.h>
+#endif
#include <linux/platform_data/mtd-nand-omap2.h>
@@ -139,8 +141,6 @@
#define BCH_ECC_SIZE0 0x0 /* ecc_size0 = 0, no oob protection */
#define BCH_ECC_SIZE1 0x20 /* ecc_size1 = 32 */
-#define BADBLOCK_MARKER_LENGTH 2
-
#ifdef CONFIG_MTD_NAND_OMAP_BCH
static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc,
0xac, 0x6b, 0xff, 0x99, 0x7b};
@@ -149,6 +149,17 @@ static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10};
/* oob info generated runtime depending on ecc algorithm and layout selected */
static struct nand_ecclayout omap_oobinfo;
+/* Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks
+ */
+static uint8_t scan_ff_pattern[] = { 0xff };
+static struct nand_bbt_descr bb_descrip_flashbased = {
+ .options = NAND_BBT_SCANALLPAGES,
+ .offs = 0,
+ .len = 1,
+ .pattern = scan_ff_pattern,
+};
+
struct omap_nand_info {
struct nand_hw_control controller;
@@ -171,10 +182,14 @@ struct omap_nand_info {
u_char *buf;
int buf_len;
struct gpmc_nand_regs reg;
- /* fields specific for BCHx_HW ECC scheme */
+
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+ struct bch_control *bch;
+ struct nand_ecclayout ecclayout;
bool is_elm_used;
struct device *elm_dev;
struct device_node *of_node;
+#endif
};
/**
@@ -1043,7 +1058,8 @@ static int omap_dev_ready(struct mtd_info *mtd)
}
}
-#if defined(CONFIG_MTD_NAND_ECC_BCH) || defined(CONFIG_MTD_NAND_OMAP_BCH)
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+
/**
* omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction
* @mtd: MTD device structure
@@ -1124,9 +1140,7 @@ static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
/* Clear ecc and enable bits */
writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control);
}
-#endif
-#ifdef CONFIG_MTD_NAND_ECC_BCH
/**
* omap3_calculate_ecc_bch4 - Generate 7 bytes of ECC bytes
* @mtd: MTD device structure
@@ -1211,9 +1225,7 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat,
return 0;
}
-#endif /* CONFIG_MTD_NAND_ECC_BCH */
-#ifdef CONFIG_MTD_NAND_OMAP_BCH
/**
* omap3_calculate_ecc_bch - Generate bytes of ECC bytes
* @mtd: MTD device structure
@@ -1507,6 +1519,38 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
}
/**
+ * omap3_correct_data_bch - Decode received data and correct errors
+ * @mtd: MTD device structure
+ * @data: page data
+ * @read_ecc: ecc read from nand flash
+ * @calc_ecc: ecc read from HW ECC registers
+ */
+static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data,
+ u_char *read_ecc, u_char *calc_ecc)
+{
+ int i, count;
+ /* cannot correct more than 8 errors */
+ unsigned int errloc[8];
+ struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+ mtd);
+
+ count = decode_bch(info->bch, NULL, 512, read_ecc, calc_ecc, NULL,
+ errloc);
+ if (count > 0) {
+ /* correct errors */
+ for (i = 0; i < count; i++) {
+ /* correct data only, not ecc bytes */
+ if (errloc[i] < 8*512)
+ data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
+ pr_debug("corrected bitflip %u\n", errloc[i]);
+ }
+ } else if (count < 0) {
+ pr_err("ecc unrecoverable error\n");
+ }
+ return count;
+}
+
+/**
* omap_write_page_bch - BCH ecc based write page function for entire page
* @mtd: mtd info structure
* @chip: nand chip info structure
@@ -1593,46 +1637,197 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
}
/**
- * is_elm_present - checks for presence of ELM module by scanning DT nodes
- * @omap_nand_info: NAND device structure containing platform data
- * @bch_type: 0x0=BCH4, 0x1=BCH8, 0x2=BCH16
+ * omap3_free_bch - Release BCH ecc resources
+ * @mtd: MTD device structure
*/
-static int is_elm_present(struct omap_nand_info *info,
- struct device_node *elm_node, enum bch_ecc bch_type)
+static void omap3_free_bch(struct mtd_info *mtd)
{
- struct platform_device *pdev;
- info->is_elm_used = false;
- /* check whether elm-id is passed via DT */
- if (!elm_node) {
- pr_err("nand: error: ELM DT node not found\n");
- return -ENODEV;
+ struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+ mtd);
+ if (info->bch) {
+ free_bch(info->bch);
+ info->bch = NULL;
}
- pdev = of_find_device_by_node(elm_node);
- /* check whether ELM device is registered */
- if (!pdev) {
- pr_err("nand: error: ELM device not found\n");
- return -ENODEV;
+}
+
+/**
+ * omap3_init_bch - Initialize BCH ECC
+ * @mtd: MTD device structure
+ * @ecc_opt: OMAP ECC mode (OMAP_ECC_BCH4_CODE_HW or OMAP_ECC_BCH8_CODE_HW)
+ */
+static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
+{
+ int max_errors;
+ struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+ mtd);
+#ifdef CONFIG_MTD_NAND_OMAP_BCH8
+ const int hw_errors = BCH8_MAX_ERROR;
+#else
+ const int hw_errors = BCH4_MAX_ERROR;
+#endif
+ enum bch_ecc bch_type;
+ const __be32 *parp;
+ int lenp;
+ struct device_node *elm_node;
+
+ info->bch = NULL;
+
+ max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ?
+ BCH8_MAX_ERROR : BCH4_MAX_ERROR;
+ if (max_errors != hw_errors) {
+ pr_err("cannot configure %d-bit BCH ecc, only %d-bit supported",
+ max_errors, hw_errors);
+ goto fail;
}
- /* ELM module available, now configure it */
- info->elm_dev = &pdev->dev;
- if (elm_config(info->elm_dev, bch_type))
- return -ENODEV;
- info->is_elm_used = true;
+
+ info->nand.ecc.size = 512;
+ info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
+ info->nand.ecc.mode = NAND_ECC_HW;
+ info->nand.ecc.strength = max_errors;
+
+ if (hw_errors == BCH8_MAX_ERROR)
+ bch_type = BCH8_ECC;
+ else
+ bch_type = BCH4_ECC;
+
+ /* Detect availability of ELM module */
+ parp = of_get_property(info->of_node, "elm_id", &lenp);
+ if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) {
+ pr_err("Missing elm_id property, fall back to Software BCH\n");
+ info->is_elm_used = false;
+ } else {
+ struct platform_device *pdev;
+
+ elm_node = of_find_node_by_phandle(be32_to_cpup(parp));
+ pdev = of_find_device_by_node(elm_node);
+ info->elm_dev = &pdev->dev;
+
+ if (elm_config(info->elm_dev, bch_type) == 0)
+ info->is_elm_used = true;
+ }
+
+ if (info->is_elm_used && (mtd->writesize <= 4096)) {
+
+ if (hw_errors == BCH8_MAX_ERROR)
+ info->nand.ecc.bytes = BCH8_SIZE;
+ else
+ info->nand.ecc.bytes = BCH4_SIZE;
+
+ info->nand.ecc.correct = omap_elm_correct_data;
+ info->nand.ecc.calculate = omap3_calculate_ecc_bch;
+ info->nand.ecc.read_page = omap_read_page_bch;
+ info->nand.ecc.write_page = omap_write_page_bch;
+ } else {
+ /*
+ * software bch library is only used to detect and
+ * locate errors
+ */
+ info->bch = init_bch(13, max_errors,
+ 0x201b /* hw polynomial */);
+ if (!info->bch)
+ goto fail;
+
+ info->nand.ecc.correct = omap3_correct_data_bch;
+
+ /*
+ * The number of corrected errors in an ecc block that will
+ * trigger block scrubbing defaults to the ecc strength (4 or 8)
+ * Set mtd->bitflip_threshold here to define a custom threshold.
+ */
+
+ if (max_errors == 8) {
+ info->nand.ecc.bytes = 13;
+ info->nand.ecc.calculate = omap3_calculate_ecc_bch8;
+ } else {
+ info->nand.ecc.bytes = 7;
+ info->nand.ecc.calculate = omap3_calculate_ecc_bch4;
+ }
+ }
+
+ pr_info("enabling NAND BCH ecc with %d-bit correction\n", max_errors);
+ return 0;
+fail:
+ omap3_free_bch(mtd);
+ return -1;
+}
+
+/**
+ * omap3_init_bch_tail - Build an oob layout for BCH ECC correction.
+ * @mtd: MTD device structure
+ */
+static int omap3_init_bch_tail(struct mtd_info *mtd)
+{
+ int i, steps, offset;
+ struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+ mtd);
+ struct nand_ecclayout *layout = &info->ecclayout;
+
+ /* build oob layout */
+ steps = mtd->writesize/info->nand.ecc.size;
+ layout->eccbytes = steps*info->nand.ecc.bytes;
+
+ /* do not bother creating special oob layouts for small page devices */
+ if (mtd->oobsize < 64) {
+ pr_err("BCH ecc is not supported on small page devices\n");
+ goto fail;
+ }
+
+ /* reserve 2 bytes for bad block marker */
+ if (layout->eccbytes+2 > mtd->oobsize) {
+ pr_err("no oob layout available for oobsize %d eccbytes %u\n",
+ mtd->oobsize, layout->eccbytes);
+ goto fail;
+ }
+
+ /* ECC layout compatible with RBL for BCH8 */
+ if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE))
+ offset = 2;
+ else
+ offset = mtd->oobsize - layout->eccbytes;
+
+ /* put ecc bytes at oob tail */
+ for (i = 0; i < layout->eccbytes; i++)
+ layout->eccpos[i] = offset + i;
+
+ if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE))
+ layout->oobfree[0].offset = 2 + layout->eccbytes * steps;
+ else
+ layout->oobfree[0].offset = 2;
+
+ layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes;
+ info->nand.ecc.layout = layout;
+
+ if (!(info->nand.options & NAND_BUSWIDTH_16))
+ info->nand.badblock_pattern = &bb_descrip_flashbased;
return 0;
+fail:
+ omap3_free_bch(mtd);
+ return -1;
+}
+
+#else
+static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
+{
+ pr_err("CONFIG_MTD_NAND_OMAP_BCH is not enabled\n");
+ return -1;
+}
+static int omap3_init_bch_tail(struct mtd_info *mtd)
+{
+ return -1;
+}
+static void omap3_free_bch(struct mtd_info *mtd)
+{
}
-#endif /* CONFIG_MTD_NAND_ECC_BCH */
+#endif /* CONFIG_MTD_NAND_OMAP_BCH */
static int omap_nand_probe(struct platform_device *pdev)
{
struct omap_nand_info *info;
struct omap_nand_platform_data *pdata;
- struct mtd_info *mtd;
- struct nand_chip *nand_chip;
- struct nand_ecclayout *ecclayout;
int err;
- int i;
- dma_cap_mask_t mask;
- unsigned sig;
+ int i, offset;
+ dma_cap_mask_t mask;
+ unsigned sig;
struct resource *res;
struct mtd_part_parser_data ppdata = {};
@@ -1642,8 +1837,7 @@ static int omap_nand_probe(struct platform_device *pdev)
return -ENODEV;
}
- info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info),
- GFP_KERNEL);
+ info = kzalloc(sizeof(struct omap_nand_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
@@ -1652,45 +1846,47 @@ static int omap_nand_probe(struct platform_device *pdev)
spin_lock_init(&info->controller.lock);
init_waitqueue_head(&info->controller.wq);
- info->pdev = pdev;
+ info->pdev = pdev;
+
info->gpmc_cs = pdata->cs;
info->reg = pdata->reg;
+
+ info->mtd.priv = &info->nand;
+ info->mtd.name = dev_name(&pdev->dev);
+ info->mtd.owner = THIS_MODULE;
+
+ info->nand.options = pdata->devsize;
+ info->nand.options |= NAND_SKIP_BBTSCAN;
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
info->of_node = pdata->of_node;
- mtd = &info->mtd;
- mtd->priv = &info->nand;
- mtd->name = dev_name(&pdev->dev);
- mtd->owner = THIS_MODULE;
- nand_chip = &info->nand;
- nand_chip->ecc.priv = NULL;
- nand_chip->options |= NAND_SKIP_BBTSCAN;
+#endif
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
err = -EINVAL;
dev_err(&pdev->dev, "error getting memory resource\n");
- goto return_error;
+ goto out_free_info;
}
info->phys_base = res->start;
info->mem_size = resource_size(res);
- if (!devm_request_mem_region(&pdev->dev, info->phys_base,
- info->mem_size, pdev->dev.driver->name)) {
+ if (!request_mem_region(info->phys_base, info->mem_size,
+ pdev->dev.driver->name)) {
err = -EBUSY;
- goto return_error;
+ goto out_free_info;
}
- nand_chip->IO_ADDR_R = devm_ioremap(&pdev->dev, info->phys_base,
- info->mem_size);
- if (!nand_chip->IO_ADDR_R) {
+ info->nand.IO_ADDR_R = ioremap(info->phys_base, info->mem_size);
+ if (!info->nand.IO_ADDR_R) {
err = -ENOMEM;
- goto return_error;
+ goto out_release_mem_region;
}
- nand_chip->controller = &info->controller;
+ info->nand.controller = &info->controller;
- nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R;
- nand_chip->cmd_ctrl = omap_hwcontrol;
+ info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
+ info->nand.cmd_ctrl = omap_hwcontrol;
/*
* If RDY/BSY line is connected to OMAP then use the omap ready
@@ -1700,42 +1896,26 @@ static int omap_nand_probe(struct platform_device *pdev)
* device and read status register until you get a failure or success
*/
if (pdata->dev_ready) {
- nand_chip->dev_ready = omap_dev_ready;
- nand_chip->chip_delay = 0;
+ info->nand.dev_ready = omap_dev_ready;
+ info->nand.chip_delay = 0;
} else {
- nand_chip->waitfunc = omap_wait;
- nand_chip->chip_delay = 50;
+ info->nand.waitfunc = omap_wait;
+ info->nand.chip_delay = 50;
}
- /* scan NAND device connected to chip controller */
- nand_chip->options |= pdata->devsize & NAND_BUSWIDTH_16;
- if (nand_scan_ident(mtd, 1, NULL)) {
- pr_err("nand device scan failed, may be bus-width mismatch\n");
- err = -ENXIO;
- goto return_error;
- }
-
- /* check for small page devices */
- if ((mtd->oobsize < 64) && (pdata->ecc_opt != OMAP_ECC_HAM1_CODE_HW)) {
- pr_err("small page devices are not supported\n");
- err = -EINVAL;
- goto return_error;
- }
-
- /* re-populate low-level callbacks based on xfer modes */
switch (pdata->xfer_type) {
case NAND_OMAP_PREFETCH_POLLED:
- nand_chip->read_buf = omap_read_buf_pref;
- nand_chip->write_buf = omap_write_buf_pref;
+ info->nand.read_buf = omap_read_buf_pref;
+ info->nand.write_buf = omap_write_buf_pref;
break;
case NAND_OMAP_POLLED:
- if (nand_chip->options & NAND_BUSWIDTH_16) {
- nand_chip->read_buf = omap_read_buf16;
- nand_chip->write_buf = omap_write_buf16;
+ if (info->nand.options & NAND_BUSWIDTH_16) {
+ info->nand.read_buf = omap_read_buf16;
+ info->nand.write_buf = omap_write_buf16;
} else {
- nand_chip->read_buf = omap_read_buf8;
- nand_chip->write_buf = omap_write_buf8;
+ info->nand.read_buf = omap_read_buf8;
+ info->nand.write_buf = omap_write_buf8;
}
break;
@@ -1747,7 +1927,7 @@ static int omap_nand_probe(struct platform_device *pdev)
if (!info->dma) {
dev_err(&pdev->dev, "DMA engine request failed\n");
err = -ENXIO;
- goto return_error;
+ goto out_release_mem_region;
} else {
struct dma_slave_config cfg;
@@ -1762,10 +1942,10 @@ static int omap_nand_probe(struct platform_device *pdev)
if (err) {
dev_err(&pdev->dev, "DMA engine slave config failed: %d\n",
err);
- goto return_error;
+ goto out_release_mem_region;
}
- nand_chip->read_buf = omap_read_buf_dma_pref;
- nand_chip->write_buf = omap_write_buf_dma_pref;
+ info->nand.read_buf = omap_read_buf_dma_pref;
+ info->nand.write_buf = omap_write_buf_dma_pref;
}
break;
@@ -1774,36 +1954,34 @@ static int omap_nand_probe(struct platform_device *pdev)
if (info->gpmc_irq_fifo <= 0) {
dev_err(&pdev->dev, "error getting fifo irq\n");
err = -ENODEV;
- goto return_error;
+ goto out_release_mem_region;
}
- err = devm_request_irq(&pdev->dev, info->gpmc_irq_fifo,
- omap_nand_irq, IRQF_SHARED,
- "gpmc-nand-fifo", info);
+ err = request_irq(info->gpmc_irq_fifo, omap_nand_irq,
+ IRQF_SHARED, "gpmc-nand-fifo", info);
if (err) {
dev_err(&pdev->dev, "requesting irq(%d) error:%d",
info->gpmc_irq_fifo, err);
info->gpmc_irq_fifo = 0;
- goto return_error;
+ goto out_release_mem_region;
}
info->gpmc_irq_count = platform_get_irq(pdev, 1);
if (info->gpmc_irq_count <= 0) {
dev_err(&pdev->dev, "error getting count irq\n");
err = -ENODEV;
- goto return_error;
+ goto out_release_mem_region;
}
- err = devm_request_irq(&pdev->dev, info->gpmc_irq_count,
- omap_nand_irq, IRQF_SHARED,
- "gpmc-nand-count", info);
+ err = request_irq(info->gpmc_irq_count, omap_nand_irq,
+ IRQF_SHARED, "gpmc-nand-count", info);
if (err) {
dev_err(&pdev->dev, "requesting irq(%d) error:%d",
info->gpmc_irq_count, err);
info->gpmc_irq_count = 0;
- goto return_error;
+ goto out_release_mem_region;
}
- nand_chip->read_buf = omap_read_buf_irq_pref;
- nand_chip->write_buf = omap_write_buf_irq_pref;
+ info->nand.read_buf = omap_read_buf_irq_pref;
+ info->nand.write_buf = omap_write_buf_irq_pref;
break;
@@ -1811,223 +1989,117 @@ static int omap_nand_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"xfer_type(%d) not supported!\n", pdata->xfer_type);
err = -EINVAL;
- goto return_error;
+ goto out_release_mem_region;
}
- /* populate MTD interface based on ECC scheme */
- nand_chip->ecc.layout = &omap_oobinfo;
- ecclayout = &omap_oobinfo;
- switch (pdata->ecc_opt) {
- case OMAP_ECC_HAM1_CODE_HW:
- pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n");
- nand_chip->ecc.mode = NAND_ECC_HW;
- nand_chip->ecc.bytes = 3;
- nand_chip->ecc.size = 512;
- nand_chip->ecc.strength = 1;
- nand_chip->ecc.calculate = omap_calculate_ecc;
- nand_chip->ecc.hwctl = omap_enable_hwecc;
- nand_chip->ecc.correct = omap_correct_data;
- /* define ECC layout */
- ecclayout->eccbytes = nand_chip->ecc.bytes *
- (mtd->writesize /
- nand_chip->ecc.size);
- if (nand_chip->options & NAND_BUSWIDTH_16)
- ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
- else
- ecclayout->eccpos[0] = 1;
- ecclayout->oobfree->offset = ecclayout->eccpos[0] +
- ecclayout->eccbytes;
- break;
-
- case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
-#ifdef CONFIG_MTD_NAND_ECC_BCH
- pr_info("nand: using OMAP_ECC_BCH4_CODE_HW_DETECTION_SW\n");
- nand_chip->ecc.mode = NAND_ECC_HW;
- nand_chip->ecc.size = 512;
- nand_chip->ecc.bytes = 7;
- nand_chip->ecc.strength = 4;
- nand_chip->ecc.hwctl = omap3_enable_hwecc_bch;
- nand_chip->ecc.correct = nand_bch_correct_data;
- nand_chip->ecc.calculate = omap3_calculate_ecc_bch4;
- /* define ECC layout */
- ecclayout->eccbytes = nand_chip->ecc.bytes *
- (mtd->writesize /
- nand_chip->ecc.size);
- ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
- ecclayout->oobfree->offset = ecclayout->eccpos[0] +
- ecclayout->eccbytes;
- /* software bch library is used for locating errors */
- nand_chip->ecc.priv = nand_bch_init(mtd,
- nand_chip->ecc.size,
- nand_chip->ecc.bytes,
- &nand_chip->ecc.layout);
- if (!nand_chip->ecc.priv) {
- pr_err("nand: error: unable to use s/w BCH library\n");
+ /* select the ecc type */
+ if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT)
+ info->nand.ecc.mode = NAND_ECC_SOFT;
+ else if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW) ||
+ (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE)) {
+ info->nand.ecc.bytes = 3;
+ info->nand.ecc.size = 512;
+ info->nand.ecc.strength = 1;
+ info->nand.ecc.calculate = omap_calculate_ecc;
+ info->nand.ecc.hwctl = omap_enable_hwecc;
+ info->nand.ecc.correct = omap_correct_data;
+ info->nand.ecc.mode = NAND_ECC_HW;
+ } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) ||
+ (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) {
+ err = omap3_init_bch(&info->mtd, pdata->ecc_opt);
+ if (err) {
err = -EINVAL;
+ goto out_release_mem_region;
}
- break;
-#else
- pr_err("nand: error: CONFIG_MTD_NAND_ECC_BCH not enabled\n");
- err = -EINVAL;
- goto return_error;
-#endif
+ }
- case OMAP_ECC_BCH4_CODE_HW:
-#ifdef CONFIG_MTD_NAND_OMAP_BCH
- pr_info("nand: using OMAP_ECC_BCH4_CODE_HW ECC scheme\n");
- nand_chip->ecc.mode = NAND_ECC_HW;
- nand_chip->ecc.size = 512;
- /* 14th bit is kept reserved for ROM-code compatibility */
- nand_chip->ecc.bytes = 7 + 1;
- nand_chip->ecc.strength = 4;
- nand_chip->ecc.hwctl = omap3_enable_hwecc_bch;
- nand_chip->ecc.correct = omap_elm_correct_data;
- nand_chip->ecc.calculate = omap3_calculate_ecc_bch;
- nand_chip->ecc.read_page = omap_read_page_bch;
- nand_chip->ecc.write_page = omap_write_page_bch;
- /* define ECC layout */
- ecclayout->eccbytes = nand_chip->ecc.bytes *
- (mtd->writesize /
- nand_chip->ecc.size);
- ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
- ecclayout->oobfree->offset = ecclayout->eccpos[0] +
- ecclayout->eccbytes;
- /* This ECC scheme requires ELM H/W block */
- if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) {
- pr_err("nand: error: could not initialize ELM\n");
- err = -ENODEV;
- goto return_error;
+ /* DIP switches on some boards change between 8 and 16 bit
+ * bus widths for flash. Try the other width if the first try fails.
+ */
+ if (nand_scan_ident(&info->mtd, 1, NULL)) {
+ info->nand.options ^= NAND_BUSWIDTH_16;
+ if (nand_scan_ident(&info->mtd, 1, NULL)) {
+ err = -ENXIO;
+ goto out_release_mem_region;
}
- break;
-#else
- pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
- err = -EINVAL;
- goto return_error;
-#endif
+ }
- case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
-#ifdef CONFIG_MTD_NAND_ECC_BCH
- pr_info("nand: using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
- nand_chip->ecc.mode = NAND_ECC_HW;
- nand_chip->ecc.size = 512;
- nand_chip->ecc.bytes = 13;
- nand_chip->ecc.strength = 8;
- nand_chip->ecc.hwctl = omap3_enable_hwecc_bch;
- nand_chip->ecc.correct = nand_bch_correct_data;
- nand_chip->ecc.calculate = omap3_calculate_ecc_bch8;
- /* define ECC layout */
- ecclayout->eccbytes = nand_chip->ecc.bytes *
- (mtd->writesize /
- nand_chip->ecc.size);
- ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
- ecclayout->oobfree->offset = ecclayout->eccpos[0] +
- ecclayout->eccbytes;
- /* software bch library is used for locating errors */
- nand_chip->ecc.priv = nand_bch_init(mtd,
- nand_chip->ecc.size,
- nand_chip->ecc.bytes,
- &nand_chip->ecc.layout);
- if (!nand_chip->ecc.priv) {
- pr_err("nand: error: unable to use s/w BCH library\n");
- err = -EINVAL;
- goto return_error;
- }
- break;
-#else
- pr_err("nand: error: CONFIG_MTD_NAND_ECC_BCH not enabled\n");
- err = -EINVAL;
- goto return_error;
-#endif
+ /* rom code layout */
+ if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE) {
- case OMAP_ECC_BCH8_CODE_HW:
-#ifdef CONFIG_MTD_NAND_OMAP_BCH
- pr_info("nand: using OMAP_ECC_BCH8_CODE_HW ECC scheme\n");
- nand_chip->ecc.mode = NAND_ECC_HW;
- nand_chip->ecc.size = 512;
- /* 14th bit is kept reserved for ROM-code compatibility */
- nand_chip->ecc.bytes = 13 + 1;
- nand_chip->ecc.strength = 8;
- nand_chip->ecc.hwctl = omap3_enable_hwecc_bch;
- nand_chip->ecc.correct = omap_elm_correct_data;
- nand_chip->ecc.calculate = omap3_calculate_ecc_bch;
- nand_chip->ecc.read_page = omap_read_page_bch;
- nand_chip->ecc.write_page = omap_write_page_bch;
- /* This ECC scheme requires ELM H/W block */
- err = is_elm_present(info, pdata->elm_of_node, BCH8_ECC);
- if (err < 0) {
- pr_err("nand: error: could not initialize ELM\n");
- goto return_error;
+ if (info->nand.options & NAND_BUSWIDTH_16)
+ offset = 2;
+ else {
+ offset = 1;
+ info->nand.badblock_pattern = &bb_descrip_flashbased;
+ }
+ omap_oobinfo.eccbytes = 3 * (info->mtd.oobsize/16);
+ for (i = 0; i < omap_oobinfo.eccbytes; i++)
+ omap_oobinfo.eccpos[i] = i+offset;
+
+ omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes;
+ omap_oobinfo.oobfree->length = info->mtd.oobsize -
+ (offset + omap_oobinfo.eccbytes);
+
+ info->nand.ecc.layout = &omap_oobinfo;
+ } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) ||
+ (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) {
+ /* build OOB layout for BCH ECC correction */
+ err = omap3_init_bch_tail(&info->mtd);
+ if (err) {
+ err = -EINVAL;
+ goto out_release_mem_region;
}
- /* define ECC layout */
- ecclayout->eccbytes = nand_chip->ecc.bytes *
- (mtd->writesize /
- nand_chip->ecc.size);
- ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH;
- ecclayout->oobfree->offset = ecclayout->eccpos[0] +
- ecclayout->eccbytes;
- break;
-#else
- pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
- err = -EINVAL;
- goto return_error;
-#endif
-
- default:
- pr_err("nand: error: invalid or unsupported ECC scheme\n");
- err = -EINVAL;
- goto return_error;
- }
-
- /* populate remaining ECC layout data */
- ecclayout->oobfree->length = mtd->oobsize - (BADBLOCK_MARKER_LENGTH +
- ecclayout->eccbytes);
- for (i = 1; i < ecclayout->eccbytes; i++)
- ecclayout->eccpos[i] = ecclayout->eccpos[0] + i;
- /* check if NAND device's OOB is enough to store ECC signatures */
- if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) {
- pr_err("not enough OOB bytes required = %d, available=%d\n",
- ecclayout->eccbytes, mtd->oobsize);
- err = -EINVAL;
- goto return_error;
}
/* second phase scan */
- if (nand_scan_tail(mtd)) {
+ if (nand_scan_tail(&info->mtd)) {
err = -ENXIO;
- goto return_error;
+ goto out_release_mem_region;
}
ppdata.of_node = pdata->of_node;
- mtd_device_parse_register(mtd, NULL, &ppdata, pdata->parts,
+ mtd_device_parse_register(&info->mtd, NULL, &ppdata, pdata->parts,
pdata->nr_parts);
- platform_set_drvdata(pdev, mtd);
+ platform_set_drvdata(pdev, &info->mtd);
return 0;
-return_error:
+out_release_mem_region:
if (info->dma)
dma_release_channel(info->dma);
- if (nand_chip->ecc.priv) {
- nand_bch_free(nand_chip->ecc.priv);
- nand_chip->ecc.priv = NULL;
- }
+ if (info->gpmc_irq_count > 0)
+ free_irq(info->gpmc_irq_count, info);
+ if (info->gpmc_irq_fifo > 0)
+ free_irq(info->gpmc_irq_fifo, info);
+ release_mem_region(info->phys_base, info->mem_size);
+out_free_info:
+ kfree(info);
+
return err;
}
static int omap_nand_remove(struct platform_device *pdev)
{
struct mtd_info *mtd = platform_get_drvdata(pdev);
- struct nand_chip *nand_chip = mtd->priv;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- if (nand_chip->ecc.priv) {
- nand_bch_free(nand_chip->ecc.priv);
- nand_chip->ecc.priv = NULL;
- }
+ omap3_free_bch(&info->mtd);
+
if (info->dma)
dma_release_channel(info->dma);
- nand_release(mtd);
+
+ if (info->gpmc_irq_count > 0)
+ free_irq(info->gpmc_irq_count, info);
+ if (info->gpmc_irq_fifo > 0)
+ free_irq(info->gpmc_irq_fifo, info);
+
+ /* Release NAND device, its internal structures and partitions */
+ nand_release(&info->mtd);
+ iounmap(info->nand.IO_ADDR_R);
+ release_mem_region(info->phys_base, info->mem_size);
+ kfree(info);
return 0;
}
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index 4d17436..5a67082 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -28,8 +28,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 4cabdc9..c28d4e2 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -39,13 +39,6 @@
#define NAND_STOP_DELAY (2 * HZ/50)
#define PAGE_CHUNK_SIZE (2048)
-/*
- * Define a buffer size for the initial command that detects the flash device:
- * STATUS, READID and PARAM. The largest of these is the PARAM command,
- * needing 256 bytes.
- */
-#define INIT_BUFFER_SIZE 256
-
/* registers and bit definitions */
#define NDCR (0x00) /* Control register */
#define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */
@@ -171,7 +164,6 @@ struct pxa3xx_nand_info {
unsigned int buf_start;
unsigned int buf_count;
- unsigned int buf_size;
/* DMA information */
int drcmr_dat;
@@ -548,6 +540,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
info->oob_size = 0;
info->use_ecc = 0;
info->use_spare = 1;
+ info->use_dma = (use_dma) ? 1 : 0;
info->is_ready = 0;
info->retcode = ERR_NONE;
if (info->cs != 0)
@@ -919,20 +912,26 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
return 0;
}
+/* the maximum possible buffer size for large page with OOB data
+ * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
+ * data buffer and the DMA descriptor
+ */
+#define MAX_BUFF_SIZE PAGE_SIZE
+
#ifdef ARCH_HAS_DMA
static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
{
struct platform_device *pdev = info->pdev;
- int data_desc_offset = info->buf_size - sizeof(struct pxa_dma_desc);
+ int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);
if (use_dma == 0) {
- info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
+ info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
if (info->data_buff == NULL)
return -ENOMEM;
return 0;
}
- info->data_buff = dma_alloc_coherent(&pdev->dev, info->buf_size,
+ info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
&info->data_buff_phys, GFP_KERNEL);
if (info->data_buff == NULL) {
dev_err(&pdev->dev, "failed to allocate dma buffer\n");
@@ -946,16 +945,11 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
pxa3xx_nand_data_dma_irq, info);
if (info->data_dma_ch < 0) {
dev_err(&pdev->dev, "failed to request data dma\n");
- dma_free_coherent(&pdev->dev, info->buf_size,
+ dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
info->data_buff, info->data_buff_phys);
return info->data_dma_ch;
}
- /*
- * Now that DMA buffers are allocated we turn on
- * DMA proper for I/O operations.
- */
- info->use_dma = 1;
return 0;
}
@@ -964,7 +958,7 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
struct platform_device *pdev = info->pdev;
if (use_dma) {
pxa_free_dma(info->data_dma_ch);
- dma_free_coherent(&pdev->dev, info->buf_size,
+ dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
info->data_buff, info->data_buff_phys);
} else {
kfree(info->data_buff);
@@ -973,7 +967,7 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
#else
static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
{
- info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
+ info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
if (info->data_buff == NULL)
return -ENOMEM;
return 0;
@@ -1087,16 +1081,7 @@ KEEP_CONFIG:
else
host->col_addr_cycles = 1;
- /* release the initial buffer */
- kfree(info->data_buff);
-
- /* allocate the real data + oob buffer */
- info->buf_size = mtd->writesize + mtd->oobsize;
- ret = pxa3xx_nand_init_buff(info);
- if (ret)
- return ret;
info->oob_buff = info->data_buff + mtd->writesize;
-
if ((mtd->size >> chip->page_shift) > 65536)
host->row_addr_cycles = 3;
else
@@ -1202,18 +1187,15 @@ static int alloc_nand_resource(struct platform_device *pdev)
}
info->mmio_phys = r->start;
- /* Allocate a buffer to allow flash detection */
- info->buf_size = INIT_BUFFER_SIZE;
- info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
- if (info->data_buff == NULL) {
- ret = -ENOMEM;
+ ret = pxa3xx_nand_init_buff(info);
+ if (ret)
goto fail_disable_clk;
- }
/* initialize all interrupts to be disabled */
disable_int(info, NDSR_MASK);
- ret = request_irq(irq, pxa3xx_nand_irq, 0, pdev->name, info);
+ ret = request_irq(irq, pxa3xx_nand_irq, IRQF_DISABLED,
+ pdev->name, info);
if (ret < 0) {
dev_err(&pdev->dev, "failed to request IRQ\n");
goto fail_free_buf;
@@ -1225,7 +1207,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
fail_free_buf:
free_irq(irq, info);
- kfree(info->data_buff);
+ pxa3xx_nand_free_buff(info);
fail_disable_clk:
clk_disable_unprepare(info->clk);
return ret;
@@ -1430,7 +1412,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
static struct platform_driver pxa3xx_nand_driver = {
.driver = {
.name = "pxa3xx-nand",
- .of_match_table = pxa3xx_nand_dt_ids,
+ .of_match_table = of_match_ptr(pxa3xx_nand_dt_ids),
},
.probe = pxa3xx_nand_probe,
.remove = pxa3xx_nand_remove,
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 325930d..9dcf02d 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -181,7 +181,7 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read)
/* Set dma direction */
dev->dma_dir = do_read;
dev->dma_stage = 1;
- reinit_completion(&dev->dma_done);
+ INIT_COMPLETION(dev->dma_done);
dbg_verbose("doing dma %s ", do_read ? "read" : "write");
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index fe8058a..09dde7d 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -15,7 +15,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
-#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/io.h>
@@ -150,13 +149,17 @@ static int socrates_nand_probe(struct platform_device *ofdev)
struct mtd_part_parser_data ppdata;
/* Allocate memory for the device structure (and zero it) */
- host = devm_kzalloc(&ofdev->dev, sizeof(*host), GFP_KERNEL);
- if (!host)
+ host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL);
+ if (!host) {
+ printk(KERN_ERR
+ "socrates_nand: failed to allocate device structure.\n");
return -ENOMEM;
+ }
host->io_base = of_iomap(ofdev->dev.of_node, 0);
if (host->io_base == NULL) {
- dev_err(&ofdev->dev, "ioremap failed\n");
+ printk(KERN_ERR "socrates_nand: ioremap failed\n");
+ kfree(host);
return -EIO;
}
@@ -208,7 +211,9 @@ static int socrates_nand_probe(struct platform_device *ofdev)
nand_release(mtd);
out:
+ dev_set_drvdata(&ofdev->dev, NULL);
iounmap(host->io_base);
+ kfree(host);
return res;
}
@@ -222,7 +227,9 @@ static int socrates_nand_remove(struct platform_device *ofdev)
nand_release(mtd);
+ dev_set_drvdata(&ofdev->dev, NULL);
iounmap(host->io_base);
+ kfree(host);
return 0;
}
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index a3747c9..396530d 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -428,7 +428,8 @@ static int tmio_probe(struct platform_device *dev)
/* 15 us command delay time */
nand_chip->chip_delay = 15;
- retval = request_irq(irq, &tmio_irq, 0, dev_name(&dev->dev), tmio);
+ retval = request_irq(irq, &tmio_irq,
+ IRQF_DISABLED, dev_name(&dev->dev), tmio);
if (retval) {
dev_err(&dev->dev, "request_irq error %d\n", retval);
goto err_irq;
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index 46f27de..c5f4ebf 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -50,7 +50,7 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
struct NFTLrecord *nftl;
unsigned long temp;
- if (!mtd_type_is_nand(mtd) || mtd->size > UINT_MAX)
+ if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX)
return;
/* OK, this is moderately ugly. But probably safe. Alternatives? */
if (memcmp(mtd->name, "DiskOnChip", 10))
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 6547c84..558071b 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -159,7 +159,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
}
- reinit_completion(&c->irq_done);
+ INIT_COMPLETION(c->irq_done);
if (c->gpio_irq) {
result = gpio_get_value(c->gpio_irq);
if (result == -1) {
@@ -349,7 +349,7 @@ static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
dma_dst, 0, 0);
- reinit_completion(&c->dma_done);
+ INIT_COMPLETION(c->dma_done);
omap_start_dma(c->dma_channel);
timeout = jiffies + msecs_to_jiffies(20);
@@ -420,7 +420,7 @@ static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
dma_dst, 0, 0);
- reinit_completion(&c->dma_done);
+ INIT_COMPLETION(c->dma_done);
omap_start_dma(c->dma_channel);
timeout = jiffies + msecs_to_jiffies(20);
@@ -499,7 +499,7 @@ static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
dma_dst, 0, 0);
- reinit_completion(&c->dma_done);
+ INIT_COMPLETION(c->dma_done);
omap_start_dma(c->dma_channel);
wait_for_completion(&c->dma_done);
@@ -544,7 +544,7 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
dma_dst, 0, 0);
- reinit_completion(&c->dma_done);
+ INIT_COMPLETION(c->dma_done);
omap_start_dma(c->dma_channel);
wait_for_completion(&c->dma_done);
@@ -573,6 +573,28 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
static struct platform_driver omap2_onenand_driver;
+static int __adjust_timing(struct device *dev, void *data)
+{
+ int ret = 0;
+ struct omap2_onenand *c;
+
+ c = dev_get_drvdata(dev);
+
+ BUG_ON(c->setup == NULL);
+
+ /* DMA is not in use so this is all that is needed */
+ /* Revisit for OMAP3! */
+ ret = c->setup(c->onenand.base, &c->freq);
+
+ return ret;
+}
+
+int omap2_onenand_rephase(void)
+{
+ return driver_for_each_device(&omap2_onenand_driver.driver, NULL,
+ NULL, __adjust_timing);
+}
+
static void omap2_onenand_shutdown(struct platform_device *pdev)
{
struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 1de33b5..b3f41f2 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -2556,6 +2556,10 @@ static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
int ret;
+ /* Check for invalid offset */
+ if (ofs > mtd->size)
+ return -EINVAL;
+
onenand_get_device(mtd, FL_READING);
ret = onenand_block_isbad_nolock(mtd, ofs, 0);
onenand_release_device(mtd);
@@ -3525,7 +3529,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
{
struct onenand_chip *this = mtd->priv;
unsigned die, bdry;
- int syscfg, locked;
+ int ret, syscfg, locked;
/* Disable ECC */
syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
@@ -3536,7 +3540,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
this->wait(mtd, FL_SYNCING);
this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
- this->wait(mtd, FL_READING);
+ ret = this->wait(mtd, FL_READING);
bdry = this->read_word(this->base + ONENAND_DATARAM);
if ((bdry >> FLEXONENAND_PI_UNLOCK_SHIFT) == 3)
@@ -3546,7 +3550,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
this->boundary[die] = bdry & FLEXONENAND_PI_MASK;
this->command(mtd, ONENAND_CMD_RESET, 0, 0);
- this->wait(mtd, FL_RESETING);
+ ret = this->wait(mtd, FL_RESETING);
printk(KERN_INFO "Die %d boundary: %d%s\n", die,
this->boundary[die], locked ? "(Locked)" : "(Unlocked)");
@@ -3730,7 +3734,7 @@ static int flexonenand_set_boundary(struct mtd_info *mtd, int die,
/* Check is boundary is locked */
this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
- this->wait(mtd, FL_READING);
+ ret = this->wait(mtd, FL_READING);
thisboundary = this->read_word(this->base + ONENAND_DATARAM);
if ((thisboundary >> FLEXONENAND_PI_UNLOCK_SHIFT) != 3) {
@@ -3831,7 +3835,7 @@ static int onenand_chip_probe(struct mtd_info *mtd)
static int onenand_probe(struct mtd_info *mtd)
{
struct onenand_chip *this = mtd->priv;
- int dev_id, ver_id;
+ int maf_id, dev_id, ver_id;
int density;
int ret;
@@ -3839,7 +3843,8 @@ static int onenand_probe(struct mtd_info *mtd)
if (ret)
return ret;
- /* Device and version IDs from Register */
+ /* Read manufacturer and device IDs from Register */
+ maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index daf82ba..ab2a52a 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -290,7 +290,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
int cis_sector;
/* Check for small page NAND flash */
- if (!mtd_type_is_nand(mtd) || mtd->oobsize != OOB_SIZE ||
+ if (mtd->type != MTD_NANDFLASH || mtd->oobsize != OOB_SIZE ||
mtd->size > UINT_MAX)
return;
diff --git a/drivers/mtd/tests/nandbiterrs.c b/drivers/mtd/tests/nandbiterrs.c
index 6f97615..3cd3aab 100644
--- a/drivers/mtd/tests/nandbiterrs.c
+++ b/drivers/mtd/tests/nandbiterrs.c
@@ -349,7 +349,7 @@ static int __init mtd_nandbiterrs_init(void)
goto exit_mtddev;
}
- if (!mtd_type_is_nand(mtd)) {
+ if (mtd->type != MTD_NANDFLASH) {
pr_info("this test requires NAND flash\n");
err = -ENODEV;
goto exit_nand;
diff --git a/drivers/mtd/tests/oobtest.c b/drivers/mtd/tests/oobtest.c
index 2e9e2d1..ff35c46 100644
--- a/drivers/mtd/tests/oobtest.c
+++ b/drivers/mtd/tests/oobtest.c
@@ -289,7 +289,7 @@ static int __init mtd_oobtest_init(void)
return err;
}
- if (!mtd_type_is_nand(mtd)) {
+ if (mtd->type != MTD_NANDFLASH) {
pr_info("this test requires NAND flash\n");
goto out;
}
diff --git a/drivers/mtd/tests/pagetest.c b/drivers/mtd/tests/pagetest.c
index ed2d3f6..44b96e9 100644
--- a/drivers/mtd/tests/pagetest.c
+++ b/drivers/mtd/tests/pagetest.c
@@ -353,7 +353,7 @@ static int __init mtd_pagetest_init(void)
return err;
}
- if (!mtd_type_is_nand(mtd)) {
+ if (mtd->type != MTD_NANDFLASH) {
pr_info("this test requires NAND flash\n");
goto out;
}
diff --git a/drivers/mtd/tests/subpagetest.c b/drivers/mtd/tests/subpagetest.c
index a876371..e2c0adf 100644
--- a/drivers/mtd/tests/subpagetest.c
+++ b/drivers/mtd/tests/subpagetest.c
@@ -299,7 +299,7 @@ static int __init mtd_subpagetest_init(void)
return err;
}
- if (!mtd_type_is_nand(mtd)) {
+ if (mtd->type != MTD_NANDFLASH) {
pr_info("this test requires NAND flash\n");
goto out;
}
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 33bb1f2..c071d41 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -900,9 +900,10 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
* number.
*/
image_seq = be32_to_cpu(ech->image_seq);
- if (!ubi->image_seq)
+ if (!ubi->image_seq && image_seq)
ubi->image_seq = image_seq;
- if (image_seq && ubi->image_seq != image_seq) {
+ if (ubi->image_seq && image_seq &&
+ ubi->image_seq != image_seq) {
ubi_err("bad image sequence number %d in PEB %d, expected %d",
image_seq, pnum, ubi->image_seq);
ubi_dump_ec_hdr(ech);
@@ -1416,11 +1417,9 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
ai = alloc_ai("ubi_aeb_slab_cache2");
if (!ai)
return -ENOMEM;
-
- err = scan_all(ubi, ai, 0);
- } else {
- err = scan_all(ubi, ai, UBI_FM_MAX_START);
}
+
+ err = scan_all(ubi, ai, UBI_FM_MAX_START);
}
}
#else
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index e05dc62..315dcc6 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -41,7 +41,6 @@
#include <linux/kthread.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/major.h>
#include "ubi.h"
/* Maximum length of the 'mtd=' parameter */
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index ead8613..f5aa4b0 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -407,7 +407,6 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
*/
for (i = 0; i < pool_size; i++) {
int scrub = 0;
- int image_seq;
pnum = be32_to_cpu(pebs[i]);
@@ -426,16 +425,10 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
} else if (ret == UBI_IO_BITFLIPS)
scrub = 1;
- /*
- * Older UBI implementations have image_seq set to zero, so
- * we shouldn't fail if image_seq == 0.
- */
- image_seq = be32_to_cpu(ech->image_seq);
-
- if (image_seq && (image_seq != ubi->image_seq)) {
+ if (be32_to_cpu(ech->image_seq) != ubi->image_seq) {
ubi_err("bad image seq: 0x%x, expected: 0x%x",
be32_to_cpu(ech->image_seq), ubi->image_seq);
- ret = UBI_BAD_FASTMAP;
+ err = UBI_BAD_FASTMAP;
goto out;
}
@@ -826,10 +819,6 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list)
list_move_tail(&tmp_aeb->u.list, &ai->free);
- ubi_assert(list_empty(&used));
- ubi_assert(list_empty(&eba_orphans));
- ubi_assert(list_empty(&free));
-
/*
* If fastmap is leaking PEBs (must not happen), raise a
* fat warning and fall back to scanning mode.
@@ -845,19 +834,6 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
fail_bad:
ret = UBI_BAD_FASTMAP;
fail:
- list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) {
- kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
- list_del(&tmp_aeb->u.list);
- }
- list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans, u.list) {
- kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
- list_del(&tmp_aeb->u.list);
- }
- list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
- kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
- list_del(&tmp_aeb->u.list);
- }
-
return ret;
}
@@ -947,8 +923,6 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
}
for (i = 0; i < used_blocks; i++) {
- int image_seq;
-
pnum = be32_to_cpu(fmsb->block_loc[i]);
if (ubi_io_is_bad(ubi, pnum)) {
@@ -966,17 +940,10 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
} else if (ret == UBI_IO_BITFLIPS)
fm->to_be_tortured[i] = 1;
- image_seq = be32_to_cpu(ech->image_seq);
if (!ubi->image_seq)
- ubi->image_seq = image_seq;
+ ubi->image_seq = be32_to_cpu(ech->image_seq);
- /*
- * Older UBI implementations have image_seq set to zero, so
- * we shouldn't fail if image_seq == 0.
- */
- if (image_seq && (image_seq != ubi->image_seq)) {
- ubi_err("wrong image seq:%d instead of %d",
- be32_to_cpu(ech->image_seq), ubi->image_seq);
+ if (be32_to_cpu(ech->image_seq) != ubi->image_seq) {
ret = UBI_BAD_FASTMAP;
goto free_hdr;
}
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 02317c1..c95bfb1 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -599,6 +599,10 @@ static void refill_wl_user_pool(struct ubi_device *ubi)
return_unused_pool_pebs(ubi, pool);
for (pool->size = 0; pool->size < pool->max_size; pool->size++) {
+ if (!ubi->free.rb_node ||
+ (ubi->free_count - ubi->beb_rsvd_pebs < 1))
+ break;
+
pool->pebs[pool->size] = __wl_get_peb(ubi);
if (pool->pebs[pool->size] < 0)
break;