kernel: update bcma and ssb to master-2012-10-18 from wireless-testing
[openwrt.git] / target / linux / brcm47xx / patches-3.3 / 053-mtd-add-nand-flash-driver.patch
1 --- a/drivers/mtd/nand/Kconfig
2 +++ b/drivers/mtd/nand/Kconfig
3 @@ -536,4 +536,12 @@ config MTD_NAND_FSMC
4           Enables support for NAND Flash chips on the ST Microelectronics
5           Flexible Static Memory Controller (FSMC)
6  
7 +config MTD_NAND_BCM47XX
8 +       tristate "bcm47xx nand flash support"
9 +       default y
10 +       depends on BCM47XX && BCMA_NFLASH
11 +       select MTD_PARTITIONS
12 +       help
13 +         Support for bcm47xx nand flash
14 +
15  endif # MTD_NAND
16 --- a/drivers/mtd/nand/Makefile
17 +++ b/drivers/mtd/nand/Makefile
18 @@ -49,5 +49,6 @@ obj-$(CONFIG_MTD_NAND_MPC5121_NFC)    += mp
19  obj-$(CONFIG_MTD_NAND_RICOH)           += r852.o
20  obj-$(CONFIG_MTD_NAND_JZ4740)          += jz4740_nand.o
21  obj-$(CONFIG_MTD_NAND_GPMI_NAND)       += gpmi-nand/
22 +obj-$(CONFIG_MTD_NAND_BCM47XX)         += bcm47xx_nand.o
23  
24  nand-objs := nand_base.o nand_bbt.o
25 --- /dev/null
26 +++ b/drivers/mtd/nand/bcm47xx_nand.c
27 @@ -0,0 +1,528 @@
28 +/*
29 + * BCMA nand flash interface
30 + *
31 + * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
32 + * Copyright 2010, Broadcom Corporation
33 + *
34 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
35 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
36 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
37 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
38 + *
39 + */
40 +
41 +#define pr_fmt(fmt) "bcm47xx_nflash: " fmt
42 +#include <linux/module.h>
43 +#include <linux/slab.h>
44 +#include <linux/ioport.h>
45 +#include <linux/sched.h>
46 +#include <linux/mtd/mtd.h>
47 +#include <linux/mtd/map.h>
48 +#include <linux/mtd/partitions.h>
49 +#include <linux/errno.h>
50 +#include <linux/delay.h>
51 +#include <linux/platform_device.h>
52 +#include <bcm47xx.h>
53 +#include <linux/cramfs_fs.h>
54 +#include <linux/romfs_fs.h>
55 +#include <linux/magic.h>
56 +#include <linux/byteorder/generic.h>
57 +#include <linux/mtd/bcm47xx_nand.h>
58 +#include <linux/mtd/nand.h>
59 +
60 +static int bcm47xx_nflash_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip);
61 +static int bcm47xx_nflash_erase(struct mtd_info *mtd, unsigned int addr, unsigned int len);
62 +
63 +/* Private Global variable */
64 +static u32 read_offset = 0;
65 +static u32 write_offset;
66 +
67 +static int
68 +nflash_mtd_poll(struct bcm47xx_nflash *nflash, unsigned int offset, int timeout)
69 +{
70 +       unsigned long now = jiffies;
71 +       int ret = 0;
72 +
73 +       for (;;) {
74 +               if (!bcma_nflash_poll(nflash->bcc)) {
75 +                       ret = 0;
76 +                       break;
77 +               }
78 +               if (time_after(jiffies, now + timeout)) {
79 +                       pr_err("timeout while polling\n");
80 +                       ret = -ETIMEDOUT;
81 +                       break;
82 +               }
83 +               udelay(1);
84 +       }
85 +
86 +       return ret;
87 +}
88 +
89 +static int
90 +bcm47xx_nflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
91 +{
92 +       struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
93 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
94 +       int bytes, ret = 0;
95 +       u32 extra = 0;
96 +       u8 *tmpbuf = NULL;
97 +       int size;
98 +       u32 offset, blocksize, mask, off;
99 +       u32 skip_bytes = 0;
100 +       int need_copy = 0;
101 +       u8 *ptr = NULL;
102 +
103 +       /* Check address range */
104 +       if (!len)
105 +               return 0;
106 +       if ((from + len) > mtd->size)
107 +               return -EINVAL;
108 +       offset = from;
109 +       if ((offset & (NFL_SECTOR_SIZE - 1)) != 0) {
110 +               extra = offset & (NFL_SECTOR_SIZE - 1);
111 +               offset -= extra;
112 +               len += extra;
113 +               need_copy = 1;
114 +       }
115 +       size = (len + (NFL_SECTOR_SIZE - 1)) & ~(NFL_SECTOR_SIZE - 1);
116 +       if (size != len) {
117 +               need_copy = 1;
118 +       }
119 +       if (!need_copy) {
120 +               ptr = buf;
121 +       } else {
122 +               tmpbuf = (u8 *)kmalloc(size, GFP_KERNEL);
123 +               ptr = tmpbuf;
124 +       }
125 +
126 +       blocksize = mtd->erasesize;
127 +       mask = blocksize - 1;
128 +       *retlen = 0;
129 +       while (len > 0) {
130 +               off = offset + skip_bytes;
131 +               if ((bytes = bcma_nflash_read(nflash->bcc, off, NFL_SECTOR_SIZE, ptr)) < 0) {
132 +                       ret = bytes;
133 +                       goto done;
134 +               }
135 +               if (bytes > len)
136 +                       bytes = len;
137 +               offset += bytes;
138 +               len -= bytes;
139 +               ptr += bytes;
140 +               *retlen += bytes;
141 +       }
142 +
143 +done:
144 +       if (tmpbuf) {
145 +               *retlen -= extra;
146 +               memcpy(buf, tmpbuf+extra, *retlen);
147 +               kfree(tmpbuf);
148 +       }
149 +
150 +       return ret;
151 +}
152 +
153 +static void bcm47xx_nflash_write(struct mtd_info *mtd, u32 to, const u_char *buf, u32 len)
154 +{
155 +       struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
156 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
157 +       u32 offset, blocksize, mask, off;
158 +       int read_len;
159 +       u32 copy_len, write_len, from;
160 +       u_char *write_ptr, *block;
161 +       const u_char *ptr;
162 +       int ret, bytes;
163 +
164 +       /* Check address range */
165 +       if (!len) {
166 +               pr_err("Error: Attempted to write too small data\n");
167 +               return;
168 +       }
169 +
170 +       if (!to)
171 +               return;
172 +
173 +       if ((to + len) > mtd->size) {
174 +               pr_err("Error: Attempted to write too large data\n");
175 +               return;
176 +       }
177 +
178 +       ptr = buf;
179 +       block = NULL;
180 +       offset = to;
181 +       blocksize = mtd->erasesize;
182 +       if (!(block = kmalloc(blocksize, GFP_KERNEL)))
183 +               return;
184 +       mask = blocksize - 1;
185 +       while (len) {
186 +               /* Align offset */
187 +               from = offset & ~mask;
188 +               /* Copy existing data into holding block if necessary */
189 +               if (((offset & (blocksize-1)) != 0) || (len < blocksize)) {
190 +                       if ((ret = bcm47xx_nflash_read(mtd, from, blocksize, &read_len, block)))
191 +                               goto done;
192 +                       if (read_len != blocksize) {
193 +                               ret = -EINVAL;
194 +                               goto done;
195 +                       }
196 +               }
197 +
198 +               /* Copy input data into holding block */
199 +               copy_len = min(len, blocksize - (offset & mask));
200 +               memcpy(block + (offset & mask), ptr, copy_len);
201 +               off = (uint) from;
202 +               /* Erase block */
203 +               if ((ret = bcm47xx_nflash_erase(mtd, off, blocksize)) < 0)
204 +                       goto done;
205 +               /* Write holding block */
206 +               write_ptr = block;
207 +               write_len = blocksize;
208 +               if ((bytes = bcma_nflash_write(nflash->bcc, (uint)from, (uint)write_len, (u8 *) write_ptr)) != 0) {
209 +                       ret = bytes;
210 +                       goto done;
211 +               }
212 +               offset += copy_len;
213 +               if (len < copy_len)
214 +                       len = 0;
215 +               else
216 +                       len -= copy_len;
217 +               ptr += copy_len;
218 +       }
219 +
220 +done:
221 +       if (block)
222 +               kfree(block);
223 +       return;
224 +}
225 +
226 +static int bcm47xx_nflash_erase(struct mtd_info *mtd, unsigned int addr, unsigned int len)
227 +{
228 +       struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
229 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
230 +
231 +       /* Check address range */
232 +       if (!len)
233 +               return 1;
234 +       if ((addr + len) > mtd->size)
235 +               return 1;
236 +
237 +       if (bcma_nflash_erase(nflash->bcc, addr)) {
238 +               pr_err("ERASE: nflash erase error\n");
239 +               return 1;
240 +       }
241 +
242 +       if (nflash_mtd_poll(nflash, addr, 10 * HZ)) {
243 +               pr_err("ERASE: nflash_mtd_poll error\n");
244 +               return 1;
245 +       }
246 +
247 +       return 0;
248 +}
249 +
250 +/* This functions is used by upper layer to checks if device is ready */
251 +static int bcm47xx_nflash_dev_ready(struct mtd_info *mtd)
252 +{
253 +       return 1;
254 +}
255 +
256 +/* Issue a nand flash command */
257 +static inline void bcm47xx_nflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
258 +{
259 +       bcma_cc_write32(cc, NAND_CMD_START, opcode);
260 +       bcma_cc_read32(cc,  NAND_CMD_START);
261 +}
262 +
263 +static void bcm47xx_nflash_command(struct mtd_info *mtd, unsigned command,
264 +                               int column, int page_addr)
265 +{
266 +       struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
267 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
268 +       u32 pagesize = 1 << nchip->page_shift;
269 +
270 +       /* Command pre-processing step */
271 +       switch (command) {
272 +       case NAND_CMD_RESET:
273 +               bcm47xx_nflash_cmd(nflash->bcc, NCMD_FLASH_RESET);
274 +               break;
275 +
276 +       case NAND_CMD_STATUS:
277 +               nflash->next_opcode = NAND_CMD_STATUS;
278 +               read_offset = 0;
279 +               write_offset = 0;
280 +               break;
281 +
282 +       case NAND_CMD_READ0:
283 +               read_offset = page_addr * pagesize;
284 +               nflash->next_opcode = 0;
285 +               break;
286 +
287 +       case NAND_CMD_READOOB:
288 +               read_offset = page_addr * pagesize;
289 +               nflash->next_opcode = 0;
290 +               break;
291 +
292 +       case NAND_CMD_SEQIN:
293 +               write_offset = page_addr * pagesize;
294 +               nflash->next_opcode = 0;
295 +               break;
296 +
297 +       case NAND_CMD_PAGEPROG:
298 +               nflash->next_opcode = 0;
299 +               break;
300 +
301 +       case NAND_CMD_READID:
302 +               read_offset = column;
303 +               bcm47xx_nflash_cmd(nflash->bcc, NCMD_ID_RD);
304 +               nflash->next_opcode = NAND_DEVID;
305 +               break;
306 +
307 +       case NAND_CMD_ERASE1:
308 +               nflash->next_opcode = 0;
309 +               bcm47xx_nflash_erase(mtd, page_addr*pagesize, pagesize);
310 +               break;
311 +
312 +       case NAND_CMD_ERASE2:
313 +               break;
314 +
315 +       case NAND_CMD_RNDOUT:
316 +               if (column > mtd->writesize)
317 +                       read_offset += (column - mtd->writesize);
318 +               else
319 +                       read_offset += column;
320 +               break;
321 +
322 +       default:
323 +               pr_err("COMMAND not supported %x\n", command);
324 +               nflash->next_opcode = 0;
325 +               break;
326 +       }
327 +}
328 +
329 +/* This function is used by upper layer for select and
330 + * deselect of the NAND chip.
331 + * It is dummy function. */
332 +static void bcm47xx_nflash_select_chip(struct mtd_info *mtd, int chip)
333 +{
334 +}
335 +
336 +static u_char bcm47xx_nflash_read_byte(struct mtd_info *mtd)
337 +{
338 +       struct nand_chip *nchip = mtd->priv;
339 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
340 +       uint8_t ret = 0;
341 +       static u32 id;
342 +
343 +       if (nflash->next_opcode == 0)
344 +               return ret;
345 +
346 +       if (nflash->next_opcode == NAND_CMD_STATUS)
347 +               return NAND_STATUS_WP;
348 +
349 +       id = bcma_cc_read32(nflash->bcc, nflash->next_opcode);
350 +
351 +       if (nflash->next_opcode == NAND_DEVID) {
352 +               ret = (id >> (8*read_offset)) & 0xff;
353 +               read_offset++;
354 +       }
355 +
356 +       return ret;
357 +}
358 +
359 +static uint16_t bcm47xx_nflash_read_word(struct mtd_info *mtd)
360 +{
361 +       loff_t from = read_offset;
362 +       uint16_t buf = 0;
363 +       int bytes;
364 +
365 +       bcm47xx_nflash_read(mtd, from, sizeof(buf), &bytes, (u_char *)&buf);
366 +       return buf;
367 +}
368 +
369 +/* Write data of length len to buffer buf. The data to be
370 + * written on NAND Flash is first copied to RAMbuffer. After the Data Input
371 + * Operation by the NFC, the data is written to NAND Flash */
372 +static void bcm47xx_nflash_write_buf(struct mtd_info *mtd,
373 +                               const u_char *buf, int len)
374 +{
375 +       bcm47xx_nflash_write(mtd, write_offset, buf, len);
376 +}
377 +
378 +/* Read the data buffer from the NAND Flash. To read the data from NAND
379 + * Flash first the data output cycle is initiated by the NFC, which copies
380 + * the data to RAMbuffer. This data of length len is then copied to buffer buf.
381 + */
382 +static void bcm47xx_nflash_read_buf(struct mtd_info *mtd, u_char *buf, int len)
383 +{
384 +       loff_t from = read_offset;
385 +       int bytes;
386 +
387 +       bcm47xx_nflash_read(mtd, from, len, &bytes, buf);
388 +}
389 +
390 +/* Used by the upper layer to verify the data in NAND Flash
391 + * with the data in the buf. */
392 +static int bcm47xx_nflash_verify_buf(struct mtd_info *mtd,
393 +                               const u_char *buf, int len)
394 +{
395 +       return -EFAULT;
396 +}
397 +
398 +static int bcm47xx_nflash_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
399 +{
400 +       struct nand_chip *nchip = mtd->priv;
401 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
402 +       int i;
403 +       uint off;
404 +       u32 pagesize = 1 << nchip->page_shift;
405 +       u32 blocksize = mtd->erasesize;
406 +
407 +       if ((ofs >> 20) >= nflash->size)
408 +               return 1;
409 +       if ((ofs & (blocksize - 1)) != 0)
410 +               return 1;
411 +
412 +       for (i = 0; i < 2; i++) {
413 +               off = ofs + pagesize;
414 +               bcma_cc_write32(nflash->bcc, NAND_CMD_ADDR, off);
415 +               bcm47xx_nflash_cmd(nflash->bcc, NCMD_SPARE_RD);
416 +               if (bcma_nflash_poll(nflash->bcc) < 0)
417 +                       break;
418 +               if ((bcma_cc_read32(nflash->bcc, NAND_INTFC_STATUS) & NIST_SPARE_VALID) != NIST_SPARE_VALID)
419 +                       return 1;
420 +               if ((bcma_cc_read32(nflash->bcc, NAND_SPARE_RD0) & 0xff) != 0xff)
421 +                       return 1;
422 +       }
423 +       return 0;
424 +}
425 +
426 +const char *part_probes[] = { "cmdlinepart", NULL };
427 +static int bcm47xx_nflash_probe(struct platform_device *pdev)
428 +{
429 +       struct nand_chip *nchip;
430 +       struct mtd_info *mtd;
431 +       struct bcm47xx_nflash *nflash = dev_get_platdata(&pdev->dev);
432 +       int ret = 0;
433 +
434 +       mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
435 +       if (!mtd){
436 +               ret = -ENOMEM;
437 +               goto err_out;
438 +       }
439 +
440 +       nchip = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
441 +       if (!nchip) {
442 +               ret = -ENOMEM;
443 +               goto err_free_mtd;
444 +       }
445 +
446 +       /* Register with MTD */
447 +       mtd->priv = nchip;
448 +       mtd->owner = THIS_MODULE;
449 +       mtd->dev.parent = &pdev->dev;
450 +
451 +       /* 50 us command delay time */
452 +       nchip->chip_delay = 50;
453 +
454 +       nchip->priv = nflash;
455 +       nchip->dev_ready = bcm47xx_nflash_dev_ready;
456 +       nchip->cmdfunc = bcm47xx_nflash_command;
457 +       nchip->select_chip = bcm47xx_nflash_select_chip;
458 +       nchip->read_byte = bcm47xx_nflash_read_byte;
459 +       nchip->read_word = bcm47xx_nflash_read_word;
460 +       nchip->write_buf = bcm47xx_nflash_write_buf;
461 +       nchip->read_buf = bcm47xx_nflash_read_buf;
462 +       nchip->verify_buf = bcm47xx_nflash_verify_buf;
463 +       nchip->block_bad = bcm47xx_nflash_block_bad;
464 +       nchip->options = NAND_SKIP_BBTSCAN;
465 +
466 +       /* Not known */
467 +       nchip->ecc.mode = NAND_ECC_NONE;
468 +
469 +       /* first scan to find the device and get the page size */
470 +       if (nand_scan_ident(mtd, 1, NULL)) {
471 +               pr_err("nand_scan_ident failed\n");
472 +               ret = -ENXIO;
473 +               goto err_free_nchip;
474 +       }
475 +       nflash->size = mtd->size;
476 +       nflash->pagesize = 1 << nchip->page_shift;
477 +       nflash->blocksize = mtd->erasesize;
478 +       nflash->mtd = mtd;
479 +
480 +       /* second phase scan */
481 +       if (nand_scan_tail(mtd)) {
482 +               pr_err("nand_scan_tail failed\n");
483 +               ret = -ENXIO;
484 +               goto err_free_nchip;
485 +       }
486 +
487 +       mtd->name = "bcm47xx-nflash";
488 +       mtd->flags |= MTD_WRITEABLE;
489 +       ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL, 0);
490 +
491 +       if (ret) {
492 +               pr_err("mtd_device_register failed\n");
493 +               goto err_free_nchip;
494 +       }
495 +
496 +       return 0;
497 +
498 +err_free_nchip:
499 +       kfree(nchip);
500 +err_free_mtd:
501 +       kfree(mtd);
502 +err_out:
503 +       return ret;
504 +}
505 +
506 +static int __devexit bcm47xx_nflash_remove(struct platform_device *pdev)
507 +{
508 +       struct bcm47xx_nflash *nflash = dev_get_platdata(&pdev->dev);
509 +       struct mtd_info *mtd = nflash->mtd;
510 +
511 +       if (nflash) {
512 +               /* Release resources, unregister device */
513 +               nand_release(mtd);
514 +               kfree(mtd->priv);
515 +               kfree(mtd);
516 +       }
517 +
518 +       return 0;
519 +}
520 +
521 +static const struct platform_device_id bcm47xx_nflash_table[] = {
522 +       { "bcm47xx-nflash", 0 },
523 +       { }
524 +};
525 +MODULE_DEVICE_TABLE(platform, bcm47xx_nflash_table);
526 +
527 +static struct platform_driver bcm47xx_nflash_driver = {
528 +       .id_table       = bcm47xx_nflash_table,
529 +       .probe  = bcm47xx_nflash_probe,
530 +       .remove = __devexit_p(bcm47xx_nflash_remove),
531 +       .driver = {
532 +               .name = "bcm47xx-nflash",
533 +               .owner = THIS_MODULE,
534 +       },
535 +};
536 +
537 +static int __init init_bcm47xx_nflash(void)
538 +{
539 +       int ret = platform_driver_register(&bcm47xx_nflash_driver);
540 +
541 +       if (ret)
542 +               pr_err("error registering platform driver: %i\n", ret);
543 +       return ret;
544 +}
545 +
546 +static void __exit exit_bcm47xx_nflash(void)
547 +{
548 +       platform_driver_unregister(&bcm47xx_nflash_driver);
549 +}
550 +
551 +module_init(init_bcm47xx_nflash);
552 +module_exit(exit_bcm47xx_nflash);
553 +
554 +MODULE_LICENSE("GPL");
555 +MODULE_DESCRIPTION("BCM47XX NAND flash driver");
556 --- /dev/null
557 +++ b/include/linux/mtd/bcm47xx_nand.h
558 @@ -0,0 +1,152 @@
559 +/*
560 + * Broadcom chipcommon NAND flash interface
561 + *
562 + * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
563 + * Copyright (C) 2009, Broadcom Corporation
564 + * All Rights Reserved.
565 + *
566 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
567 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
568 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
569 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
570 + *
571 + */
572 +
573 +#ifndef LINUX_MTD_BCM47XX_NAND_H_
574 +#define LINUX_MTD_BCM47XX_NAND_H_
575 +
576 +#include <linux/mtd/mtd.h>
577 +
578 +#define  NAND_FLASH1                                           0x1fc00000  /* MIPS Flash Region 1 */
579 +
580 +/* nand_cmd_start commands */
581 +#define        NCMD_NULL                                               0
582 +#define        NCMD_PAGE_RD                                    1
583 +#define        NCMD_SPARE_RD                                   2
584 +#define        NCMD_STATUS_RD                                  3
585 +#define        NCMD_PAGE_PROG                                  4
586 +#define        NCMD_SPARE_PROG                         5
587 +#define        NCMD_COPY_BACK                                  6
588 +#define        NCMD_ID_RD                                              7
589 +#define        NCMD_BLOCK_ERASE                                8
590 +#define        NCMD_FLASH_RESET                                9
591 +#define        NCMD_LOCK                                               0xa
592 +#define        NCMD_LOCK_DOWN                                  0xb
593 +#define        NCMD_UNLOCK                                             0xc
594 +#define        NCMD_LOCK_STATUS                                0xd
595 +
596 +/* nand_acc_control */
597 +#define        NAC_RD_ECC_EN                                   0x80000000
598 +#define        NAC_WR_ECC_EN                                   0x40000000
599 +#define        NAC_RD_ECC_BLK0_EN                      0x20000000
600 +#define        NAC_FAST_PGM_RDIN                               0x10000000
601 +#define        NAC_RD_ERASED_ECC_EN                    0x08000000
602 +#define        NAC_PARTIAL_PAGE_EN                     0x04000000
603 +#define        NAC_PAGE_HIT_EN                         0x01000000
604 +#define        NAC_ECC_LEVEL0                                  0x00f00000
605 +#define        NAC_ECC_LEVEL                                   0x000f0000
606 +#define        NAC_SPARE_SIZE0                         0x00003f00
607 +#define        NAC_SPARE_SIZE                                  0x0000003f
608 +
609 +/* nand_config */
610 +#define        NCF_CONFIG_LOCK                         0x80000000
611 +#define        NCF_BLOCK_SIZE_MASK                     0x70000000
612 +#define        NCF_BLOCK_SIZE_SHIFT                    28
613 +#define        NCF_DEVICE_SIZE_MASK                    0x0f000000
614 +#define        NCF_DEVICE_SIZE_SHIFT           24
615 +#define        NCF_DEVICE_WIDTH                                0x00800000
616 +#define        NCF_PAGE_SIZE_MASK                      0x00300000
617 +#define        NCF_PAGE_SIZE_SHIFT                     20
618 +#define        NCF_FULL_ADDR_BYTES_MASK        0x00070000
619 +#define        NCF_FULL_ADDR_BYTES_SHIFT       16
620 +#define        NCF_COL_ADDR_BYTES_MASK         0x00007000
621 +#define        NCF_COL_ADDR_BYTES_SHIFT        12
622 +#define        NCF_BLK_ADDR_BYTES_MASK         0x00000700
623 +#define        NCF_BLK_ADDR_BYTES_SHIFT        8
624 +
625 +/* nand_intfc_status */
626 +#define        NIST_CTRL_READY                         0x80000000
627 +#define        NIST_FLASH_READY                                0x40000000
628 +#define        NIST_CACHE_VALID                                0x20000000
629 +#define        NIST_SPARE_VALID                                0x10000000
630 +#define        NIST_ERASED                                             0x08000000
631 +#define        NIST_STATUS                                             0x000000ff
632 +
633 +#define        NFL_SECTOR_SIZE                         512
634 +
635 +#define        NFL_TABLE_END                                   0xffffffff
636 +#define        NFL_BOOT_SIZE                                   0x200000
637 +#define        NFL_BOOT_OS_SIZE                                0x2000000
638 +
639 +/* Nand flash MLC controller registers (corerev >= 38) */
640 +#define        NAND_REVISION                                   0xC00
641 +#define        NAND_CMD_START                                  0xC04
642 +#define        NAND_CMD_ADDR_X                         0xC08
643 +#define        NAND_CMD_ADDR                                   0xC0C
644 +#define        NAND_CMD_END_ADDR                               0xC10
645 +#define        NAND_CS_NAND_SELECT                     0xC14
646 +#define        NAND_CS_NAND_XOR                                0xC18
647 +#define        NAND_SPARE_RD0                                  0xC20
648 +#define        NAND_SPARE_RD4                                  0xC24
649 +#define        NAND_SPARE_RD8                                  0xC28
650 +#define        NAND_SPARE_RD12                         0xC2C
651 +#define        NAND_SPARE_WR0                                  0xC30
652 +#define        NAND_SPARE_WR4                                  0xC34
653 +#define        NAND_SPARE_WR8                                  0xC38
654 +#define        NAND_SPARE_WR12                         0xC3C
655 +#define        NAND_ACC_CONTROL                                0xC40
656 +#define        NAND_CONFIG                                             0xC48
657 +#define        NAND_TIMING_1                                   0xC50
658 +#define        NAND_TIMING_2                                   0xC54
659 +#define        NAND_SEMAPHORE                                  0xC58
660 +#define        NAND_DEVID                                              0xC60
661 +#define        NAND_DEVID_X                                    0xC64
662 +#define        NAND_BLOCK_LOCK_STATUS          0xC68
663 +#define        NAND_INTFC_STATUS                               0xC6C
664 +#define        NAND_ECC_CORR_ADDR_X                    0xC70
665 +#define        NAND_ECC_CORR_ADDR                      0xC74
666 +#define        NAND_ECC_UNC_ADDR_X                     0xC78
667 +#define        NAND_ECC_UNC_ADDR                               0xC7C
668 +#define        NAND_READ_ERROR_COUNT           0xC80
669 +#define        NAND_CORR_STAT_THRESHOLD        0xC84
670 +#define        NAND_READ_ADDR_X                                0xC90
671 +#define        NAND_READ_ADDR                                  0xC94
672 +#define        NAND_PAGE_PROGRAM_ADDR_X        0xC98
673 +#define        NAND_PAGE_PROGRAM_ADDR          0xC9C
674 +#define        NAND_COPY_BACK_ADDR_X           0xCA0
675 +#define        NAND_COPY_BACK_ADDR                     0xCA4
676 +#define        NAND_BLOCK_ERASE_ADDR_X         0xCA8
677 +#define        NAND_BLOCK_ERASE_ADDR           0xCAC
678 +#define        NAND_INV_READ_ADDR_X                    0xCB0
679 +#define        NAND_INV_READ_ADDR                      0xCB4
680 +#define        NAND_BLK_WR_PROTECT                     0xCC0
681 +#define        NAND_ACC_CONTROL_CS1                    0xCD0
682 +#define        NAND_CONFIG_CS1                         0xCD4
683 +#define        NAND_TIMING_1_CS1                               0xCD8
684 +#define        NAND_TIMING_2_CS1                               0xCDC
685 +#define        NAND_SPARE_RD16                         0xD30
686 +#define        NAND_SPARE_RD20                         0xD34
687 +#define        NAND_SPARE_RD24                         0xD38
688 +#define        NAND_SPARE_RD28                         0xD3C
689 +#define        NAND_CACHE_ADDR                         0xD40
690 +#define        NAND_CACHE_DATA                         0xD44
691 +#define        NAND_CTRL_CONFIG                                0xD48
692 +#define        NAND_CTRL_STATUS                                0xD4C
693 +
694 +struct bcma_drv_cc;
695 +
696 +struct bcm47xx_nflash {
697 +       struct bcma_drv_cc *bcc;
698 +
699 +       bool present;
700 +       bool boot;              /* This is the flash the SoC boots from */
701 +       u32 blocksize;          /* Block size */
702 +       u32 pagesize;           /* Page size */
703 +
704 +       u32 size;               /* Total size in bytes */
705 +       u32 next_opcode; /* Next expected command from upper NAND layer */
706 +
707 +       struct mtd_info *mtd;
708 +};
709 +
710 +#endif /* LINUX_MTD_BCM47XX_NAND_H_ */