7635d424ded01e887bdf4fd8d4ded958688f6f16
[openwrt/staging/yousong.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_ */