Root/target/linux/mpc83xx/patches-2.6.33/016-drivers_mtd_nand_rbppc_nand.patch

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

Archive Download this file



interactive