Root/target/linux/mpc83xx/patches-3.7/203-mtd-add-rbppc_nand-driver.patch

1--- a/drivers/mtd/nand/Kconfig
2+++ b/drivers/mtd/nand/Kconfig
3@@ -454,6 +454,13 @@ config MTD_NAND_PLATFORM
4       devices. You will need to provide platform-specific functions
5       via platform_data.
6 
7+config MTD_NAND_RB_PPC
8+ tristate "MikroTik RB333/600 NAND support"
9+ depends on RB_PPC
10+ help
11+ This option enables support for the NAND device on MikroTik
12+ RouterBOARD 333/600 series boards.
13+
14 config MTD_ALAUDA
15     tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1"
16     depends on USB
17--- a/drivers/mtd/nand/Makefile
18+++ b/drivers/mtd/nand/Makefile
19@@ -34,6 +34,7 @@ obj-$(CONFIG_MTD_NAND_CM_X270) += cmx27
20 obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o
21 obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o
22 obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
23+obj-$(CONFIG_MTD_NAND_RB_PPC) += rbppc_nand.o
24 obj-$(CONFIG_MTD_ALAUDA) += alauda.o
25 obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
26 obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o
27--- /dev/null
28+++ b/drivers/mtd/nand/rbppc_nand.c
29@@ -0,0 +1,250 @@
30+/*
31+ * Copyright (C) 2008-2009 Noah Fontes <nfontes@transtruct.org>
32+ * Copyright (C) 2009 Michael Guntsche <mike@it-loops.com>
33+ * Copyright (C) Mikrotik 2007
34+ *
35+ * This program is free software; you can redistribute it and/or modify it
36+ * under the terms of the GNU General Public License as published by the
37+ * Free Software Foundation; either version 2 of the License, or (at your
38+ * option) any later version.
39+ */
40+
41+#include <linux/init.h>
42+#include <linux/module.h>
43+#include <linux/mtd/nand.h>
44+#include <linux/mtd/mtd.h>
45+#include <linux/mtd/partitions.h>
46+#include <linux/of_platform.h>
47+#include <linux/of_device.h>
48+#include <linux/slab.h>
49+#include <linux/delay.h>
50+#include <asm/io.h>
51+
52+#define DRV_NAME "rbppc_nand"
53+#define DRV_VERSION "0.0.2"
54+
55+static struct mtd_info rmtd;
56+static struct nand_chip rnand;
57+
58+struct rbppc_nand_info {
59+ void *gpi;
60+ void *gpo;
61+ void *localbus;
62+
63+ unsigned gpio_rdy;
64+ unsigned gpio_nce;
65+ unsigned gpio_cle;
66+ unsigned gpio_ale;
67+ unsigned gpio_ctrls;
68+};
69+
70+/* We must use the OOB layout from yaffs 1 if we want this to be recognized
71+ * properly. Borrowed from the OpenWRT patches for the RB532.
72+ *
73+ * See <https://dev.openwrt.org/browser/trunk/target/linux/rb532/
74+ * patches-2.6.28/025-rb532_nand_fixup.patch> for more details.
75+ */
76+static struct nand_ecclayout rbppc_nand_oob_16 = {
77+ .eccbytes = 6,
78+ .eccpos = { 8, 9, 10, 13, 14, 15 },
79+ .oobavail = 9,
80+ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
81+};
82+
83+static struct mtd_partition rbppc_nand_partition_info[] = {
84+ {
85+ name: "kernel",
86+ offset: 0,
87+ size: 4 * 1024 * 1024,
88+ },
89+ {
90+ name: "rootfs",
91+ offset: MTDPART_OFS_NXTBLK,
92+ size: MTDPART_SIZ_FULL,
93+ },
94+};
95+
96+static int rbppc_nand_dev_ready(struct mtd_info *mtd) {
97+ struct nand_chip *chip = mtd->priv;
98+ struct rbppc_nand_info *priv = chip->priv;
99+
100+ return in_be32(priv->gpi) & priv->gpio_rdy;
101+}
102+
103+static void rbppc_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) {
104+ struct nand_chip *chip = mtd->priv;
105+ struct rbppc_nand_info *priv = chip->priv;
106+
107+ if (ctrl & NAND_CTRL_CHANGE) {
108+ unsigned val = in_be32(priv->gpo);
109+ if (!(val & priv->gpio_nce)) {
110+ /* make sure Local Bus has done NAND operations */
111+ readb(priv->localbus);
112+ }
113+
114+ if (ctrl & NAND_CLE) {
115+ val |= priv->gpio_cle;
116+ } else {
117+ val &= ~priv->gpio_cle;
118+ }
119+ if (ctrl & NAND_ALE) {
120+ val |= priv->gpio_ale;
121+ } else {
122+ val &= ~priv->gpio_ale;
123+ }
124+ if (!(ctrl & NAND_NCE)) {
125+ val |= priv->gpio_nce;
126+ } else {
127+ val &= ~priv->gpio_nce;
128+ }
129+ out_be32(priv->gpo, val);
130+
131+ /* make sure GPIO output has changed */
132+ val ^= in_be32(priv->gpo);
133+ if (val & priv->gpio_ctrls) {
134+ printk(KERN_ERR "rbppc_nand_hwcontrol: NAND GPO change failed 0x%08x\n", val);
135+ }
136+ }
137+
138+ if (cmd != NAND_CMD_NONE) writeb(cmd, chip->IO_ADDR_W);
139+}
140+
141+static void rbppc_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
142+{
143+ struct nand_chip *chip = mtd->priv;
144+ memcpy(buf, chip->IO_ADDR_R, len);
145+}
146+
147+static unsigned init_ok = 0;
148+
149+static int __devinit rbppc_nand_probe(struct platform_device *pdev)
150+{
151+ struct device_node *gpio;
152+ struct device_node *nnand;
153+ struct resource res;
154+ struct rbppc_nand_info *info;
155+ void *baddr;
156+ const unsigned *rdy, *nce, *cle, *ale;
157+
158+ printk(KERN_INFO "rbppc_nand_probe: MikroTik RouterBOARD 333/600 series NAND driver, version " DRV_VERSION "\n");
159+
160+ info = kmalloc(sizeof(*info), GFP_KERNEL);
161+
162+ rdy = of_get_property(pdev->dev.of_node, "rdy", NULL);
163+ nce = of_get_property(pdev->dev.of_node, "nce", NULL);
164+ cle = of_get_property(pdev->dev.of_node, "cle", NULL);
165+ ale = of_get_property(pdev->dev.of_node, "ale", NULL);
166+
167+ if (!rdy || !nce || !cle || !ale) {
168+ printk(KERN_ERR "rbppc_nand_probe: GPIO properties are missing\n");
169+ goto err;
170+ }
171+ if (rdy[0] != nce[0] || rdy[0] != cle[0] || rdy[0] != ale[0]) {
172+ printk(KERN_ERR "rbppc_nand_probe: Different GPIOs are not supported\n");
173+ goto err;
174+ }
175+
176+ gpio = of_find_node_by_phandle(rdy[0]);
177+ if (!gpio) {
178+ printk(KERN_ERR "rbppc_nand_probe: No GPIO<%x> node found\n", *rdy);
179+ goto err;
180+ }
181+ if (of_address_to_resource(gpio, 0, &res)) {
182+ printk(KERN_ERR "rbppc_nand_probe: No reg property in GPIO found\n");
183+ goto err;
184+ }
185+ info->gpo = ioremap_nocache(res.start, res.end - res.start + 1);
186+
187+ if (!of_address_to_resource(gpio, 1, &res)) {
188+ info->gpi = ioremap_nocache(res.start, res.end - res.start + 1);
189+ } else {
190+ info->gpi = info->gpo;
191+ }
192+ of_node_put(gpio);
193+
194+ info->gpio_rdy = 1 << (31 - rdy[1]);
195+ info->gpio_nce = 1 << (31 - nce[1]);
196+ info->gpio_cle = 1 << (31 - cle[1]);
197+ info->gpio_ale = 1 << (31 - ale[1]);
198+ info->gpio_ctrls = info->gpio_nce | info->gpio_cle | info->gpio_ale;
199+
200+ nnand = of_find_node_by_name(NULL, "nnand");
201+ if (!nnand) {
202+ printk("rbppc_nand_probe: No nNAND found\n");
203+ goto err;
204+ }
205+ if (of_address_to_resource(nnand, 0, &res)) {
206+ printk("rbppc_nand_probe: No reg property in nNAND found\n");
207+ goto err;
208+ }
209+ of_node_put(nnand);
210+ info->localbus = ioremap_nocache(res.start, res.end - res.start + 1);
211+
212+ if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
213+ printk("rbppc_nand_probe: No reg property found\n");
214+ goto err;
215+ }
216+ baddr = ioremap_nocache(res.start, res.end - res.start + 1);
217+
218+ memset(&rnand, 0, sizeof(rnand));
219+ rnand.cmd_ctrl = rbppc_nand_cmd_ctrl;
220+ rnand.dev_ready = rbppc_nand_dev_ready;
221+ rnand.read_buf = rbppc_nand_read_buf;
222+ rnand.IO_ADDR_W = baddr;
223+ rnand.IO_ADDR_R = baddr;
224+ rnand.priv = info;
225+
226+ memset(&rmtd, 0, sizeof(rmtd));
227+ rnand.ecc.mode = NAND_ECC_SOFT;
228+ rnand.ecc.layout = &rbppc_nand_oob_16;
229+ rnand.chip_delay = 25;
230+ rmtd.priv = &rnand;
231+ rmtd.owner = THIS_MODULE;
232+
233+ if (nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1)) {
234+ printk(KERN_ERR "rbppc_nand_probe: RouterBOARD NAND device not found\n");
235+ return -ENXIO;
236+ }
237+
238+ mtd_device_parse_register(&rmtd, NULL, 0, rbppc_nand_partition_info, 2);
239+ init_ok = 1;
240+ return 0;
241+
242+err:
243+ kfree(info);
244+ return -1;
245+}
246+
247+static struct of_device_id rbppc_nand_ids[] = {
248+ { .name = "nand", },
249+ { },
250+};
251+
252+static struct platform_driver rbppc_nand_driver = {
253+ .probe = rbppc_nand_probe,
254+ .driver = {
255+ .name = "rbppc-nand",
256+ .owner = THIS_MODULE,
257+ .of_match_table = rbppc_nand_ids,
258+ },
259+};
260+
261+static int __init rbppc_nand_init(void)
262+{
263+ return platform_driver_register(&rbppc_nand_driver);
264+}
265+
266+static void __exit rbppc_nand_exit(void)
267+{
268+ platform_driver_unregister(&rbppc_nand_driver);
269+}
270+
271+MODULE_AUTHOR("Mikrotikls SIA");
272+MODULE_AUTHOR("Noah Fontes");
273+MODULE_AUTHOR("Michael Guntsche");
274+MODULE_DESCRIPTION("MikroTik RouterBOARD 333/600 series NAND driver");
275+MODULE_LICENSE("GPL");
276+MODULE_VERSION(DRV_VERSION);
277+
278+module_init(rbppc_nand_init);
279+module_exit(rbppc_nand_exit);
280

Archive Download this file



interactive