]> Pileus Git - ~andy/linux/blobdiff - drivers/mtd/nand/davinci_nand.c
Merge branch 'for-3.14-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj...
[~andy/linux] / drivers / mtd / nand / davinci_nand.c
index b77a01efb4837ea325988ee6e58e82bd128d7892..a4989ec6292efa0127ba4cc84d13fd07ad09fe4b 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/of_device.h>
 #include <linux/of.h>
+#include <linux/of_mtd.h>
 
 #include <linux/platform_data/mtd-davinci.h>
 #include <linux/platform_data/mtd-davinci-aemif.h>
@@ -487,7 +488,7 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
  * ten ECC bytes plus the manufacturer's bad block marker byte, and
  * and not overlapping the default BBT markers.
  */
-static struct nand_ecclayout hwecc4_small __initconst = {
+static struct nand_ecclayout hwecc4_small = {
        .eccbytes = 10,
        .eccpos = { 0, 1, 2, 3, 4,
                /* offset 5 holds the badblock marker */
@@ -503,7 +504,7 @@ static struct nand_ecclayout hwecc4_small __initconst = {
  * storing ten ECC bytes plus the manufacturer's bad block marker byte,
  * and not overlapping the default BBT markers.
  */
-static struct nand_ecclayout hwecc4_2048 __initconst = {
+static struct nand_ecclayout hwecc4_2048 = {
        .eccbytes = 40,
        .eccpos = {
                /* at the end of spare sector */
@@ -534,17 +535,19 @@ static struct davinci_nand_pdata
                struct davinci_nand_pdata *pdata;
                const char *mode;
                u32 prop;
-               int len;
 
                pdata =  devm_kzalloc(&pdev->dev,
                                sizeof(struct davinci_nand_pdata),
                                GFP_KERNEL);
                pdev->dev.platform_data = pdata;
                if (!pdata)
-                       return NULL;
+                       return ERR_PTR(-ENOMEM);
                if (!of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-chipselect", &prop))
                        pdev->id = prop;
+               else
+                       return ERR_PTR(-EINVAL);
+
                if (!of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-mask-ale", &prop))
                        pdata->mask_ale = prop;
@@ -555,6 +558,8 @@ static struct davinci_nand_pdata
                        "ti,davinci-mask-chipsel", &prop))
                        pdata->mask_chipsel = prop;
                if (!of_property_read_string(pdev->dev.of_node,
+                       "nand-ecc-mode", &mode) ||
+                   !of_property_read_string(pdev->dev.of_node,
                        "ti,davinci-ecc-mode", &mode)) {
                        if (!strncmp("none", mode, 4))
                                pdata->ecc_mode = NAND_ECC_NONE;
@@ -566,12 +571,16 @@ static struct davinci_nand_pdata
                if (!of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-ecc-bits", &prop))
                        pdata->ecc_bits = prop;
-               if (!of_property_read_u32(pdev->dev.of_node,
+
+               prop = of_get_nand_bus_width(pdev->dev.of_node);
+               if (0 < prop || !of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-nand-buswidth", &prop))
                        if (prop == 16)
                                pdata->options |= NAND_BUSWIDTH_16;
-               if (of_find_property(pdev->dev.of_node,
-                       "ti,davinci-nand-use-bbt", &len))
+               if (of_property_read_bool(pdev->dev.of_node,
+                       "nand-on-flash-bbt") ||
+                   of_property_read_bool(pdev->dev.of_node,
+                       "ti,davinci-nand-use-bbt"))
                        pdata->bbt_options = NAND_BBT_USE_FLASH;
        }
 
@@ -585,7 +594,7 @@ static struct davinci_nand_pdata
 }
 #endif
 
-static int __init nand_davinci_probe(struct platform_device *pdev)
+static int nand_davinci_probe(struct platform_device *pdev)
 {
        struct davinci_nand_pdata       *pdata;
        struct davinci_nand_info        *info;
@@ -598,6 +607,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        nand_ecc_modes_t                ecc_mode;
 
        pdata = nand_davinci_get_pdata(pdev);
+       if (IS_ERR(pdata))
+               return PTR_ERR(pdata);
+
        /* insist on board-specific configuration */
        if (!pdata)
                return -ENODEV;
@@ -607,11 +619,8 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                return -ENODEV;
 
        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
-       if (!info) {
-               dev_err(&pdev->dev, "unable to allocate memory\n");
-               ret = -ENOMEM;
-               goto err_nomem;
-       }
+       if (!info)
+               return -ENOMEM;
 
        platform_set_drvdata(pdev, info);
 
@@ -619,19 +628,23 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        if (!res1 || !res2) {
                dev_err(&pdev->dev, "resource missing\n");
-               ret = -EINVAL;
-               goto err_nomem;
+               return -EINVAL;
        }
 
        vaddr = devm_ioremap_resource(&pdev->dev, res1);
-       if (IS_ERR(vaddr)) {
-               ret = PTR_ERR(vaddr);
-               goto err_ioremap;
-       }
-       base = devm_ioremap_resource(&pdev->dev, res2);
-       if (IS_ERR(base)) {
-               ret = PTR_ERR(base);
-               goto err_ioremap;
+       if (IS_ERR(vaddr))
+               return PTR_ERR(vaddr);
+
+       /*
+        * This registers range is used to setup NAND settings. In case with
+        * TI AEMIF driver, the same memory address range is requested already
+        * by AEMIF, so we cannot request it twice, just ioremap.
+        * The AEMIF and NAND drivers not use the same registers in this range.
+        */
+       base = devm_ioremap(&pdev->dev, res2->start, resource_size(res2));
+       if (!base) {
+               dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res2);
+               return -EADDRNOTAVAIL;
        }
 
        info->dev               = &pdev->dev;
@@ -699,7 +712,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                        spin_unlock_irq(&davinci_nand_lock);
 
                        if (ret == -EBUSY)
-                               goto err_ecc;
+                               return ret;
 
                        info->chip.ecc.calculate = nand_davinci_calculate_4bit;
                        info->chip.ecc.correct = nand_davinci_correct_4bit;
@@ -715,8 +728,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                info->chip.ecc.strength = pdata->ecc_bits;
                break;
        default:
-               ret = -EINVAL;
-               goto err_ecc;
+               return -EINVAL;
        }
        info->chip.ecc.mode = ecc_mode;
 
@@ -724,7 +736,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        if (IS_ERR(info->clk)) {
                ret = PTR_ERR(info->clk);
                dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret);
-               goto err_clk;
+               return ret;
        }
 
        ret = clk_prepare_enable(info->clk);
@@ -753,7 +765,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                                                        info->core_chipsel);
        if (ret < 0) {
                dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
-               goto err_timing;
+               goto err;
        }
 
        spin_lock_irq(&davinci_nand_lock);
@@ -769,7 +781,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        ret = nand_scan_ident(&info->mtd, pdata->mask_chipsel ? 2 : 1, NULL);
        if (ret < 0) {
                dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
-               goto err_scan;
+               goto err;
        }
 
        /* Update ECC layout if needed ... for 1-bit HW ECC, the default
@@ -783,7 +795,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                if (!chunks || info->mtd.oobsize < 16) {
                        dev_dbg(&pdev->dev, "too small\n");
                        ret = -EINVAL;
-                       goto err_scan;
+                       goto err;
                }
 
                /* For small page chips, preserve the manufacturer's
@@ -814,7 +826,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                dev_warn(&pdev->dev, "no 4-bit ECC support yet "
                                "for 4KiB-page NAND\n");
                ret = -EIO;
-               goto err_scan;
+               goto err;
 
 syndrome_done:
                info->chip.ecc.layout = &info->ecclayout;
@@ -822,7 +834,7 @@ syndrome_done:
 
        ret = nand_scan_tail(&info->mtd);
        if (ret < 0)
-               goto err_scan;
+               goto err;
 
        if (pdata->parts)
                ret = mtd_device_parse_register(&info->mtd, NULL, NULL,
@@ -835,7 +847,7 @@ syndrome_done:
                                                NULL, 0);
        }
        if (ret < 0)
-               goto err_scan;
+               goto err;
 
        val = davinci_nand_readl(info, NRCSR_OFFSET);
        dev_info(&pdev->dev, "controller rev. %d.%d\n",
@@ -843,8 +855,7 @@ syndrome_done:
 
        return 0;
 
-err_scan:
-err_timing:
+err:
        clk_disable_unprepare(info->clk);
 
 err_clk_enable:
@@ -852,15 +863,10 @@ err_clk_enable:
        if (ecc_mode == NAND_ECC_HW_SYNDROME)
                ecc4_busy = false;
        spin_unlock_irq(&davinci_nand_lock);
-
-err_ecc:
-err_clk:
-err_ioremap:
-err_nomem:
        return ret;
 }
 
-static int __exit nand_davinci_remove(struct platform_device *pdev)
+static int nand_davinci_remove(struct platform_device *pdev)
 {
        struct davinci_nand_info *info = platform_get_drvdata(pdev);
 
@@ -877,7 +883,8 @@ static int __exit nand_davinci_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver nand_davinci_driver = {
-       .remove         = __exit_p(nand_davinci_remove),
+       .probe          = nand_davinci_probe,
+       .remove         = nand_davinci_remove,
        .driver         = {
                .name   = "davinci_nand",
                .owner  = THIS_MODULE,
@@ -886,7 +893,7 @@ static struct platform_driver nand_davinci_driver = {
 };
 MODULE_ALIAS("platform:davinci_nand");
 
-module_platform_driver_probe(nand_davinci_driver, nand_davinci_probe);
+module_platform_driver(nand_davinci_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Texas Instruments");