83cb507377aa0a4989292584e96ed05277d8291e
[openwrt.git] / target / linux / mpc83xx / patches-2.6.35 / 016-drivers_mtd_nand_rbppc_nand.patch
1 --- /dev/null
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);