mtd: nand: davinci: add OF support for davinci nand controller
authorHeiko Schocher <hs@denx.de>
Mon, 30 Jul 2012 07:22:24 +0000 (09:22 +0200)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Sat, 29 Sep 2012 13:59:04 +0000 (14:59 +0100)
add OF support for the davinci nand controller.

Signed-off-by: Heiko Schocher <hs@denx.de>
Acked-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Documentation/devicetree/bindings/arm/davinci/nand.txt [new file with mode: 0644]
drivers/mtd/nand/davinci_nand.c

diff --git a/Documentation/devicetree/bindings/arm/davinci/nand.txt b/Documentation/devicetree/bindings/arm/davinci/nand.txt
new file mode 100644 (file)
index 0000000..e37241f
--- /dev/null
@@ -0,0 +1,51 @@
+* Texas Instruments Davinci NAND
+
+This file provides information, what the device node for the
+davinci nand interface contain.
+
+Required properties:
+- compatible: "ti,davinci-nand";
+- reg : contain 2 offset/length values:
+        - offset and length for the access window
+        - offset and length for accessing the aemif control registers
+- ti,davinci-chipselect: Indicates on the davinci_nand driver which
+                         chipselect is used for accessing the nand.
+
+Recommended properties :
+- ti,davinci-mask-ale: mask for ale
+- ti,davinci-mask-cle: mask for cle
+- ti,davinci-mask-chipsel: mask for chipselect
+- ti,davinci-ecc-mode: ECC mode valid values for davinci driver:
+               - "none"
+               - "soft"
+               - "hw"
+- ti,davinci-ecc-bits: used ECC bits, currently supported 1 or 4.
+- ti,davinci-nand-buswidth: buswidth 8 or 16
+- ti,davinci-nand-use-bbt: use flash based bad block table support.
+
+Example (enbw_cmc board):
+aemif@60000000 {
+       compatible = "ti,davinci-aemif";
+       #address-cells = <2>;
+       #size-cells = <1>;
+       reg = <0x68000000 0x80000>;
+       ranges = <2 0 0x60000000 0x02000000
+                 3 0 0x62000000 0x02000000
+                 4 0 0x64000000 0x02000000
+                 5 0 0x66000000 0x02000000
+                 6 0 0x68000000 0x02000000>;
+       nand@3,0 {
+               compatible = "ti,davinci-nand";
+               reg = <3 0x0 0x807ff
+                       6 0x0 0x8000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ti,davinci-chipselect = <1>;
+               ti,davinci-mask-ale = <0>;
+               ti,davinci-mask-cle = <0>;
+               ti,davinci-mask-chipsel = <0>;
+               ti,davinci-ecc-mode = "hw";
+               ti,davinci-ecc-bits = <4>;
+               ti,davinci-nand-use-bbt;
+       };
+};
index d94b03c..f386b3c 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 
 #include <mach/nand.h>
 #include <mach/aemif.h>
@@ -518,9 +519,75 @@ static struct nand_ecclayout hwecc4_2048 __initconst = {
        },
 };
 
+#if defined(CONFIG_OF)
+static const struct of_device_id davinci_nand_of_match[] = {
+       {.compatible = "ti,davinci-nand", },
+       {},
+}
+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) {
+               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;
+               if (!of_property_read_u32(pdev->dev.of_node,
+                       "ti,davinci-chipselect", &prop))
+                       pdev->id = prop;
+               if (!of_property_read_u32(pdev->dev.of_node,
+                       "ti,davinci-mask-ale", &prop))
+                       pdata->mask_ale = prop;
+               if (!of_property_read_u32(pdev->dev.of_node,
+                       "ti,davinci-mask-cle", &prop))
+                       pdata->mask_cle = prop;
+               if (!of_property_read_u32(pdev->dev.of_node,
+                       "ti,davinci-mask-chipsel", &prop))
+                       pdata->mask_chipsel = prop;
+               if (!of_property_read_string(pdev->dev.of_node,
+                       "ti,davinci-ecc-mode", &mode)) {
+                       if (!strncmp("none", mode, 4))
+                               pdata->ecc_mode = NAND_ECC_NONE;
+                       if (!strncmp("soft", mode, 4))
+                               pdata->ecc_mode = NAND_ECC_SOFT;
+                       if (!strncmp("hw", mode, 2))
+                               pdata->ecc_mode = NAND_ECC_HW;
+               }
+               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,
+                       "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))
+                       pdata->bbt_options = NAND_BBT_USE_FLASH;
+       }
+
+       return pdev->dev.platform_data;
+}
+#else
+#define davinci_nand_of_match NULL
+static struct davinci_nand_pdata
+       *nand_davinci_get_pdata(struct platform_device *pdev)
+{
+       return pdev->dev.platform_data;
+}
+#endif
+
 static int __init nand_davinci_probe(struct platform_device *pdev)
 {
-       struct davinci_nand_pdata       *pdata = pdev->dev.platform_data;
+       struct davinci_nand_pdata       *pdata;
        struct davinci_nand_info        *info;
        struct resource                 *res1;
        struct resource                 *res2;
@@ -530,6 +597,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        uint32_t                        val;
        nand_ecc_modes_t                ecc_mode;
 
+       pdata = nand_davinci_get_pdata(pdev);
        /* insist on board-specific configuration */
        if (!pdata)
                return -ENODEV;
@@ -816,6 +884,8 @@ static struct platform_driver nand_davinci_driver = {
        .remove         = __exit_p(nand_davinci_remove),
        .driver         = {
                .name   = "davinci_nand",
+               .owner  = THIS_MODULE,
+               .of_match_table = davinci_nand_of_match,
        },
 };
 MODULE_ALIAS("platform:davinci_nand");