[target:xburst] do not override CFLAGS - the default ones are fine
[openwrt.git] / target / linux / xburst / patches-2.6.34 / 050-nand.patch
1 From 88aacb09dfdf4d85c507757524166433204260e8 Mon Sep 17 00:00:00 2001
2 From: Lars-Peter Clausen <lars@metafoo.de>
3 Date: Sat, 24 Apr 2010 12:14:46 +0200
4 Subject: [PATCH] Add jz4740 nand driver
5
6 ---
7  drivers/mtd/nand/Kconfig        |    6 +
8  drivers/mtd/nand/Makefile       |    1 +
9  drivers/mtd/nand/jz4740_nand.c  |  444 +++++++++++++++++++++++++++++++++++++++
10  include/linux/mtd/jz4740_nand.h |   34 +++
11  include/mtd/mtd-abi.h           |    2 +-
12  5 files changed, 486 insertions(+), 1 deletions(-)
13  create mode 100644 drivers/mtd/nand/jz4740_nand.c
14  create mode 100644 include/linux/mtd/jz4740_nand.h
15
16 diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
17 index 42e5ea4..6f587b8 100644
18 --- a/drivers/mtd/nand/Kconfig
19 +++ b/drivers/mtd/nand/Kconfig
20 @@ -488,4 +488,10 @@ config MTD_NAND_W90P910
21           This enables the driver for the NAND Flash on evaluation board based
22           on w90p910.
23  
24 +config MTD_NAND_JZ4740
25 +       tristate "Support NAND Flash device on Jz4740 board"
26 +       depends on SOC_JZ4740
27 +       help
28 +       Support NAND Flash device on Jz4740 board
29 +
30  endif # MTD_NAND
31 diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
32 index 1407bd1..e56bd52 100644
33 --- a/drivers/mtd/nand/Makefile
34 +++ b/drivers/mtd/nand/Makefile
35 @@ -42,5 +42,6 @@ obj-$(CONFIG_MTD_NAND_TXX9NDFMC)      += txx9ndfmc.o
36  obj-$(CONFIG_MTD_NAND_W90P910)         += w90p910_nand.o
37  obj-$(CONFIG_MTD_NAND_NOMADIK)         += nomadik_nand.o
38  obj-$(CONFIG_MTD_NAND_BCM_UMI)         += bcm_umi_nand.o nand_bcm_umi.o
39 +obj-$(CONFIG_MTD_NAND_JZ4740)          += jz4740_nand.o
40  
41  nand-objs := nand_base.o nand_bbt.o
42 diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
43 new file mode 100644
44 index 0000000..7b3477d
45 --- /dev/null
46 +++ b/drivers/mtd/nand/jz4740_nand.c
47 @@ -0,0 +1,444 @@
48 +/*
49 + *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
50 + *     JZ4720/JZ4740 SoC NAND controller driver
51 + *
52 + *  This program is free software; you can redistribute         it and/or modify it
53 + *  under  the terms of         the GNU General  Public License as published by the
54 + *  Free Software Foundation;  either version 2 of the License, or (at your
55 + *  option) any later version.
56 + *
57 + *  You should have received a copy of the  GNU General Public License along
58 + *  with this program; if not, write  to the Free Software Foundation, Inc.,
59 + *  675 Mass Ave, Cambridge, MA 02139, USA.
60 + *
61 + */
62 +
63 +#include <linux/ioport.h>
64 +#include <linux/kernel.h>
65 +#include <linux/module.h>
66 +#include <linux/platform_device.h>
67 +#include <linux/slab.h>
68 +
69 +#include <linux/mtd/mtd.h>
70 +#include <linux/mtd/nand.h>
71 +#include <linux/mtd/partitions.h>
72 +
73 +#include <linux/mtd/jz4740_nand.h>
74 +#include <linux/gpio.h>
75 +
76 +#define JZ_REG_NAND_CTRL       0x50
77 +#define JZ_REG_NAND_ECC_CTRL   0x100
78 +#define JZ_REG_NAND_DATA       0x104
79 +#define JZ_REG_NAND_PAR0       0x108
80 +#define JZ_REG_NAND_PAR1       0x10C
81 +#define JZ_REG_NAND_PAR2       0x110
82 +#define JZ_REG_NAND_IRQ_STAT   0x114
83 +#define JZ_REG_NAND_IRQ_CTRL   0x118
84 +#define JZ_REG_NAND_ERR(x)     (0x11C + (x << 2))
85 +
86 +#define JZ_NAND_ECC_CTRL_PAR_READY     BIT(4)
87 +#define JZ_NAND_ECC_CTRL_ENCODING      BIT(3)
88 +#define JZ_NAND_ECC_CTRL_RS            BIT(2)
89 +#define JZ_NAND_ECC_CTRL_RESET         BIT(1)
90 +#define JZ_NAND_ECC_CTRL_ENABLE                BIT(0)
91 +
92 +#define JZ_NAND_STATUS_ERR_COUNT       (BIT(31) | BIT(30) | BIT(29))
93 +#define JZ_NAND_STATUS_PAD_FINISH      BIT(4)
94 +#define JZ_NAND_STATUS_DEC_FINISH      BIT(3)
95 +#define JZ_NAND_STATUS_ENC_FINISH      BIT(2)
96 +#define JZ_NAND_STATUS_UNCOR_ERROR     BIT(1)
97 +#define JZ_NAND_STATUS_ERROR           BIT(0)
98 +
99 +#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT(x << 1)
100 +#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT((x << 1) + 1)
101 +
102 +#define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
103 +#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
104 +#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
105 +
106 +struct jz_nand {
107 +       struct mtd_info mtd;
108 +       struct nand_chip chip;
109 +       void __iomem *base;
110 +       struct resource *mem;
111 +
112 +       struct jz_nand_platform_data *pdata;
113 +       bool is_reading;
114 +};
115 +
116 +static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
117 +{
118 +       return container_of(mtd, struct jz_nand, mtd);
119 +}
120 +
121 +static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
122 +{
123 +       struct jz_nand *nand = mtd_to_jz_nand(mtd);
124 +       struct nand_chip *chip = mtd->priv;
125 +       uint32_t reg;
126 +
127 +       if (ctrl & NAND_CTRL_CHANGE) {
128 +               BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
129 +               if (ctrl & NAND_ALE)
130 +                       chip->IO_ADDR_W = JZ_NAND_ADDR_ADDR;
131 +               else if (ctrl & NAND_CLE)
132 +                       chip->IO_ADDR_W = JZ_NAND_CMD_ADDR;
133 +               else
134 +                       chip->IO_ADDR_W = JZ_NAND_DATA_ADDR;
135 +
136 +               reg = readl(nand->base + JZ_REG_NAND_CTRL);
137 +               if (ctrl & NAND_NCE)
138 +                       reg |= JZ_NAND_CTRL_ASSERT_CHIP(0);
139 +               else
140 +                       reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0);
141 +               writel(reg, nand->base + JZ_REG_NAND_CTRL);
142 +       }
143 +       if (dat != NAND_CMD_NONE)
144 +               writeb(dat, chip->IO_ADDR_W);
145 +}
146 +
147 +static int jz_nand_dev_ready(struct mtd_info *mtd)
148 +{
149 +       struct jz_nand *nand = mtd_to_jz_nand(mtd);
150 +       return gpio_get_value_cansleep(nand->pdata->busy_gpio);
151 +}
152 +
153 +static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
154 +{
155 +       struct jz_nand *nand = mtd_to_jz_nand(mtd);
156 +       uint32_t reg;
157 +
158 +
159 +       writel(0, nand->base + JZ_REG_NAND_IRQ_STAT);
160 +       reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
161 +
162 +       reg |= JZ_NAND_ECC_CTRL_RESET;
163 +       reg |= JZ_NAND_ECC_CTRL_ENABLE;
164 +       reg |= JZ_NAND_ECC_CTRL_RS;
165 +
166 +       switch (mode) {
167 +       case NAND_ECC_READ:
168 +               reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
169 +               nand->is_reading = true;
170 +               break;
171 +       case NAND_ECC_WRITE:
172 +               reg |= JZ_NAND_ECC_CTRL_ENCODING;
173 +               nand->is_reading = false;
174 +               break;
175 +       default:
176 +               break;
177 +       }
178 +
179 +       writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
180 +}
181 +
182 +
183 +static int jz_nand_calculate_ecc_rs(struct mtd_info* mtd, const uint8_t *dat,
184 +                                       uint8_t *ecc_code)
185 +{
186 +       struct jz_nand *nand = mtd_to_jz_nand(mtd);
187 +       uint32_t reg, status;
188 +       int i;
189 +       static uint8_t empty_block_ecc[] = {0xcd, 0x9d, 0x90, 0x58, 0xf4,
190 +                                               0x8b, 0xff, 0xb7, 0x6f};
191 +
192 +       if (nand->is_reading)
193 +               return 0;
194 +
195 +       do {
196 +               status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
197 +       } while (!(status & JZ_NAND_STATUS_ENC_FINISH));
198 +
199 +       reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
200 +       reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
201 +       writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
202 +
203 +       for (i = 0; i < 9; ++i)
204 +               ecc_code[i] = readb(nand->base + JZ_REG_NAND_PAR0 + i);
205 +
206 +       /* If the written data is completly 0xff, we also want to write 0xff as
207 +        * ecc, otherwise we will get in trouble when doing subpage writes. */
208 +       if (memcmp(ecc_code, empty_block_ecc, 9) == 0)
209 +               memset(ecc_code, 0xff, 9);
210 +
211 +       return 0;
212 +}
213 +
214 +/*#define printkd printk*/
215 +#define printkd(...)
216 +
217 +static void correct_data(uint8_t *dat, int index, int mask)
218 +{
219 +       int offset = index & 0x7;
220 +       uint16_t data;
221 +       printkd("correct: ");
222 +
223 +       index += (index >> 3);
224 +
225 +       data = dat[index];
226 +       data |= dat[index+1] << 8;
227 +
228 +       printkd("0x%x -> ", data);
229 +
230 +       mask ^= (data >> offset) & 0x1ff;
231 +       data &= ~(0x1ff << offset);
232 +       data |= (mask << offset);
233 +
234 +       printkd("0x%x\n", data);
235 +
236 +       dat[index] = data & 0xff;
237 +       dat[index+1] = (data >> 8) & 0xff;
238 +}
239 +
240 +static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
241 +                                 uint8_t *read_ecc, uint8_t *calc_ecc)
242 +{
243 +       struct jz_nand *nand = mtd_to_jz_nand(mtd);
244 +       int i, error_count, index;
245 +       uint32_t reg, status, error;
246 +       uint32_t t;
247 +
248 +       t = read_ecc[0];
249 +
250 +       if (t == 0xff) {
251 +               for (i = 1; i < 9; ++i)
252 +                       t &= read_ecc[i];
253 +
254 +               t &= dat[0];
255 +               t &= dat[nand->chip.ecc.size / 2];
256 +               t &= dat[nand->chip.ecc.size - 1];
257 +
258 +               if (t == 0xff) {
259 +                       for (i = 1; i < nand->chip.ecc.size - 1; ++i)
260 +                               t &= dat[i];
261 +                       if (t == 0xff)
262 +                               return 0;
263 +               }
264 +       }
265 +
266 +       for (i = 0; i < 9; ++i)
267 +               writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i);
268 +
269 +       reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
270 +       reg |= JZ_NAND_ECC_CTRL_PAR_READY;
271 +       writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
272 +
273 +       do {
274 +               status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
275 +       } while (!(status & JZ_NAND_STATUS_DEC_FINISH));
276 +
277 +       reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
278 +       reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
279 +       writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
280 +
281 +       if (status & JZ_NAND_STATUS_ERROR) {
282 +               if (status & JZ_NAND_STATUS_UNCOR_ERROR) {
283 +                       printkd("uncorrectable ecc:");
284 +                       for (i = 0; i < 9; ++i)
285 +                               printkd(" 0x%x", read_ecc[i]);
286 +                       printkd("\n");
287 +                       printkd("uncorrectable data:");
288 +                       for (i = 0; i < 32; ++i)
289 +                               printkd(" 0x%x", dat[i]);
290 +                       printkd("\n");
291 +                       return -1;
292 +               }
293 +
294 +               error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29;
295 +
296 +               printkd("error_count: %d %x\n", error_count, status);
297 +
298 +               for (i = 0; i < error_count; ++i) {
299 +                       error = readl(nand->base + JZ_REG_NAND_ERR(i));
300 +                       index = ((error >> 16) & 0x1ff) - 1;
301 +                       if (index >= 0 && index < 512)
302 +                               correct_data(dat, index, error & 0x1ff);
303 +               }
304 +
305 +               return error_count;
306 +       }
307 +
308 +       return 0;
309 +}
310 +
311 +
312 +
313 +#ifdef CONFIG_MTD_CMDLINE_PARTS
314 +static const char *part_probes[] = {"cmdline", NULL};
315 +#endif
316 +
317 +static int __devinit jz_nand_probe(struct platform_device *pdev)
318 +{
319 +       int ret;
320 +       struct jz_nand *nand;
321 +       struct nand_chip *chip;
322 +       struct mtd_info *mtd;
323 +       struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
324 +#ifdef CONFIG_MTD_PARTITIONS
325 +       struct mtd_partition *partition_info;
326 +       int num_partitions = 0;
327 +#endif
328 +
329 +       nand = kzalloc(sizeof(*nand), GFP_KERNEL);
330 +       if (!nand) {
331 +               dev_err(&pdev->dev, "Failed to allocate device structure.\n");
332 +               return -ENOMEM;
333 +       }
334 +
335 +       nand->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
336 +       if (!nand->mem) {
337 +               dev_err(&pdev->dev, "Failed to get platform mmio memory\n");
338 +               ret = -ENOENT;
339 +               goto err_free;
340 +       }
341 +
342 +       nand->mem = request_mem_region(nand->mem->start,
343 +                                       resource_size(nand->mem), pdev->name);
344 +
345 +       if (!nand->mem) {
346 +               dev_err(&pdev->dev, "Failed to request mmio memory region\n");
347 +               ret = -EBUSY;
348 +               goto err_free;
349 +       }
350 +
351 +       nand->base = ioremap(nand->mem->start, resource_size(nand->mem));
352 +
353 +       if (!nand->base) {
354 +               dev_err(&pdev->dev, "Failed to ioremap mmio memory region\n");
355 +               ret = -EBUSY;
356 +               goto err_release_mem;
357 +       }
358 +
359 +       if (pdata && gpio_is_valid(pdata->busy_gpio)) {
360 +               ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
361 +               if (ret) {
362 +                       dev_err(&pdev->dev,
363 +                               "Failed to request busy gpio %d: %d\n",
364 +                               pdata->busy_gpio, ret);
365 +                       goto err_iounmap;
366 +               }
367 +       }
368 +
369 +       mtd             = &nand->mtd;
370 +       chip            = &nand->chip;
371 +       mtd->priv       = chip;
372 +       mtd->owner      = THIS_MODULE;
373 +       mtd->name       = "jz4740-nand";
374 +
375 +       chip->ecc.hwctl         = jz_nand_hwctl;
376 +
377 +       chip->ecc.calculate     = jz_nand_calculate_ecc_rs;
378 +       chip->ecc.correct       = jz_nand_correct_ecc_rs;
379 +       chip->ecc.mode          = NAND_ECC_HW_OOB_FIRST;
380 +       chip->ecc.size          = 512;
381 +       chip->ecc.bytes         = 9;
382 +       if (pdata)
383 +               chip->ecc.layout = pdata->ecc_layout;
384 +
385 +       chip->chip_delay = 50;
386 +       chip->cmd_ctrl = jz_nand_cmd_ctrl;
387 +
388 +       if (pdata && gpio_is_valid(pdata->busy_gpio))
389 +               chip->dev_ready = jz_nand_dev_ready;
390 +
391 +       chip->IO_ADDR_R = JZ_NAND_DATA_ADDR;
392 +       chip->IO_ADDR_W = JZ_NAND_DATA_ADDR;
393 +
394 +       nand->pdata = pdata;
395 +       platform_set_drvdata(pdev, nand);
396 +
397 +       ret = nand_scan_ident(mtd, 1);
398 +       if (ret) {
399 +               dev_err(&pdev->dev,  "Failed to scan nand\n");
400 +               goto err_gpio_free;
401 +       }
402 +
403 +       if (pdata && pdata->ident_callback) {
404 +               pdata->ident_callback(pdev, chip, &pdata->partitions,
405 +                                       &pdata->num_partitions);
406 +       }
407 +
408 +       ret = nand_scan_tail(mtd);
409 +       if (ret) {
410 +               dev_err(&pdev->dev,  "Failed to scan nand\n");
411 +               goto err_gpio_free;
412 +       }
413 +
414 +#ifdef CONFIG_MTD_PARTITIONS
415 +#ifdef CONFIG_MTD_CMDLINE_PARTS
416 +       num_partitions = parse_mtd_partitions(mtd, part_probes,
417 +                                               &partition_info, 0);
418 +#endif
419 +       if (num_partitions <= 0 && pdata) {
420 +               num_partitions = pdata->num_partitions;
421 +               partition_info = pdata->partitions;
422 +       }
423 +
424 +       if (num_partitions > 0)
425 +               ret = add_mtd_partitions(mtd, partition_info, num_partitions);
426 +       else
427 +#endif
428 +       ret = add_mtd_device(mtd);
429 +
430 +       if (ret) {
431 +               dev_err(&pdev->dev, "Failed to add mtd device\n");
432 +               goto err_nand_release;
433 +       }
434 +
435 +       dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n");
436 +
437 +       return 0;
438 +err_nand_release:
439 +       nand_release(&nand->mtd);
440 +err_gpio_free:
441 +       platform_set_drvdata(pdev, NULL);
442 +       gpio_free(pdata->busy_gpio);
443 +err_iounmap:
444 +       iounmap(nand->base);
445 +err_release_mem:
446 +       release_mem_region(nand->mem->start, resource_size(nand->mem));
447 +err_free:
448 +       kfree(nand);
449 +       return ret;
450 +}
451 +
452 +static void __devexit jz_nand_remove(struct platform_device *pdev)
453 +{
454 +       struct jz_nand *nand = platform_get_drvdata(pdev);
455 +
456 +       nand_release(&nand->mtd);
457 +
458 +       iounmap(nand->base);
459 +
460 +       release_mem_region(nand->mem->start, resource_size(nand->mem));
461 +
462 +       platform_set_drvdata(pdev, NULL);
463 +       kfree(nand);
464 +}
465 +
466 +struct platform_driver jz_nand_driver = {
467 +       .probe = jz_nand_probe,
468 +       .remove = __devexit_p(jz_nand_probe),
469 +       .driver = {
470 +               .name = "jz4740-nand",
471 +               .owner = THIS_MODULE,
472 +       },
473 +};
474 +
475 +static int __init jz_nand_init(void)
476 +{
477 +       return platform_driver_register(&jz_nand_driver);
478 +}
479 +module_init(jz_nand_init);
480 +
481 +static void __exit jz_nand_exit(void)
482 +{
483 +       platform_driver_unregister(&jz_nand_driver);
484 +}
485 +module_exit(jz_nand_exit);
486 +
487 +MODULE_LICENSE("GPL");
488 +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
489 +MODULE_DESCRIPTION("NAND controller driver for JZ4720/JZ4740 SoC");
490 +MODULE_ALIAS("platform:jz4740-nand");
491 +MODULE_ALIAS("platform:jz4720-nand");
492 diff --git a/include/linux/mtd/jz4740_nand.h b/include/linux/mtd/jz4740_nand.h
493 new file mode 100644
494 index 0000000..8254e4c
495 --- /dev/null
496 +++ b/include/linux/mtd/jz4740_nand.h
497 @@ -0,0 +1,34 @@
498 +/*
499 + *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
500 + *      JZ4720/JZ4740 SoC NAND controller driver
501 + *
502 + *  This program is free software; you can redistribute         it and/or modify it
503 + *  under  the terms of         the GNU General  Public License as published by the
504 + *  Free Software Foundation;  either version 2 of the License, or (at your
505 + *  option) any later version.
506 + *
507 + *  You should have received a copy of the  GNU General Public License along
508 + *  with this program; if not, write  to the Free Software Foundation, Inc.,
509 + *  675 Mass Ave, Cambridge, MA 02139, USA.
510 + *
511 + */
512 +
513 +#ifndef __JZ_NAND_H__
514 +#define __JZ_NAND_H__
515 +
516 +#include <linux/mtd/nand.h>
517 +#include <linux/mtd/partitions.h>
518 +
519 +struct jz_nand_platform_data {
520 +       int                     num_partitions;
521 +       struct mtd_partition    *partitions;
522 +
523 +       struct nand_ecclayout   *ecc_layout;
524 +
525 +       unsigned int busy_gpio;
526 +
527 +       void (*ident_callback)(struct platform_device *, struct nand_chip *,
528 +                               struct mtd_partition **, int *num_partitions);
529 +};
530 +
531 +#endif
532 diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
533 index be51ae2..cf90168 100644
534 --- a/include/mtd/mtd-abi.h
535 +++ b/include/mtd/mtd-abi.h
536 @@ -134,7 +134,7 @@ struct nand_oobfree {
537   */
538  struct nand_ecclayout {
539         __u32 eccbytes;
540 -       __u32 eccpos[64];
541 +       __u32 eccpos[72];
542         __u32 oobavail;
543         struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
544  };
545 -- 
546 1.5.6.5
547