From patchwork Sat Aug 24 18:14:59 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Clouter X-Patchwork-Id: 269656 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from casper.infradead.org (unknown [IPv6:2001:770:15f::2]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 076592C00A6 for ; Sun, 25 Aug 2013 04:15:57 +1000 (EST) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VDIN8-0004Ul-Fy; Sat, 24 Aug 2013 18:15:38 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VDIN6-000350-NL; Sat, 24 Aug 2013 18:15:36 +0000 Received: from marmot.wormnet.eu ([2a03:9800:10:2d:3203:b3a5:8bdc:5b68]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VDIN2-00034I-JY for linux-mtd@lists.infradead.org; Sat, 24 Aug 2013 18:15:34 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=digriz.org.uk; s=wopr; h=Content-Type:MIME-Version:Message-ID:Subject:Cc:To:From:Date; bh=gbJdXklUjot9ZnkNLfHVnwiFwiqc9JGv7WUb058F+pA=; b=QBbIuTnMPxaKd0oF4Rq08Ub0pZk3I9LgodUMG5YkC2bJI6YY96TNq3L1NqNVQY+Ab2vZ7gX97SnOftqeh3wXZtKEQtt4aCDY4xSRqJE/G10knMBRKcVqEQxeKaJM75Ny4kPNsfNyPvUkLYNJp/Uk6QNKLHSOCwAQfAOb/A2tXE0=; Received: from waffles.digriz.wormnet.eu ([77.75.106.34] helo=localhost) by marmot.wormnet.eu with esmtpsa (TLSv1:DHE-RSA-AES128-SHA:128) (Exim 4.80) (envelope-from ) id 1VDIMX-0003FX-5d; Sat, 24 Aug 2013 19:15:01 +0100 Date: Sat, 24 Aug 2013 19:14:59 +0100 From: Alexander Clouter To: devicetree-discuss@lists.ozlabs.org Subject: [RFC] mtd: plat_nand: add further DT bindings and documentation Message-ID: <20130824181459.GF3464@edkhil> MIME-Version: 1.0 Content-Disposition: inline Organization: diGriz X-URL: http://www.digriz.org.uk/ X-JabberID: alex@digriz.org.uk User-Agent: Mutt/1.5.20 (2009-06-14) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130824_141533_003357_7A8B179A X-CRM114-Status: GOOD ( 28.17 ) X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: linux-mtd@lists.infradead.org X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Hi, 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 --- .../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@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@0 { + label = "mbr"; + reg = <0x00000000 0x20000>; + read-only; + }; + + partition@20000 { + label = "kernel"; + reg = <0x00020000 0x400000>; + }; + + partition@420000 { + label = "initrd"; + reg = <0x00420000 0x400000>; + }; + + partition@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 #include #include +#include #include #include #include @@ -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; }