mtd: nand: denali_dt: add a DT driver
authorMasahiro Yamada <yamada.masahiro@socionext.com>
Fri, 25 Aug 2017 16:12:31 +0000 (01:12 +0900)
committerMasahiro Yamada <yamada.masahiro@socionext.com>
Wed, 30 Aug 2017 00:03:11 +0000 (09:03 +0900)
A patch for NAND uclass support was proposed about half a year ago:
https://patchwork.ozlabs.org/patch/722282/

It was not merged and I do not see on-going work for this.

Without DM-based probing, we need to set up pinctrl etc. in an ad-hoc
way and give lots of crappy CONFIG options for base addresses and
properties, which are supposed to be specified by DT.  This is painful.

This commit just provides a probe hook to retrieve "reg" from DT and
allocate private data in a DM manner.  This DT driver is not essentially
a NAND driver, in fact it is (ab)using UCLASS_MISC.  Once UCLASS_NAND is
supported, it would be possible to migrate to it.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/denali.c
drivers/mtd/nand/denali.h
drivers/mtd/nand/denali_dt.c [new file with mode: 0644]

index 71d678fc66b5895878c153b559cd8561ebb1eaa7..85b26d608851591cca14dd36e1229db845215918 100644 (file)
@@ -16,6 +16,13 @@ config NAND_DENALI
        help
          Enable support for the Denali NAND controller.
 
+config NAND_DENALI_DT
+       bool "Support Denali NAND controller as a DT device"
+       depends on NAND_DENALI && OF_CONTROL && DM
+       help
+         Enable the driver for NAND flash on platforms using a Denali NAND
+         controller as a DT device.
+
 config SYS_NAND_DENALI_64BIT
        bool "Use 64-bit variant of Denali NAND controller"
        depends on NAND_DENALI
index c3d4a996f37fa7e9ffc28ddb1e7cee1f7a16a490..9f7d9d6ff7ae2ca04edfe29bd09f4af9da810fc1 100644 (file)
@@ -44,6 +44,7 @@ obj-$(CONFIG_NAND_ATMEL) += atmel_nand.o
 obj-$(CONFIG_NAND_ARASAN) += arasan_nfc.o
 obj-$(CONFIG_NAND_DAVINCI) += davinci_nand.o
 obj-$(CONFIG_NAND_DENALI) += denali.o
+obj-$(CONFIG_NAND_DENALI_DT) += denali_dt.o
 obj-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
 obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_nand.o
 obj-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
index 18280b0b2fe87092db40720d7e1355dbf04da9f8..47cf37d1d9b7d2934d1c5e04a0aef0361758c907 100644 (file)
@@ -1175,7 +1175,7 @@ static void denali_hw_init(struct denali_nand_info *denali)
 
 static struct nand_ecclayout nand_oob;
 
-static int denali_init(struct denali_nand_info *denali)
+int denali_init(struct denali_nand_info *denali)
 {
        struct mtd_info *mtd = nand_to_mtd(&denali->nand);
        int ret;
@@ -1273,6 +1273,7 @@ fail:
        return ret;
 }
 
+#ifndef CONFIG_NAND_DENALI_DT
 static int __board_nand_init(void)
 {
        struct denali_nand_info *denali;
@@ -1296,3 +1297,4 @@ void board_nand_init(void)
        if (__board_nand_init() < 0)
                pr_warn("Failed to initialize Denali NAND controller.\n");
 }
+#endif
index 0e098bddf11daddb2ad87c671cfea2ec0283f16f..694bce53a955f272891a81b43e5cec3f8f394c50 100644 (file)
@@ -464,4 +464,6 @@ struct denali_nand_info {
        uint32_t max_banks;
 };
 
+int denali_init(struct denali_nand_info *denali);
+
 #endif /* __DENALI_H__ */
diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c
new file mode 100644 (file)
index 0000000..0a6155c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+
+#include "denali.h"
+
+static const struct udevice_id denali_nand_dt_ids[] = {
+       {
+               .compatible = "altr,socfpga-denali-nand",
+       },
+       {
+               .compatible = "socionext,uniphier-denali-nand-v5a",
+       },
+       {
+               .compatible = "socionext,uniphier-denali-nand-v5b",
+       },
+       { /* sentinel */ }
+};
+
+static int denali_dt_probe(struct udevice *dev)
+{
+       struct denali_nand_info *denali = dev_get_priv(dev);
+       struct resource res;
+       int ret;
+
+       ret = dev_read_resource_byname(dev, "denali_reg", &res);
+       if (ret)
+               return ret;
+
+       denali->flash_reg = devm_ioremap(dev, res.start, resource_size(&res));
+
+       ret = dev_read_resource_byname(dev, "nand_data", &res);
+       if (ret)
+               return ret;
+
+       denali->flash_mem = devm_ioremap(dev, res.start, resource_size(&res));
+
+       return denali_init(denali);
+}
+
+U_BOOT_DRIVER(denali_nand_dt) = {
+       .name = "denali-nand-dt",
+       .id = UCLASS_MISC,
+       .of_match = denali_nand_dt_ids,
+       .probe = denali_dt_probe,
+       .priv_auto_alloc_size = sizeof(struct denali_nand_info),
+};
+
+void board_nand_init(void)
+{
+       struct udevice *dev;
+       int ret;
+
+       ret = uclass_get_device_by_driver(UCLASS_MISC,
+                                         DM_GET_DRIVER(denali_nand_dt),
+                                         &dev);
+       if (ret && ret != -ENODEV)
+               printf("Failed to initialize Denali NAND controller. (error %d)\n",
+                      ret);
+}