summaryrefslogtreecommitdiff
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/atmel_nand.c2
-rw-r--r--drivers/mtd/nand/au1550nd.c2
-rw-r--r--drivers/mtd/nand/bf5xx_nand.c2
-rw-r--r--drivers/mtd/nand/davinci_nand.c6
-rw-r--r--drivers/mtd/nand/gpio.c231
-rw-r--r--drivers/mtd/nand/jz4740_nand.c4
-rw-r--r--drivers/mtd/nand/lpc32xx_mlc.c2
-rw-r--r--drivers/mtd/nand/lpc32xx_slc.c2
-rw-r--r--drivers/mtd/nand/mxc_nand.c3
-rw-r--r--drivers/mtd/nand/nand_bbt.c33
-rw-r--r--drivers/mtd/nand/omap2.c662
-rw-r--r--drivers/mtd/nand/orion_nand.c5
-rw-r--r--drivers/mtd/nand/plat_nand.c4
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c124
-rw-r--r--drivers/mtd/nand/s3c2410.c2
-rw-r--r--drivers/mtd/nand/sh_flctl.c4
-rw-r--r--drivers/mtd/nand/sharpsl.c2
-rw-r--r--drivers/mtd/nand/tmio_nand.c2
-rw-r--r--drivers/mtd/nand/txx9ndfmc.c8
19 files changed, 447 insertions, 653 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 2d23d292943..023541d7a30 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -1502,7 +1502,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
if (res)
goto err_ecc_ioremap;
} else {
- memcpy(&host->board, pdev->dev.platform_data,
+ memcpy(&host->board, dev_get_platdata(&pdev->dev),
sizeof(struct atmel_nand_data));
}
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 217459d02b2..ae8dd7c4103 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -411,7 +411,7 @@ static int au1550nd_probe(struct platform_device *pdev)
struct resource *r;
int ret, cs;
- pd = pdev->dev.platform_data;
+ pd = dev_get_platdata(&pdev->dev);
if (!pd) {
dev_err(&pdev->dev, "missing platform data\n");
return -ENODEV;
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 776df3694f7..d7f7df3cd96 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -171,7 +171,7 @@ static struct bf5xx_nand_info *to_nand_info(struct platform_device *pdev)
static struct bf5xx_nand_platform *to_nand_plat(struct platform_device *pdev)
{
- return pdev->dev.platform_data;
+ return dev_get_platdata(&pdev->dev);
}
/*
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index c3e15a55817..758a111a3bc 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -530,7 +530,7 @@ MODULE_DEVICE_TABLE(of, davinci_nand_of_match);
static struct davinci_nand_pdata
*nand_davinci_get_pdata(struct platform_device *pdev)
{
- if (!pdev->dev.platform_data && pdev->dev.of_node) {
+ if (!dev_get_platdata(&pdev->dev) && pdev->dev.of_node) {
struct davinci_nand_pdata *pdata;
const char *mode;
u32 prop;
@@ -575,13 +575,13 @@ static struct davinci_nand_pdata
pdata->bbt_options = NAND_BBT_USE_FLASH;
}
- return pdev->dev.platform_data;
+ return dev_get_platdata(&pdev->dev);
}
#else
static struct davinci_nand_pdata
*nand_davinci_get_pdata(struct platform_device *pdev)
{
- return pdev->dev.platform_data;
+ return dev_get_platdata(&pdev->dev);
}
#endif
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
index 89065dd83d6..e826f898241 100644
--- a/drivers/mtd/nand/gpio.c
+++ b/drivers/mtd/nand/gpio.c
@@ -17,6 +17,7 @@
*/
#include <linux/kernel.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -86,59 +87,11 @@ static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
gpio_nand_dosync(gpiomtd);
}
-static void gpio_nand_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
-{
- struct nand_chip *this = mtd->priv;
-
- iowrite8_rep(this->IO_ADDR_W, buf, len);
-}
-
-static void gpio_nand_readbuf(struct mtd_info *mtd, u_char *buf, int len)
-{
- struct nand_chip *this = mtd->priv;
-
- ioread8_rep(this->IO_ADDR_R, buf, len);
-}
-
-static void gpio_nand_writebuf16(struct mtd_info *mtd, const u_char *buf,
- int len)
-{
- struct nand_chip *this = mtd->priv;
-
- if (IS_ALIGNED((unsigned long)buf, 2)) {
- iowrite16_rep(this->IO_ADDR_W, buf, len>>1);
- } else {
- int i;
- unsigned short *ptr = (unsigned short *)buf;
-
- for (i = 0; i < len; i += 2, ptr++)
- writew(*ptr, this->IO_ADDR_W);
- }
-}
-
-static void gpio_nand_readbuf16(struct mtd_info *mtd, u_char *buf, int len)
-{
- struct nand_chip *this = mtd->priv;
-
- if (IS_ALIGNED((unsigned long)buf, 2)) {
- ioread16_rep(this->IO_ADDR_R, buf, len>>1);
- } else {
- int i;
- unsigned short *ptr = (unsigned short *)buf;
-
- for (i = 0; i < len; i += 2, ptr++)
- *ptr = readw(this->IO_ADDR_R);
- }
-}
-
static int gpio_nand_devready(struct mtd_info *mtd)
{
struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
- if (gpio_is_valid(gpiomtd->plat.gpio_rdy))
- return gpio_get_value(gpiomtd->plat.gpio_rdy);
-
- return 1;
+ return gpio_get_value(gpiomtd->plat.gpio_rdy);
}
#ifdef CONFIG_OF
@@ -153,6 +106,9 @@ static int gpio_nand_get_config_of(const struct device *dev,
{
u32 val;
+ if (!dev->of_node)
+ return -ENODEV;
+
if (!of_property_read_u32(dev->of_node, "bank-width", &val)) {
if (val == 2) {
plat->options |= NAND_BUSWIDTH_16;
@@ -211,8 +167,8 @@ static inline int gpio_nand_get_config(const struct device *dev,
if (!ret)
return ret;
- if (dev->platform_data) {
- memcpy(plat, dev->platform_data, sizeof(*plat));
+ if (dev_get_platdata(dev)) {
+ memcpy(plat, dev_get_platdata(dev), sizeof(*plat));
return 0;
}
@@ -230,145 +186,100 @@ gpio_nand_get_io_sync(struct platform_device *pdev)
return platform_get_resource(pdev, IORESOURCE_MEM, 1);
}
-static int gpio_nand_remove(struct platform_device *dev)
+static int gpio_nand_remove(struct platform_device *pdev)
{
- struct gpiomtd *gpiomtd = platform_get_drvdata(dev);
- struct resource *res;
+ struct gpiomtd *gpiomtd = platform_get_drvdata(pdev);
nand_release(&gpiomtd->mtd_info);
- res = gpio_nand_get_io_sync(dev);
- iounmap(gpiomtd->io_sync);
- if (res)
- release_mem_region(res->start, resource_size(res));
-
- res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- iounmap(gpiomtd->nand_chip.IO_ADDR_R);
- release_mem_region(res->start, resource_size(res));
-
if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
gpio_set_value(gpiomtd->plat.gpio_nce, 1);
- gpio_free(gpiomtd->plat.gpio_cle);
- gpio_free(gpiomtd->plat.gpio_ale);
- gpio_free(gpiomtd->plat.gpio_nce);
- if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
- gpio_free(gpiomtd->plat.gpio_nwp);
- if (gpio_is_valid(gpiomtd->plat.gpio_rdy))
- gpio_free(gpiomtd->plat.gpio_rdy);
-
return 0;
}
-static void __iomem *request_and_remap(struct resource *res, size_t size,
- const char *name, int *err)
-{
- void __iomem *ptr;
-
- if (!request_mem_region(res->start, resource_size(res), name)) {
- *err = -EBUSY;
- return NULL;
- }
-
- ptr = ioremap(res->start, size);
- if (!ptr) {
- release_mem_region(res->start, resource_size(res));
- *err = -ENOMEM;
- }
- return ptr;
-}
-
-static int gpio_nand_probe(struct platform_device *dev)
+static int gpio_nand_probe(struct platform_device *pdev)
{
struct gpiomtd *gpiomtd;
- struct nand_chip *this;
- struct resource *res0, *res1;
+ struct nand_chip *chip;
+ struct resource *res;
struct mtd_part_parser_data ppdata = {};
int ret = 0;
- if (!dev->dev.of_node && !dev->dev.platform_data)
- return -EINVAL;
-
- res0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!res0)
+ if (!pdev->dev.of_node && !dev_get_platdata(&pdev->dev))
return -EINVAL;
- gpiomtd = devm_kzalloc(&dev->dev, sizeof(*gpiomtd), GFP_KERNEL);
- if (gpiomtd == NULL) {
- dev_err(&dev->dev, "failed to create NAND MTD\n");
+ gpiomtd = devm_kzalloc(&pdev->dev, sizeof(*gpiomtd), GFP_KERNEL);
+ if (!gpiomtd) {
+ dev_err(&pdev->dev, "failed to create NAND MTD\n");
return -ENOMEM;
}
- this = &gpiomtd->nand_chip;
- this->IO_ADDR_R = request_and_remap(res0, 2, "NAND", &ret);
- if (!this->IO_ADDR_R) {
- dev_err(&dev->dev, "unable to map NAND\n");
- goto err_map;
- }
+ chip = &gpiomtd->nand_chip;
- res1 = gpio_nand_get_io_sync(dev);
- if (res1) {
- gpiomtd->io_sync = request_and_remap(res1, 4, "NAND sync", &ret);
- if (!gpiomtd->io_sync) {
- dev_err(&dev->dev, "unable to map sync NAND\n");
- goto err_sync;
- }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(chip->IO_ADDR_R))
+ return PTR_ERR(chip->IO_ADDR_R);
+
+ res = gpio_nand_get_io_sync(pdev);
+ if (res) {
+ gpiomtd->io_sync = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(gpiomtd->io_sync))
+ return PTR_ERR(gpiomtd->io_sync);
}
- ret = gpio_nand_get_config(&dev->dev, &gpiomtd->plat);
+ ret = gpio_nand_get_config(&pdev->dev, &gpiomtd->plat);
if (ret)
- goto err_nce;
+ return ret;
- ret = gpio_request(gpiomtd->plat.gpio_nce, "NAND NCE");
+ ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nce, "NAND NCE");
if (ret)
- goto err_nce;
+ return ret;
gpio_direction_output(gpiomtd->plat.gpio_nce, 1);
+
if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) {
- ret = gpio_request(gpiomtd->plat.gpio_nwp, "NAND NWP");
+ ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nwp,
+ "NAND NWP");
if (ret)
- goto err_nwp;
- gpio_direction_output(gpiomtd->plat.gpio_nwp, 1);
+ return ret;
}
- ret = gpio_request(gpiomtd->plat.gpio_ale, "NAND ALE");
+
+ ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_ale, "NAND ALE");
if (ret)
- goto err_ale;
+ return ret;
gpio_direction_output(gpiomtd->plat.gpio_ale, 0);
- ret = gpio_request(gpiomtd->plat.gpio_cle, "NAND CLE");
+
+ ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_cle, "NAND CLE");
if (ret)
- goto err_cle;
+ return ret;
gpio_direction_output(gpiomtd->plat.gpio_cle, 0);
+
if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) {
- ret = gpio_request(gpiomtd->plat.gpio_rdy, "NAND RDY");
+ ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_rdy,
+ "NAND RDY");
if (ret)
- goto err_rdy;
+ return ret;
gpio_direction_input(gpiomtd->plat.gpio_rdy);
+ chip->dev_ready = gpio_nand_devready;
}
+ chip->IO_ADDR_W = chip->IO_ADDR_R;
+ chip->ecc.mode = NAND_ECC_SOFT;
+ chip->options = gpiomtd->plat.options;
+ chip->chip_delay = gpiomtd->plat.chip_delay;
+ chip->cmd_ctrl = gpio_nand_cmd_ctrl;
- this->IO_ADDR_W = this->IO_ADDR_R;
- this->ecc.mode = NAND_ECC_SOFT;
- this->options = gpiomtd->plat.options;
- this->chip_delay = gpiomtd->plat.chip_delay;
-
- /* install our routines */
- this->cmd_ctrl = gpio_nand_cmd_ctrl;
- this->dev_ready = gpio_nand_devready;
+ gpiomtd->mtd_info.priv = chip;
+ gpiomtd->mtd_info.owner = THIS_MODULE;
- if (this->options & NAND_BUSWIDTH_16) {
- this->read_buf = gpio_nand_readbuf16;
- this->write_buf = gpio_nand_writebuf16;
- } else {
- this->read_buf = gpio_nand_readbuf;
- this->write_buf = gpio_nand_writebuf;
- }
+ platform_set_drvdata(pdev, gpiomtd);
- /* set the mtd private data for the nand driver */
- gpiomtd->mtd_info.priv = this;
- gpiomtd->mtd_info.owner = THIS_MODULE;
+ if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
+ gpio_direction_output(gpiomtd->plat.gpio_nwp, 1);
if (nand_scan(&gpiomtd->mtd_info, 1)) {
- dev_err(&dev->dev, "no nand chips found?\n");
ret = -ENXIO;
goto err_wp;
}
@@ -377,38 +288,17 @@ static int gpio_nand_probe(struct platform_device *dev)
gpiomtd->plat.adjust_parts(&gpiomtd->plat,
gpiomtd->mtd_info.size);
- ppdata.of_node = dev->dev.of_node;
+ ppdata.of_node = pdev->dev.of_node;
ret = mtd_device_parse_register(&gpiomtd->mtd_info, NULL, &ppdata,
gpiomtd->plat.parts,
gpiomtd->plat.num_parts);
- if (ret)
- goto err_wp;
- platform_set_drvdata(dev, gpiomtd);
-
- return 0;
+ if (!ret)
+ return 0;
err_wp:
if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
- if (gpio_is_valid(gpiomtd->plat.gpio_rdy))
- gpio_free(gpiomtd->plat.gpio_rdy);
-err_rdy:
- gpio_free(gpiomtd->plat.gpio_cle);
-err_cle:
- gpio_free(gpiomtd->plat.gpio_ale);
-err_ale:
- if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
- gpio_free(gpiomtd->plat.gpio_nwp);
-err_nwp:
- gpio_free(gpiomtd->plat.gpio_nce);
-err_nce:
- iounmap(gpiomtd->io_sync);
- if (res1)
- release_mem_region(res1->start, resource_size(res1));
-err_sync:
- iounmap(gpiomtd->nand_chip.IO_ADDR_R);
- release_mem_region(res0->start, resource_size(res0));
-err_map:
+
return ret;
}
@@ -417,6 +307,7 @@ static struct platform_driver gpio_nand_driver = {
.remove = gpio_nand_remove,
.driver = {
.name = "gpio-nand",
+ .owner = THIS_MODULE,
.of_match_table = of_match_ptr(gpio_nand_id_table),
},
};
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index b76460eeaf2..976d5662c3b 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -411,7 +411,7 @@ static int jz_nand_probe(struct platform_device *pdev)
struct jz_nand *nand;
struct nand_chip *chip;
struct mtd_info *mtd;
- struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+ struct jz_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
size_t chipnr, bank_idx;
uint8_t nand_maf_id = 0, nand_dev_id = 0;
@@ -549,7 +549,7 @@ err_free:
static int jz_nand_remove(struct platform_device *pdev)
{
struct jz_nand *nand = platform_get_drvdata(pdev);
- struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+ struct jz_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
size_t i;
nand_release(&nand->mtd);
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
index fd1df5e13ae..a379c39dab0 100644
--- a/drivers/mtd/nand/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_mlc.c
@@ -696,7 +696,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
}
lpc32xx_wp_disable(host);
- host->pdata = pdev->dev.platform_data;
+ host->pdata = dev_get_platdata(&pdev->dev);
nand_chip->priv = host; /* link the private data structures */
mtd->priv = nand_chip;
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
index be94ed5abef..81cd0719f03 100644
--- a/drivers/mtd/nand/lpc32xx_slc.c
+++ b/drivers/mtd/nand/lpc32xx_slc.c
@@ -798,7 +798,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
}
lpc32xx_wp_disable(host);
- host->pdata = pdev->dev.platform_data;
+ host->pdata = dev_get_platdata(&pdev->dev);
mtd = &host->mtd;
chip = &host->nand_chip;
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 07e5784e5cd..302c676c7ec 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -1432,7 +1432,8 @@ static int mxcnd_probe(struct platform_device *pdev)
err = mxcnd_probe_dt(host);
if (err > 0) {
- struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
+ struct mxc_nand_platform_data *pdata =
+ dev_get_platdata(&pdev->dev);
if (pdata) {
host->pdata = *pdata;
host->devtype_data = (struct mxc_nand_devtype_data *)
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 267264320e0..b5208d1c790 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -86,33 +86,17 @@ static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
* @td: search pattern descriptor
*
* Check for a pattern at the given place. Used to search bad block tables and
- * good / bad block identifiers. If the SCAN_EMPTY option is set then check, if
- * all bytes except the pattern area contain 0xff.
+ * good / bad block identifiers.
*/
static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
{
- int end = 0;
- uint8_t *p = buf;
-
if (td->options & NAND_BBT_NO_OOB)
return check_pattern_no_oob(buf, td);
- end = paglen + td->offs;
- if (td->options & NAND_BBT_SCANEMPTY)
- if (memchr_inv(p, 0xff, end))
- return -1;
- p += end;
-
/* Compare the pattern */
- if (memcmp(p, td->pattern, td->len))
+ if (memcmp(buf + paglen + td->offs, td->pattern, td->len))
return -1;
- if (td->options & NAND_BBT_SCANEMPTY) {
- p += td->len;
- end += td->len;
- if (memchr_inv(p, 0xff, len - end))
- return -1;
- }
return 0;
}
@@ -478,15 +462,9 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
else
numpages = 1;
- if (!(bd->options & NAND_BBT_SCANEMPTY)) {
- /* We need only read few bytes from the OOB area */
- scanlen = 0;
- readlen = bd->len;
- } else {
- /* Full page content should be read */
- scanlen = mtd->writesize + mtd->oobsize;
- readlen = numpages * mtd->writesize;
- }
+ /* We need only read few bytes from the OOB area */
+ scanlen = 0;
+ readlen = bd->len;
if (chip == -1) {
/*
@@ -865,7 +843,6 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
{
struct nand_chip *this = mtd->priv;
- bd->options &= ~NAND_BBT_SCANEMPTY;
return create_bbt(mtd, this->buffers->databuf, bd, -1);
}
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 81b80af5587..64d8e32b6ca 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -25,10 +25,8 @@
#include <linux/of.h>
#include <linux/of_device.h>
-#ifdef CONFIG_MTD_NAND_OMAP_BCH
-#include <linux/bch.h>
+#include <linux/mtd/nand_bch.h>
#include <linux/platform_data/elm.h>
-#endif
#include <linux/platform_data/mtd-nand-omap2.h>
@@ -141,6 +139,8 @@
#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,17 +149,6 @@ 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_SCANEMPTY | NAND_BBT_SCANALLPAGES,
- .offs = 0,
- .len = 1,
- .pattern = scan_ff_pattern,
-};
-
struct omap_nand_info {
struct nand_hw_control controller;
@@ -182,14 +171,10 @@ struct omap_nand_info {
u_char *buf;
int buf_len;
struct gpmc_nand_regs reg;
-
-#ifdef CONFIG_MTD_NAND_OMAP_BCH
- struct bch_control *bch;
- struct nand_ecclayout ecclayout;
+ /* fields specific for BCHx_HW ECC scheme */
bool is_elm_used;
struct device *elm_dev;
struct device_node *of_node;
-#endif
};
/**
@@ -948,7 +933,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u32 val;
val = readl(info->reg.gpmc_ecc_config);
- if (((val >> ECC_CONFIG_CS_SHIFT) & ~CS_MASK) != info->gpmc_cs)
+ if (((val >> ECC_CONFIG_CS_SHIFT) & CS_MASK) != info->gpmc_cs)
return -EINVAL;
/* read ecc result */
@@ -1058,8 +1043,7 @@ static int omap_dev_ready(struct mtd_info *mtd)
}
}
-#ifdef CONFIG_MTD_NAND_OMAP_BCH
-
+#if defined(CONFIG_MTD_NAND_ECC_BCH) || defined(CONFIG_MTD_NAND_OMAP_BCH)
/**
* omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction
* @mtd: MTD device structure
@@ -1140,7 +1124,9 @@ 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
@@ -1225,7 +1211,9 @@ 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
@@ -1463,7 +1451,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
/* Check if any error reported */
if (!is_error_reported)
- return 0;
+ return stat;
/* Decode BCH error using ELM module */
elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec);
@@ -1519,38 +1507,6 @@ 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
@@ -1637,207 +1593,58 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
}
/**
- * omap3_free_bch - Release BCH ecc resources
- * @mtd: MTD device structure
- */
-static void omap3_free_bch(struct mtd_info *mtd)
-{
- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
- mtd);
- if (info->bch) {
- free_bch(info->bch);
- info->bch = NULL;
- }
-}
-
-/**
- * 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)
+ * 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
*/
-static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
+static int is_elm_present(struct omap_nand_info *info,
+ struct device_node *elm_node, enum bch_ecc bch_type)
{
- 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;
- }
-
- 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;
+ 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;
}
-
- /* 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;
+ 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;
}
-
- /* 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;
+ /* 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;
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_OMAP_BCH */
+#endif /* CONFIG_MTD_NAND_ECC_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, offset;
- dma_cap_mask_t mask;
- unsigned sig;
+ int i;
+ dma_cap_mask_t mask;
+ unsigned sig;
+ unsigned oob_index;
struct resource *res;
struct mtd_part_parser_data ppdata = {};
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
if (pdata == NULL) {
dev_err(&pdev->dev, "platform data missing\n");
return -ENODEV;
}
- info = kzalloc(sizeof(struct omap_nand_info), GFP_KERNEL);
+ info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info),
+ GFP_KERNEL);
if (!info)
return -ENOMEM;
@@ -1846,47 +1653,45 @@ 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;
-#endif
+ 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;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
err = -EINVAL;
dev_err(&pdev->dev, "error getting memory resource\n");
- goto out_free_info;
+ goto return_error;
}
info->phys_base = res->start;
info->mem_size = resource_size(res);
- if (!request_mem_region(info->phys_base, info->mem_size,
- pdev->dev.driver->name)) {
+ if (!devm_request_mem_region(&pdev->dev, info->phys_base,
+ info->mem_size, pdev->dev.driver->name)) {
err = -EBUSY;
- goto out_free_info;
+ goto return_error;
}
- info->nand.IO_ADDR_R = ioremap(info->phys_base, info->mem_size);
- if (!info->nand.IO_ADDR_R) {
+ nand_chip->IO_ADDR_R = devm_ioremap(&pdev->dev, info->phys_base,
+ info->mem_size);
+ if (!nand_chip->IO_ADDR_R) {
err = -ENOMEM;
- goto out_release_mem_region;
+ goto return_error;
}
- info->nand.controller = &info->controller;
+ nand_chip->controller = &info->controller;
- info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
- info->nand.cmd_ctrl = omap_hwcontrol;
+ nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R;
+ nand_chip->cmd_ctrl = omap_hwcontrol;
/*
* If RDY/BSY line is connected to OMAP then use the omap ready
@@ -1896,27 +1701,37 @@ 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) {
- info->nand.dev_ready = omap_dev_ready;
- info->nand.chip_delay = 0;
+ nand_chip->dev_ready = omap_dev_ready;
+ nand_chip->chip_delay = 0;
} else {
- info->nand.waitfunc = omap_wait;
- info->nand.chip_delay = 50;
+ nand_chip->waitfunc = omap_wait;
+ nand_chip->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:
- info->nand.read_buf = omap_read_buf_pref;
- info->nand.write_buf = omap_write_buf_pref;
+ nand_chip->read_buf = omap_read_buf_pref;
+ nand_chip->write_buf = omap_write_buf_pref;
break;
case NAND_OMAP_POLLED:
- if (info->nand.options & NAND_BUSWIDTH_16) {
- info->nand.read_buf = omap_read_buf16;
- info->nand.write_buf = omap_write_buf16;
- } else {
- info->nand.read_buf = omap_read_buf8;
- info->nand.write_buf = omap_write_buf8;
- }
+ /* Use nand_base defaults for {read,write}_buf */
break;
case NAND_OMAP_PREFETCH_DMA:
@@ -1927,7 +1742,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 out_release_mem_region;
+ goto return_error;
} else {
struct dma_slave_config cfg;
@@ -1942,10 +1757,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 out_release_mem_region;
+ goto return_error;
}
- info->nand.read_buf = omap_read_buf_dma_pref;
- info->nand.write_buf = omap_write_buf_dma_pref;
+ nand_chip->read_buf = omap_read_buf_dma_pref;
+ nand_chip->write_buf = omap_write_buf_dma_pref;
}
break;
@@ -1954,34 +1769,36 @@ 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 out_release_mem_region;
+ goto return_error;
}
- err = request_irq(info->gpmc_irq_fifo, omap_nand_irq,
- IRQF_SHARED, "gpmc-nand-fifo", info);
+ err = devm_request_irq(&pdev->dev, 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 out_release_mem_region;
+ goto return_error;
}
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 out_release_mem_region;
+ goto return_error;
}
- err = request_irq(info->gpmc_irq_count, omap_nand_irq,
- IRQF_SHARED, "gpmc-nand-count", info);
+ err = devm_request_irq(&pdev->dev, 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 out_release_mem_region;
+ goto return_error;
}
- info->nand.read_buf = omap_read_buf_irq_pref;
- info->nand.write_buf = omap_write_buf_irq_pref;
+ nand_chip->read_buf = omap_read_buf_irq_pref;
+ nand_chip->write_buf = omap_write_buf_irq_pref;
break;
@@ -1989,118 +1806,241 @@ 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 out_release_mem_region;
+ goto return_error;
}
- /* 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) {
+ /* 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)
+ oob_index = BADBLOCK_MARKER_LENGTH;
+ else
+ oob_index = 1;
+ for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+ ecclayout->eccpos[i] = oob_index;
+ /* no reserved-marker in ecclayout for this ecc-scheme */
+ ecclayout->oobfree->offset =
+ ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
+ 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);
+ oob_index = BADBLOCK_MARKER_LENGTH;
+ for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) {
+ ecclayout->eccpos[i] = oob_index;
+ if (((i + 1) % nand_chip->ecc.bytes) == 0)
+ oob_index++;
+ }
+ /* include reserved-marker in ecclayout->oobfree calculation */
+ ecclayout->oobfree->offset = 1 +
+ ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
+ /* 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 out_release_mem_region;
}
- }
+ break;
+#else
+ pr_err("nand: error: CONFIG_MTD_NAND_ECC_BCH not enabled\n");
+ err = -EINVAL;
+ goto return_error;
+#endif
- /* 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;
+ 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);
+ oob_index = BADBLOCK_MARKER_LENGTH;
+ for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+ ecclayout->eccpos[i] = oob_index;
+ /* reserved marker already included in ecclayout->eccbytes */
+ ecclayout->oobfree->offset =
+ ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
+ /* 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;
}
- }
+ break;
+#else
+ pr_err("nand: error: CONFIG_MTD_NAND_OMAP_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_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);
+ oob_index = BADBLOCK_MARKER_LENGTH;
+ for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) {
+ ecclayout->eccpos[i] = oob_index;
+ if (((i + 1) % nand_chip->ecc.bytes) == 0)
+ oob_index++;
+ }
+ /* include reserved-marker in ecclayout->oobfree calculation */
+ ecclayout->oobfree->offset = 1 +
+ ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
+ /* 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
- if (info->nand.options & NAND_BUSWIDTH_16)
- offset = 2;
- else {
- offset = 1;
- info->nand.badblock_pattern = &bb_descrip_flashbased;
+ 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;
}
- omap_oobinfo.eccbytes = 3 * (info->mtd.oobsize/16);
- for (i = 0; i < omap_oobinfo.eccbytes; i++)
- omap_oobinfo.eccpos[i] = i+offset;
+ /* define ECC layout */
+ ecclayout->eccbytes = nand_chip->ecc.bytes *
+ (mtd->writesize /
+ nand_chip->ecc.size);
+ oob_index = BADBLOCK_MARKER_LENGTH;
+ for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+ ecclayout->eccpos[i] = oob_index;
+ /* reserved marker already included in ecclayout->eccbytes */
+ ecclayout->oobfree->offset =
+ ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
+ break;
+#else
+ pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
+ err = -EINVAL;
+ goto return_error;
+#endif
- omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes;
- omap_oobinfo.oobfree->length = info->mtd.oobsize -
- (offset + omap_oobinfo.eccbytes);
+ default:
+ pr_err("nand: error: invalid or unsupported ECC scheme\n");
+ err = -EINVAL;
+ goto return_error;
+ }
- 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;
- }
+ /* all OOB bytes from oobfree->offset till end off OOB are free */
+ ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
+ /* 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(&info->mtd)) {
+ if (nand_scan_tail(mtd)) {
err = -ENXIO;
- goto out_release_mem_region;
+ goto return_error;
}
ppdata.of_node = pdata->of_node;
- mtd_device_parse_register(&info->mtd, NULL, &ppdata, pdata->parts,
+ mtd_device_parse_register(mtd, NULL, &ppdata, pdata->parts,
pdata->nr_parts);
- platform_set_drvdata(pdev, &info->mtd);
+ platform_set_drvdata(pdev, mtd);
return 0;
-out_release_mem_region:
+return_error:
if (info->dma)
dma_release_channel(info->dma);
- 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);
-
+ if (nand_chip->ecc.priv) {
+ nand_bch_free(nand_chip->ecc.priv);
+ nand_chip->ecc.priv = NULL;
+ }
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);
- omap3_free_bch(&info->mtd);
-
- platform_set_drvdata(pdev, NULL);
+ if (nand_chip->ecc.priv) {
+ nand_bch_free(nand_chip->ecc.priv);
+ nand_chip->ecc.priv = NULL;
+ }
if (info->dma)
dma_release_channel(info->dma);
-
- 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);
+ nand_release(mtd);
return 0;
}
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index 8fbd0020861..834cb3541b8 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -130,8 +130,9 @@ static int __init orion_nand_probe(struct platform_device *pdev)
if (!of_property_read_u32(pdev->dev.of_node,
"chip-delay", &val))
board->chip_delay = (u8)val;
- } else
- board = pdev->dev.platform_data;
+ } else {
+ board = dev_get_platdata(&pdev->dev);
+ }
mtd->priv = nc;
mtd->owner = THIS_MODULE;
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index c004566a9ad..08766d1ea44 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -30,7 +30,7 @@ static const char *part_probe_types[] = { "cmdlinepart", NULL };
*/
static int plat_nand_probe(struct platform_device *pdev)
{
- struct platform_nand_data *pdata = pdev->dev.platform_data;
+ struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
struct mtd_part_parser_data ppdata;
struct plat_nand_data *data;
struct resource *res;
@@ -137,7 +137,7 @@ out_free:
static int plat_nand_remove(struct platform_device *pdev)
{
struct plat_nand_data *data = platform_get_drvdata(pdev);
- struct platform_nand_data *pdata = pdev->dev.platform_data;
+ struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index dec80ca6a5c..501e380211e 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -506,6 +506,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
info->buf_count = 0;
info->oob_size = 0;
info->use_ecc = 0;
+ info->use_dma = (use_dma) ? 1 : 0;
info->is_ready = 0;
info->retcode = ERR_NONE;
if (info->cs != 0)
@@ -589,12 +590,23 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
| addr_cycle;
break;
+ case NAND_CMD_PARAM:
+ cmd = NAND_CMD_PARAM;
+ info->buf_count = 256;
+ info->ndcb0 |= NDCB0_CMD_TYPE(0)
+ | NDCB0_ADDR_CYC(1)
+ | cmd;
+ info->ndcb1 = (column & 0xFF);
+ info->data_size = 256;
+ break;
+
case NAND_CMD_READID:
cmd = host->cmdset->read_id;
info->buf_count = host->read_id_bytes;
info->ndcb0 |= NDCB0_CMD_TYPE(3)
| NDCB0_ADDR_CYC(1)
| cmd;
+ info->ndcb1 = (column & 0xFF);
info->data_size = 8;
break;
@@ -803,7 +815,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
const struct pxa3xx_nand_flash *f)
{
struct platform_device *pdev = info->pdev;
- struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+ struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct pxa3xx_nand_host *host = info->host[info->cs];
uint32_t ndcr = 0x0; /* enable all interrupts */
@@ -912,6 +924,18 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
return 0;
}
+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, MAX_BUFF_SIZE,
+ info->data_buff, info->data_buff_phys);
+ } else {
+ kfree(info->data_buff);
+ }
+}
+
static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
{
struct mtd_info *mtd;
@@ -934,7 +958,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
struct pxa3xx_nand_host *host = mtd->priv;
struct pxa3xx_nand_info *info = host->info_data;
struct platform_device *pdev = info->pdev;
- struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+ struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
const struct pxa3xx_nand_flash *f = NULL;
struct nand_chip *chip = mtd->priv;
@@ -1034,13 +1058,11 @@ static int alloc_nand_resource(struct platform_device *pdev)
struct resource *r;
int ret, irq, cs;
- pdata = pdev->dev.platform_data;
- info = kzalloc(sizeof(*info) + (sizeof(*mtd) +
- sizeof(*host)) * pdata->num_cs, GFP_KERNEL);
- if (!info) {
- dev_err(&pdev->dev, "failed to allocate memory\n");
+ pdata = dev_get_platdata(&pdev->dev);
+ info = devm_kzalloc(&pdev->dev, sizeof(*info) + (sizeof(*mtd) +
+ sizeof(*host)) * pdata->num_cs, GFP_KERNEL);
+ if (!info)
return -ENOMEM;
- }
info->pdev = pdev;
for (cs = 0; cs < pdata->num_cs; cs++) {
@@ -1069,20 +1091,21 @@ static int alloc_nand_resource(struct platform_device *pdev)
spin_lock_init(&chip->controller->lock);
init_waitqueue_head(&chip->controller->wq);
- info->clk = clk_get(&pdev->dev, NULL);
+ info->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(info->clk)) {
dev_err(&pdev->dev, "failed to get nand clock\n");
- ret = PTR_ERR(info->clk);
- goto fail_free_mtd;
+ return PTR_ERR(info->clk);
}
- clk_enable(info->clk);
+ ret = clk_prepare_enable(info->clk);
+ if (ret < 0)
+ return ret;
/*
* This is a dirty hack to make this driver work from devicetree
* bindings. It can be removed once we have a prober DMA controller
* framework for DT.
*/
- if (pdev->dev.of_node && cpu_is_pxa3xx()) {
+ if (pdev->dev.of_node && of_machine_is_compatible("marvell,pxa3xx")) {
info->drcmr_dat = 97;
info->drcmr_cmd = 99;
} else {
@@ -1090,7 +1113,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
if (r == NULL) {
dev_err(&pdev->dev, "no resource defined for data DMA\n");
ret = -ENXIO;
- goto fail_put_clk;
+ goto fail_disable_clk;
}
info->drcmr_dat = r->start;
@@ -1098,7 +1121,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
if (r == NULL) {
dev_err(&pdev->dev, "no resource defined for command DMA\n");
ret = -ENXIO;
- goto fail_put_clk;
+ goto fail_disable_clk;
}
info->drcmr_cmd = r->start;
}
@@ -1107,34 +1130,20 @@ static int alloc_nand_resource(struct platform_device *pdev)
if (irq < 0) {
dev_err(&pdev->dev, "no IRQ resource defined\n");
ret = -ENXIO;
- goto fail_put_clk;
+ goto fail_disable_clk;
}
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- dev_err(&pdev->dev, "no IO memory resource defined\n");
- ret = -ENODEV;
- goto fail_put_clk;
- }
-
- r = request_mem_region(r->start, resource_size(r), pdev->name);
- if (r == NULL) {
- dev_err(&pdev->dev, "failed to request memory resource\n");
- ret = -EBUSY;
- goto fail_put_clk;
- }
-
- info->mmio_base = ioremap(r->start, resource_size(r));
- if (info->mmio_base == NULL) {
- dev_err(&pdev->dev, "ioremap() failed\n");
- ret = -ENODEV;
- goto fail_free_res;
+ info->mmio_base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(info->mmio_base)) {
+ ret = PTR_ERR(info->mmio_base);
+ goto fail_disable_clk;
}
info->mmio_phys = r->start;
ret = pxa3xx_nand_init_buff(info);
if (ret)
- goto fail_free_io;
+ goto fail_disable_clk;
/* initialize all interrupts to be disabled */
disable_int(info, NDSR_MASK);
@@ -1152,21 +1161,9 @@ static int alloc_nand_resource(struct platform_device *pdev)
fail_free_buf:
free_irq(irq, info);
- if (use_dma) {
- pxa_free_dma(info->data_dma_ch);
- dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
- info->data_buff, info->data_buff_phys);
- } else
- kfree(info->data_buff);
-fail_free_io:
- iounmap(info->mmio_base);
-fail_free_res:
- release_mem_region(r->start, resource_size(r));
-fail_put_clk:
- clk_disable(info->clk);
- clk_put(info->clk);
-fail_free_mtd:
- kfree(info);
+ pxa3xx_nand_free_buff(info);
+fail_disable_clk:
+ clk_disable_unprepare(info->clk);
return ret;
}
@@ -1174,35 +1171,22 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
{
struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
struct pxa3xx_nand_platform_data *pdata;
- struct resource *r;
int irq, cs;
if (!info)
return 0;
- pdata = pdev->dev.platform_data;
- platform_set_drvdata(pdev, NULL);
+ pdata = dev_get_platdata(&pdev->dev);
irq = platform_get_irq(pdev, 0);
if (irq >= 0)
free_irq(irq, info);
- if (use_dma) {
- pxa_free_dma(info->data_dma_ch);
- dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
- info->data_buff, info->data_buff_phys);
- } else
- kfree(info->data_buff);
-
- iounmap(info->mmio_base);
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(r->start, resource_size(r));
+ pxa3xx_nand_free_buff(info);
- clk_disable(info->clk);
- clk_put(info->clk);
+ clk_disable_unprepare(info->clk);
for (cs = 0; cs < pdata->num_cs; cs++)
nand_release(info->host[cs]->mtd);
- kfree(info);
return 0;
}
@@ -1211,7 +1195,7 @@ static struct of_device_id pxa3xx_nand_dt_ids[] = {
{ .compatible = "marvell,pxa3xx-nand" },
{}
};
-MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
+MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
{
@@ -1255,7 +1239,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
if (ret)
return ret;
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data defined\n");
return -ENODEV;
@@ -1302,7 +1286,7 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
struct mtd_info *mtd;
int cs;
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
if (info->state) {
dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
return -EAGAIN;
@@ -1323,7 +1307,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
struct mtd_info *mtd;
int cs;
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
/* We don't want to handle interrupt without calling mtd routine */
disable_int(info, NDCR_INT_MASK);
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index d65afd23e17..b707d0f8247 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -150,7 +150,7 @@ static struct s3c2410_nand_info *to_nand_info(struct platform_device *dev)
static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
{
- return dev->dev.platform_data;
+ return dev_get_platdata(&dev->dev);
}
static inline int allow_clk_suspend(struct s3c2410_nand_info *info)
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index e57e18e8c28..a3c84ebbe39 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -137,7 +137,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
dma_cap_mask_t mask;
struct dma_slave_config cfg;
struct platform_device *pdev = flctl->pdev;
- struct sh_flctl_platform_data *pdata = pdev->dev.platform_data;
+ struct sh_flctl_platform_data *pdata = dev_get_platdata(&pdev->dev);
int ret;
if (!pdata)
@@ -1131,7 +1131,7 @@ static int flctl_probe(struct platform_device *pdev)
if (pdev->dev.of_node)
pdata = flctl_parse_dt(&pdev->dev);
else
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "no setup data defined\n");
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 127bc427182..26b27201520 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -112,7 +112,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
struct resource *r;
int err = 0;
struct sharpsl_nand *sharpsl;
- struct sharpsl_nand_platform_data *data = pdev->dev.platform_data;
+ struct sharpsl_nand_platform_data *data = dev_get_platdata(&pdev->dev);
if (!data) {
dev_err(&pdev->dev, "no platform data!\n");
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index 508e9e04b09..396530d87ec 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -357,7 +357,7 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)
static int tmio_probe(struct platform_device *dev)
{
- struct tmio_nand_data *data = dev->dev.platform_data;
+ struct tmio_nand_data *data = dev_get_platdata(&dev->dev);
struct resource *fcr = platform_get_resource(dev,
IORESOURCE_MEM, 0);
struct resource *ccr = platform_get_resource(dev,
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index 7ed654c68b0..388b13a6d7e 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -87,7 +87,7 @@ static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
static void __iomem *ndregaddr(struct platform_device *dev, unsigned int reg)
{
struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev);
- struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
+ struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
return drvdata->base + (reg << plat->shift);
}
@@ -138,7 +138,7 @@ static void txx9ndfmc_cmd_ctrl(struct mtd_info *mtd, int cmd,
struct nand_chip *chip = mtd->priv;
struct txx9ndfmc_priv *txx9_priv = chip->priv;
struct platform_device *dev = txx9_priv->dev;
- struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
+ struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
if (ctrl & NAND_CTRL_CHANGE) {
u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR);
@@ -225,7 +225,7 @@ static void txx9ndfmc_enable_hwecc(struct mtd_info *mtd, int mode)
static void txx9ndfmc_initialize(struct platform_device *dev)
{
- struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
+ struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev);
int tmout = 100;
@@ -274,7 +274,7 @@ static int txx9ndfmc_nand_scan(struct mtd_info *mtd)
static int __init txx9ndfmc_probe(struct platform_device *dev)
{
- struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
+ struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
int hold, spw;
int i;
struct txx9ndfmc_drvdata *drvdata;