From patchwork Sun Mar 3 15:52:26 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Clouter X-Patchwork-Id: 224554 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 97DBF2C030B for ; Mon, 4 Mar 2013 03:02:34 +1100 (EST) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UCBFm-0001sM-Qw; Sun, 03 Mar 2013 15:55:10 +0000 Received: from marmot.wormnet.eu ([188.246.204.87]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UCBFe-0001qR-VO for linux-mtd@lists.infradead.org; Sun, 03 Mar 2013 15:55:08 +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=ZeWcI3iZKYYRkEUjEdvSOrVGTpWecSBRTmrAsbpLwiA=; b=pgF1UzmXwCffY49aGFH50Zikvyqrppoie9a25avwwxHx/lz3GSVVeriWzDaD3by91Gl3gn2XABfV015mrO252IxuJzx3Mlq5deN5MWirMeIhMxW2xfrN3aXzNwKgsZdjb5eBl2t71+Xuo3Etz8ac8kr7pHX2AqDWg9J2m4zfRcw=; 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 1UCBDA-0007zG-Ax; Sun, 03 Mar 2013 15:52:28 +0000 Date: Sun, 3 Mar 2013 15:52:26 +0000 From: Alexander Clouter To: linux-mtd@lists.infradead.org Subject: plat-nand DT support Message-ID: <20130303155226.GA1976@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-20130303_105503_275027_C1607AC4 X-CRM114-Status: GOOD ( 24.09 ) 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: hsweeten@visionengravers.com, devicetree-discuss@lists.ozlabs.org, blogic@openwrt.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 been busy porting an ARM board (that uses plat_nand) to devicetree and stumbled on John Crispin's patch from last year[1]. 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/gen-nand-dt/arch/arm/mach-orion5x/board-ts7800.c https://github.com/jimdigriz/ts78xx/blob/gen-nand-dt/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[2] but then are we not just littering drivers/mtd/nand rather than arch/arm/mach-foobar? Cheers [1] http://lists.infradead.org/pipermail/linux-mtd/2012-April/041025.html [2] could also support the NAND used by arch/arm/mach-ep93xx/ts72xx.c but the whole SoC has not been ported to DT diff --git a/Documentation/devicetree/bindings/mtd/plat-nand.txt b/Documentation/devicetree/bindings/mtd/plat-nand.txt new file mode 100644 index 0000000..8df90d2 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/plat-nand.txt @@ -0,0 +1,92 @@ +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. Typically only one element in size, but some users + (see board-ts7800.c) need additional addresses. The first reg *must* + be the data io region, additional ones are platform defined +- nr-chips : Number of physical chips + +Optional properties: +- reg-name : First *should* be "data", 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 = "technologicsystems,nand", "gen_nand"; + reg = <0x804 0x04>, + <0x800 0x04>; + reg-names = "data", "ctrl"; + nr-chips = <1>; + chip-delay = <15>; + bbt-use-flash; + + partition@0 { + label = "mbr"; + reg = <0x00000000 0x00020000>; + read-only; + }; + + partition@20000 { + label = "kernel"; + reg = <0x00020000 0x00400000>; + }; + + partition@420000 { + label = "initrd"; + reg = <0x00420000 0x00400000>; + }; + + 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 (relevant snippets from board-ts7800.c): + +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, "technologicsystems,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..0b07388 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,11 +43,6 @@ 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); if (!res) return -ENXIO; @@ -79,15 +75,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 +123,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; }