[RFC] mtd: plat_nand: add further DT bindings and documentation

Alexander Clouter alex at digriz.org.uk
Sun Sep 1 09:52:44 EDT 2013


Anyone?

On Sat, Aug 24, 2013 at 07:14:59PM +0100, Alexander Clouter wrote:
>I have run this via the linux-mtd folks before[1], but I get the
>impression everyone is either too busy or does not want to make the
>judgement call about plat_nand's future; linux-mtd pointed me here. :)
>
>I have been busy porting an ARM board (that uses plat_nand) to
>devicetree and stumbled on John Crispin's patch from last year[2].
>There was not much online about how to use it, so I went about
>building upon his work it what seemed to be natural and a good fit.
>
>Attached is the work I have done to the driver its-self (including the
>much needed bindings documentation), whilst on my github page I have
>put up an example of its usage:
>
>https://github.com/jimdigriz/ts78xx/blob/plat-nand/arch/arm/mach-orion5x/board-ts7800.c
>https://github.com/jimdigriz/ts78xx/blob/plat-nand/arch/arm/boot/dts/orion5x-ts7800.dts
>
>Am I going in the right direction here?  plat_nand, by its nature, is
>not very DT, the alternative would be a custom driver for my
>platform[3] but then are we not just littering drivers/mtd/nand rather
>than arch/arm/mach-foobar?  Is plat_nand going to be marked deprecated?
>
>Meanwhile, the plat_nand driver does currently have some devicetree
>support but it is currently unusable, and more so as there is no
>documentation on how to use it.
>
>The patch below adds the much needed documentation as well as adds some
>common properties (bank-width, chip-delay, bbt-use-flash and nr-chips)
>removing further use of the platform_nand_data struct.
>
>So, what am I to do.  Forget plat_nand as it is going to be marked
>deprecated and write a dedicated driver[4]?  If not, what do I need to
>do/change/improve to get this ready for for prime time action?
>
>Cheers
>
>[1] http://lists.infradead.org/pipermail/linux-mtd/2013-March/046371.html
>[2] http://lists.infradead.org/pipermail/linux-mtd/2012-April/041025.html
>[3] I could also support the NAND used by arch/arm/mach-ep93xx/ts72xx.c
>	but the whole SoC has not been ported to DT
>[4] which ironically it was recommended[5] I used plat_nand when I did this
>	(although a lot	changes in four years) originally by Hartley who had
>	just moved the ts72xx to plat_nand[6]
>[5] http://lists.infradead.org/pipermail/linux-mtd/2009-October/027563.html
>[6] http://lists.infradead.org/pipermail/linux-mtd/2009-February/024555.html
>
>Signed-off-by: Alexander Clouter <alex at digriz.org.uk>
>---
>  .../devicetree/bindings/mtd/plat-nand.txt          |   93 ++++++++++++++++++++
>  drivers/mtd/nand/plat_nand.c                       |   53 ++++++++---
>  2 files changed, 134 insertions(+), 12 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/mtd/plat-nand.txt
>
>diff --git a/Documentation/devicetree/bindings/mtd/plat-nand.txt b/Documentation/devicetree/bindings/mtd/plat-nand.txt
>new file mode 100644
>index 0000000..d534bfa
>--- /dev/null
>+++ b/Documentation/devicetree/bindings/mtd/plat-nand.txt
>@@ -0,0 +1,93 @@
>+NAND support for Generic NAND driver
>+
>+Required properties:
>+- compatible : "gen_nand"
>+- reg : Array of base physical addresses of the NAND and the length of memory
>+	mapped regions.  You *should* have a "nand_data" reg which is the
>+	data io region (if not named, then the first reg is used for
>+	IO_ADDR_R/IO_ADDR_W), additional regs are platform defined
>+- nr-chips : Number of physical chips
>+
>+Optional properties:
>+- reg-name : "nand_data" *should* be defined, additional ones are platform
>+		defined
>+- bank-width : Width in bytes of the device. Default is 1 (8bit), 2 (16bit)
>+		implies NAND_BUSWIDTH_16 and any other value is invalid
>+- chip-delay : Chip dependent delay for transferring data from array to read
>+		registers in usecs
>+- bbt-use-flash : Use a flash based bad block table.  Default, OOB identifier
>+		is saved in OOB area
>+
>+The device tree may optionally contain sub-nodes describing partitions of the
>+address space. See partition.txt for more detail.
>+
>+Example:
>+
>+nand at 800 {
>+	#address-cells = <1>;
>+	#size-cells = <1>;
>+	compatible = "ts,nand", "gen_nand";
>+	reg =   <0x800 0x04>,
>+		<0x804 0x04>;
>+	reg-names = "nand_ctrl", "nand_data";
>+	nr-chips = <1>;
>+	chip-delay = <15>;
>+	bbt-use-flash;
>+
>+	partition at 0 {
>+		label = "mbr";
>+		reg = <0x00000000 0x20000>;
>+		read-only;
>+	};
>+
>+	partition at 20000 {
>+		label = "kernel";
>+		reg = <0x00020000 0x400000>;
>+	};
>+
>+	partition at 420000 {
>+		label = "initrd";
>+		reg = <0x00420000 0x400000>;
>+	};
>+
>+	partition at 820000 {
>+		label = "rootfs";
>+		reg = <0x00820000 0x1f7e0000>;
>+	};
>+};
>+
>+N.B. to use the plat-nand driver, the platform board code does still need to
>+	setup platform_nand_data and hook it into the platform_device so
>+	the callbacks (for at least .cmd_ctrl and .dev_ready) are available.
>+
>+Example:
>+
>+static struct platform_nand_data ts7800_nand_data = {
>+        .ctrl   = {
>+                .cmd_ctrl               = ts7800_nand_cmd_ctrl,
>+                .dev_ready              = ts7800_nand_dev_ready,
>+        },
>+};
>+
>+static int ts7800_platform_notifier(struct notifier_block *nb,
>+                                  unsigned long event, void *__dev)
>+{
>+        struct device *dev = __dev;
>+
>+        if (event != BUS_NOTIFY_ADD_DEVICE)
>+                return NOTIFY_DONE;
>+
>+        if (of_device_is_compatible(dev->of_node, "ts,nand"))
>+                dev->platform_data = &ts7800_nand_data;
>+
>+        return NOTIFY_OK;
>+}
>+
>+static struct notifier_block ts7800_platform_nb = {
>+        .notifier_call = ts7800_platform_notifier,
>+};
>+
>+void __init ts7800_init(void)
>+{
>+        bus_register_notifier(&platform_bus_type, &ts7800_platform_nb);
>+}
>diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
>index c004566..1407db5 100644
>--- a/drivers/mtd/nand/plat_nand.c
>+++ b/drivers/mtd/nand/plat_nand.c
>@@ -12,6 +12,7 @@
>  #include <linux/io.h>
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
>+#include <linux/of.h>
>  #include <linux/slab.h>
>  #include <linux/mtd/mtd.h>
>  #include <linux/mtd/nand.h>
>@@ -23,7 +24,7 @@ struct plat_nand_data {
>  	void __iomem		*io_base;
>  };
>-static const char *part_probe_types[] = { "cmdlinepart", NULL };
>+static const char *part_probe_types[] = { "cmdlinepart", "ofpart", NULL };
>  /*
>   * Probe for the NAND device.
>@@ -42,14 +43,11 @@ static int plat_nand_probe(struct platform_device *pdev)
>  		return -EINVAL;
>  	}
>-	if (pdata->chip.nr_chips < 1) {
>-		dev_err(&pdev->dev, "invalid number of chips specified\n");
>-		return -EINVAL;
>-	}
>-
>-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data");
>  	if (!res)
>-		return -ENXIO;
>+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>+		if (!res)
>+			return -ENXIO;
>  	/* Allocate memory for the device structure (and zero it) */
>  	data = kzalloc(sizeof(struct plat_nand_data), GFP_KERNEL);
>@@ -79,15 +77,40 @@ static int plat_nand_probe(struct platform_device *pdev)
>  	data->chip.IO_ADDR_R = data->io_base;
>  	data->chip.IO_ADDR_W = data->io_base;
>+
>+	if (pdev->dev.of_node) {
>+		int i;
>+
>+		if (!of_property_read_u32(pdev->dev.of_node,
>+						"nr-chips", &i))
>+			data->chip.numchips = i;
>+		if (!of_property_read_u32(pdev->dev.of_node,
>+						"chip-delay", &i))
>+			data->chip.chip_delay = (u8)i;
>+		if (!of_property_read_u32(pdev->dev.of_node,
>+						"bank-width", &i)) {
>+			if (i == 2)
>+				data->chip.options |= NAND_BUSWIDTH_16;
>+			else if (i != 1) {
>+				dev_warn(&pdev->dev,
>+					"%d bit bus width out of range\n", i);
>+			}
>+		}
>+		if (of_get_property(pdev->dev.of_node, "bbt-use-flash", &i))
>+			data->chip.bbt_options |= NAND_BBT_USE_FLASH;
>+	} else {
>+		data->chip.numchips = pdata->chip.nr_chips;
>+		data->chip.chip_delay = pdata->chip.chip_delay;
>+		data->chip.options |= pdata->chip.options;
>+		data->chip.bbt_options |= pdata->chip.bbt_options;
>+	}
>+
>  	data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl;
>  	data->chip.dev_ready = pdata->ctrl.dev_ready;
>  	data->chip.select_chip = pdata->ctrl.select_chip;
>  	data->chip.write_buf = pdata->ctrl.write_buf;
>  	data->chip.read_buf = pdata->ctrl.read_buf;
>  	data->chip.read_byte = pdata->ctrl.read_byte;
>-	data->chip.chip_delay = pdata->chip.chip_delay;
>-	data->chip.options |= pdata->chip.options;
>-	data->chip.bbt_options |= pdata->chip.bbt_options;
>  	data->chip.ecc.hwctl = pdata->ctrl.hwcontrol;
>  	data->chip.ecc.layout = pdata->chip.ecclayout;
>@@ -102,8 +125,14 @@ static int plat_nand_probe(struct platform_device *pdev)
>  			goto out;
>  	}
>+	if (data->chip.numchips < 1) {
>+		dev_err(&pdev->dev, "invalid number of chips specified\n");
>+		err = -EINVAL;
>+		goto out;
>+	}
>+
>  	/* Scan to find existence of the device */
>-	if (nand_scan(&data->mtd, pdata->chip.nr_chips)) {
>+	if (nand_scan(&data->mtd, data->chip.numchips)) {
>  		err = -ENXIO;
>  		goto out;
>  	}
>-- 
>1.7.10.4

-- 
Alexander Clouter
.sigmonster says: BOFH excuse #227:
                   Fatal error right in front of screen



More information about the linux-mtd mailing list