[RFC PATCH 6/9] nand/denali: add an mmio driver

Jamie Iles jamie at jamieiles.com
Fri May 6 10:29:00 EDT 2011


Add an mmio driver so that the Denali controller can be used as a
platform_device.  This is useful on SoC devices.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/Kconfig       |   10 +++-
 drivers/mtd/nand/Makefile      |    1 +
 drivers/mtd/nand/denali.h      |    1 +
 drivers/mtd/nand/denali_mmio.c |  145 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 156 insertions(+), 1 deletions(-)
 create mode 100644 drivers/mtd/nand/denali_mmio.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index d629b68..6698bd5 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -78,7 +78,15 @@ config MTD_NAND_DENALI_PCI
         help
           Enable the driver for NAND flash on Intel Moorestown, using the
           Denali NAND controller core.
- 
+
+config MTD_NAND_DENALI_MMIO
+	tristate "Support Denali NAND controller as an MMIO device"
+	depends on HAVE_CLK && MTD_NAND_DENALI
+	help
+	  Enable the driver for NAND flash on platforms using a Denali NAND
+	  controller as an MMIO device.  This uses a platform_driver and
+	  platform_device as the driver model interface.
+
 config MTD_NAND_DENALI_SCRATCH_REG_ADDR
         hex "Denali NAND size scratch register address"
         default "0xFF108018"
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index ed4a2d8..c400549 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_MTD_NAND_AMS_DELTA)	+= ams-delta.o
 obj-$(CONFIG_MTD_NAND_AUTCPU12)		+= autcpu12.o
 obj-$(CONFIG_MTD_NAND_DENALI)		+= denali.o
 obj-$(CONFIG_MTD_NAND_DENALI_PCI)	+= denali_pci.o
+obj-$(CONFIG_MTD_NAND_DENALI_MMIO)	+= denali_mmio.o
 obj-$(CONFIG_MTD_NAND_EDB7312)		+= edb7312.o
 obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
 obj-$(CONFIG_MTD_NAND_BF5XX)		+= bf5xx_nand.o
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index e5aa995..3f99b7b 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -466,6 +466,7 @@ struct nand_buf {
 
 #define INTEL_CE4100	1
 #define INTEL_MRST	2
+#define MMIO		3
 
 struct denali_nand_info {
 	struct mtd_info mtd;
diff --git a/drivers/mtd/nand/denali_mmio.c b/drivers/mtd/nand/denali_mmio.c
new file mode 100644
index 0000000..b9ef645
--- /dev/null
+++ b/drivers/mtd/nand/denali_mmio.c
@@ -0,0 +1,145 @@
+/*
+ * NAND Flash Controller Device Driver
+ *
+ * Copyright © 2011, Picochip.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "denali.h"
+
+struct denali_mmio {
+	struct denali_nand_info	denali;
+	struct clk		*clk;
+};
+
+static void __iomem *request_and_map(struct device *dev,
+				     const struct resource *res)
+{
+	void __iomem *ptr;
+
+	if (!devm_request_mem_region(dev, res->start, resource_size(res),
+				     "denali-mmio")) {
+		dev_err(dev, "unable to request %s\n", res->name);
+		return NULL;
+	}
+
+	ptr = devm_ioremap_nocache(dev, res->start, resource_size(res));
+	if (!res)
+		dev_err(dev, "ioremap_nocache of %s failed!", res->name);
+
+	return ptr;
+}
+
+static int __devinit denali_mmio_probe(struct platform_device *pdev)
+{
+	struct resource *reg, *mem;
+	struct denali_mmio *mmio;
+	struct denali_nand_info *denali;
+	int ret;
+
+	mmio = devm_kzalloc(&pdev->dev, sizeof(*mmio), GFP_KERNEL);
+	if (!mmio)
+		return -ENOMEM;
+	denali = &mmio->denali;
+
+	reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg");
+	mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
+	if (!reg || !mem) {
+		dev_err(&pdev->dev, "resources not completely defined\n");
+		return -EINVAL;
+	}
+
+	denali->platform = MMIO;
+	denali->dev = &pdev->dev;
+	denali->irq = platform_get_irq(pdev, 0);
+	if (denali->irq < 0) {
+		dev_err(&pdev->dev, "no irq defined\n");
+		return -ENXIO;
+	}
+
+	denali->flash_reg = request_and_map(&pdev->dev, reg);
+	if (!denali->flash_reg)
+		return -ENOMEM;
+
+	denali->flash_mem = request_and_map(&pdev->dev, mem);
+	if (!denali->flash_mem)
+		return -ENOMEM;
+
+	mmio->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mmio->clk)) {
+		dev_err(&pdev->dev, "no clk available\n");
+		return PTR_ERR(mmio->clk);
+	}
+
+	ret = clk_enable(mmio->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable clk\n");
+		goto out_put_clk;
+	}
+
+	ret = denali_init(denali);
+	if (ret)
+		goto out_disable_clk;
+
+	platform_set_drvdata(pdev, mmio);
+
+	return 0;
+
+out_disable_clk:
+	clk_disable(mmio->clk);
+out_put_clk:
+	clk_put(mmio->clk);
+
+	return ret;
+}
+
+static int __devexit denali_mmio_remove(struct platform_device *pdev)
+{
+	struct denali_mmio *mmio = platform_get_drvdata(pdev);
+
+	denali_remove(&mmio->denali);
+	clk_disable(mmio->clk);
+	clk_put(mmio->clk);
+
+	return 0;
+}
+
+static struct platform_driver denali_mmio_driver = {
+	.probe		= denali_mmio_probe,
+	.remove		= __devexit_p(denali_mmio_remove),
+	.driver		= {
+		.name	= "denali-nand-mmio",
+	},
+};
+
+static int __init denali_init_mmio(void)
+{
+	return platform_driver_register(&denali_mmio_driver);
+}
+module_init(denali_init_mmio);
+
+static void __exit denali_exit_mmio(void)
+{
+	platform_driver_unregister(&denali_mmio_driver);
+}
+module_exit(denali_exit_mmio);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jamie Iles");
+MODULE_DESCRIPTION("MMIO driver for Denali NAND controller");
-- 
1.7.4.4




More information about the linux-mtd mailing list