brcm47xx: add support for NAND flash on devices using bcma
[librecmc/librecmc.git] / target / linux / brcm47xx / patches-3.2 / 030-bcm47xx-bcma-nandflash.patch
1 --- a/arch/mips/bcm47xx/bus.c
2 +++ b/arch/mips/bcm47xx/bus.c
3 @@ -2,6 +2,7 @@
4   * BCM947xx nvram variable access
5   *
6   * Copyright (C) 2011 Hauke Mehrtens <hauke@hauke-m.de>
7 + * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
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 @@ -92,3 +93,9 @@ void bcm47xx_sflash_struct_ssb_init(stru
12         sflash->numblocks = scc->sflash.numblocks;
13         sflash->size = scc->sflash.size;
14  }
15 +
16 +void bcm47xx_nflash_struct_bcma_init(struct bcm47xx_nflash *nflash, struct bcma_drv_cc *bcc)
17 +{
18 +       nflash->nflash_type = BCM47XX_BUS_TYPE_BCMA;
19 +       nflash->bcc = bcc;
20 +}
21 --- a/arch/mips/bcm47xx/nvram.c
22 +++ b/arch/mips/bcm47xx/nvram.c
23 @@ -4,6 +4,7 @@
24   * Copyright (C) 2005 Broadcom Corporation
25   * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
26   * Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
27 + * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
28   *
29   * This program is free software; you can redistribute  it and/or modify it
30   * under  the terms of  the GNU General  Public License as published by the
31 @@ -21,6 +22,7 @@
32  #include <asm/mach-bcm47xx/nvram.h>
33  #include <asm/mach-bcm47xx/bcm47xx.h>
34  #include <asm/mach-bcm47xx/bus.h>
35 +#include <linux/mtd/bcm47xx_nand.h>
36  
37  static char nvram_buf[NVRAM_SPACE];
38  
39 @@ -137,6 +139,51 @@ found:
40         return 0;
41  }
42  
43 +static int early_nvram_init_nflash(void)
44 +{
45 +       struct nvram_header *header;
46 +       u32 off;
47 +       int ret;
48 +       int len;
49 +       u32 flash_size = bcm47xx_nflash.size;
50 +       u8 tmpbuf[NFL_SECTOR_SIZE];
51 +       int i;
52 +       u32 *src, *dst;
53 +
54 +       /* check if the struct is already initilized */
55 +       if (!flash_size)
56 +               return -1;
57 +       
58 +       cfe_env = 0;
59 +
60 +       off = FLASH_MIN;
61 +       while (off <= flash_size) {
62 +               ret = bcma_nflash_read(bcm47xx_nflash.bcc, off, NFL_SECTOR_SIZE, tmpbuf);
63 +               if (ret != NFL_SECTOR_SIZE)
64 +                       goto done;
65 +               header = (struct nvram_header *)tmpbuf;
66 +               if (header->magic == NVRAM_HEADER)
67 +                       goto found;
68 +               off <<= 1;
69 +       }
70 +
71 +       ret = -1;
72 +       goto done;
73 +
74 +found:
75 +       len = header->len;
76 +       header = (struct nvram_header *) KSEG1ADDR(NAND_FLASH1 + off);
77 +       src = (u32 *) header;
78 +       dst = (u32 *) nvram_buf;
79 +       for (i = 0; i < sizeof(struct nvram_header); i += 4)
80 +               *dst++ = *src++;
81 +       for (; i < len && i < NVRAM_SPACE; i += 4)
82 +               *dst++ = *src++;
83 +       ret = 0;
84 +done:
85 +       return ret;
86 +}
87 +
88  static void early_nvram_init(void)
89  {
90         int err = 0;
91 @@ -163,6 +210,10 @@ static void early_nvram_init(void)
92                         err = early_nvram_init_sflash();
93                         if (err < 0)
94                                 printk(KERN_WARNING "can not read from flash: %i\n", err);
95 +               } else if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_NFLASH) {
96 +                       err = early_nvram_init_nflash();
97 +                       if (err < 0)
98 +                               printk(KERN_WARNING "can not read from nflash: %i\n", err);
99                 } else {
100                         printk(KERN_WARNING "unknow flash type\n");
101                 }
102 --- a/arch/mips/bcm47xx/setup.c
103 +++ b/arch/mips/bcm47xx/setup.c
104 @@ -4,6 +4,7 @@
105   *  Copyright (C) 2006 Michael Buesch <m@bues.ch>
106   *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
107   *  Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
108 + *  Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
109   *
110   *  This program is free software; you can redistribute  it and/or modify it
111   *  under  the terms of  the GNU General  Public License as published by the
112 @@ -46,6 +47,7 @@ enum bcm47xx_bus_type bcm47xx_bus_type;
113  EXPORT_SYMBOL(bcm47xx_bus_type);
114  
115  struct bcm47xx_sflash bcm47xx_sflash;
116 +struct bcm47xx_nflash bcm47xx_nflash;
117  
118  static void bcm47xx_machine_restart(char *command)
119  {
120 @@ -325,6 +327,9 @@ static void __init bcm47xx_register_bcma
121  
122         if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_SFLASH)
123                 bcm47xx_sflash_struct_bcma_init(&bcm47xx_sflash, &bcm47xx_bus.bcma.bus.drv_cc);
124 +       
125 +       if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_NFLASH)
126 +               bcm47xx_nflash_struct_bcma_init(&bcm47xx_nflash, &bcm47xx_bus.bcma.bus.drv_cc);
127  }
128  #endif
129  
130 @@ -395,6 +400,19 @@ static struct platform_device bcm47xx_sf
131         .num_resources  = 1,
132  };
133  
134 +static struct resource bcm47xx_nflash_resource = {
135 +       .name   = "bcm47xx_nflash",
136 +       .start  = 0,
137 +       .end    = 0,
138 +       .flags  = 0,
139 +};
140 +
141 +static struct platform_device bcm47xx_nflash_dev = {
142 +       .name           = "bcm47xx_nflash",
143 +       .resource       = &bcm47xx_nflash_resource,
144 +       .num_resources  = 1,
145 +};
146 +
147  static int __init bcm47xx_register_flash(void)
148  {
149  #ifdef CONFIG_BCM47XX_SSB
150 @@ -429,6 +447,9 @@ static int __init bcm47xx_register_flash
151                 } else if (drv_cc->flash_type == BCMA_SFLASH) {
152                         bcm47xx_sflash_dev.dev.platform_data = &bcm47xx_sflash;
153                         return platform_device_register(&bcm47xx_sflash_dev);
154 +               } else if (drv_cc->flash_type == BCMA_NFLASH) {
155 +                       bcm47xx_nflash_dev.dev.platform_data = &bcm47xx_nflash;
156 +                       return platform_device_register(&bcm47xx_nflash_dev);
157                 } else {
158                         printk(KERN_ERR "No flash device found\n");
159                         return -1;
160 --- a/arch/mips/include/asm/mach-bcm47xx/bus.h
161 +++ b/arch/mips/include/asm/mach-bcm47xx/bus.h
162 @@ -2,6 +2,7 @@
163   * BCM947xx nvram variable access
164   *
165   * Copyright (C) 2011 Hauke Mehrtens <hauke@hauke-m.de>
166 + * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
167   *
168   * This program is free software; you can redistribute  it and/or modify it
169   * under  the terms of  the GNU General  Public License as published by the
170 @@ -13,6 +14,7 @@
171  #include <linux/bcma/bcma.h>
172  #include <linux/mtd/mtd.h>
173  #include <bcm47xx.h>
174 +#include <linux/mtd/nand.h>
175  
176  struct bcm47xx_sflash {
177         enum bcm47xx_bus_type sflash_type;
178 @@ -38,3 +40,18 @@ void bcm47xx_sflash_struct_bcma_init(str
179  void bcm47xx_sflash_struct_ssb_init(struct bcm47xx_sflash *sflash, struct ssb_chipcommon *scc);
180  
181  extern struct bcm47xx_sflash bcm47xx_sflash;
182 +
183 +struct bcm47xx_nflash {
184 +       enum bcm47xx_bus_type nflash_type;
185 +       struct bcma_drv_cc *bcc;
186 +
187 +       u32 size;               /* Total size in bytes */
188 +       u32 next_opcode; /* Next expected command from upper NAND layer */
189 +
190 +       struct mtd_info mtd;
191 +       struct nand_chip nand;
192 +};
193 +
194 +void bcm47xx_nflash_struct_bcma_init(struct bcm47xx_nflash *nflash, struct bcma_drv_cc *bcc);
195 +
196 +extern struct bcm47xx_nflash bcm47xx_nflash;
197 --- a/drivers/bcma/bcma_private.h
198 +++ b/drivers/bcma/bcma_private.h
199 @@ -46,6 +46,11 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr
200  int bcma_sflash_init(struct bcma_drv_cc *cc);
201  #endif /* CONFIG_BCMA_SFLASH */
202  
203 +#ifdef CONFIG_BCMA_NFLASH
204 +/* driver_chipcommon_nflash.c */
205 +int bcma_nflash_init(struct bcma_drv_cc *cc);
206 +#endif /* CONFIG_BCMA_NFLASH */
207 +
208  #ifdef CONFIG_BCMA_HOST_PCI
209  /* host_pci.c */
210  extern int __init bcma_host_pci_init(void);
211 --- /dev/null
212 +++ b/drivers/bcma/driver_chipcommon_nflash.c
213 @@ -0,0 +1,154 @@
214 +/*
215 + * BCMA nand flash interface
216 + *
217 + * Copyright 2011, Tathagata Das <tathagata@alumnux.com>
218 + * Copyright 2010, Broadcom Corporation
219 + *
220 + * Licensed under the GNU/GPL. See COPYING for details.
221 + */
222 +
223 +#include <linux/bcma/bcma.h>
224 +#include <linux/bcma/bcma_driver_chipcommon.h>
225 +#include <linux/delay.h>
226 +#include <linux/mtd/bcm47xx_nand.h>
227 +#include <linux/mtd/nand.h>
228 +
229 +#include "bcma_private.h"
230 +
231 +/* Issue a nand flash command */
232 +static inline void bcma_nflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
233 +{
234 +       bcma_cc_write32(cc, NAND_CMD_START, opcode);
235 +       bcma_cc_read32(cc,  NAND_CMD_START);
236 +}
237 +
238 +/* Check offset and length */
239 +static int bcma_nflash_offset_is_valid(struct bcma_drv_cc *cc, u32 offset, u32 len, u32 mask)
240 +{
241 +       if ((offset & mask) != 0 || (len & mask) != 0) {
242 +               pr_err("%s(): Address is not aligned. offset: %x, len: %x, mask: %x\n", __func__, offset, len, mask);
243 +               return 1;
244 +       }
245 +
246 +       if ((((offset + len) >> 20) >= cc->nflash.size) &&
247 +               (((offset + len) & ((1 << 20) - 1)) != 0)) {
248 +               pr_err("%s(): Address is outside Flash memory region. offset: %x, len: %x, mask: %x\n", __func__, offset, len, mask);
249 +               return 1;
250 +       }
251 +
252 +       return 0;
253 +}
254 +
255 +/* Read len bytes starting at offset into buf. Returns number of bytes read. */
256 +int bcma_nflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len, u8 *buf)
257 +{
258 +       u32 mask;
259 +       int i;
260 +       u32 *to, val, res;
261 +
262 +       mask = NFL_SECTOR_SIZE - 1;
263 +       if (bcma_nflash_offset_is_valid(cc, offset, len, mask))
264 +               return 0;
265 +
266 +       to = (u32 *)buf;
267 +       res = len;
268 +       while (res > 0) {
269 +               bcma_cc_write32(cc, NAND_CMD_ADDR, offset);
270 +               bcma_nflash_cmd(cc, NCMD_PAGE_RD);
271 +               if (bcma_nflash_poll(cc) < 0)
272 +                       break;
273 +               val = bcma_cc_read32(cc, NAND_INTFC_STATUS);
274 +               if ((val & NIST_CACHE_VALID) == 0)
275 +                       break;
276 +               bcma_cc_write32(cc, NAND_CACHE_ADDR, 0);
277 +               for (i = 0; i < NFL_SECTOR_SIZE; i += 4, to++) {
278 +                       *to = bcma_cc_read32(cc, NAND_CACHE_DATA);
279 +               }
280 +               res -= NFL_SECTOR_SIZE;
281 +               offset += NFL_SECTOR_SIZE;
282 +       }
283 +       return (len - res);
284 +}
285 +
286 +#define NF_RETRIES   1000000
287 +
288 +/* Poll for command completion. Returns zero when complete. */
289 +int bcma_nflash_poll(struct bcma_drv_cc *cc)
290 +{
291 +       u32 retries = NF_RETRIES;
292 +       u32 pollmask = NIST_CTRL_READY|NIST_FLASH_READY;
293 +       u32 mask;
294 +
295 +       while (retries--) {
296 +               mask = bcma_cc_read32(cc, NAND_INTFC_STATUS) & pollmask;
297 +               if (mask == pollmask)
298 +                       return 0;
299 +               cpu_relax();
300 +       }
301 +
302 +       if (!retries) {
303 +               pr_err("bcma_nflash_poll: not ready\n");
304 +               return -1;
305 +       }
306 +
307 +       return 0;
308 +}
309 +
310 +/* Write len bytes starting at offset into buf. Returns success (0) or failure (!0).
311 + * Should poll for completion.
312 + */
313 +int bcma_nflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
314 +                           const u8 *buf)
315 +{
316 +       u32 mask;
317 +       int i;
318 +       u32 *from, res, reg;
319 +
320 +       mask = cc->nflash.pagesize - 1;
321 +       if (bcma_nflash_offset_is_valid(cc, offset, len, mask))
322 +               return 1;
323 +       
324 +       /* disable partial page enable */
325 +       reg = bcma_cc_read32(cc, NAND_ACC_CONTROL);
326 +       reg &= ~NAC_PARTIAL_PAGE_EN;
327 +       bcma_cc_write32(cc, NAND_ACC_CONTROL, reg);
328 +
329 +       from = (u32 *)buf;
330 +       res = len;
331 +       while (res > 0) {
332 +               bcma_cc_write32(cc, NAND_CACHE_ADDR, 0);
333 +               for (i = 0; i < cc->nflash.pagesize; i += 4, from++) {
334 +                       if (i % 512 == 0)
335 +                               bcma_cc_write32(cc, NAND_CMD_ADDR, i);
336 +                       bcma_cc_write32(cc, NAND_CACHE_DATA, *from);
337 +               }
338 +               bcma_cc_write32(cc, NAND_CMD_ADDR, offset + cc->nflash.pagesize - 512);
339 +               bcma_nflash_cmd(cc, NCMD_PAGE_PROG);
340 +               if (bcma_nflash_poll(cc) < 0)
341 +                       break;
342 +               res -= cc->nflash.pagesize;
343 +               offset += cc->nflash.pagesize;
344 +       }
345 +
346 +       if (res <= 0)
347 +               return 0;
348 +       else
349 +               return (len - res);
350 +}
351 +
352 +/* Erase a region. Returns success (0) or failure (-1). 
353 + * Poll for completion.
354 + */
355 +int bcma_nflash_erase(struct bcma_drv_cc *cc, u32 offset)
356 +{
357 +       if ((offset >> 20) >= cc->nflash.size)
358 +               return -1;
359 +       if ((offset & (cc->nflash.blocksize - 1)) != 0)
360 +               return -1;
361 +
362 +       bcma_cc_write32(cc, NAND_CMD_ADDR, offset);
363 +       bcma_nflash_cmd(cc, NCMD_BLOCK_ERASE);
364 +       if (bcma_nflash_poll(cc) < 0)
365 +               return -1;
366 +       return 0;
367 +}
368 --- a/drivers/bcma/driver_mips.c
369 +++ b/drivers/bcma/driver_mips.c
370 @@ -6,6 +6,7 @@
371   * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
372   * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
373   * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
374 + * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
375   *
376   * Licensed under the GNU/GPL. See COPYING for details.
377   */
378 @@ -182,6 +183,17 @@ static void bcma_core_mips_flash_detect(
379  {
380         struct bcma_bus *bus = mcore->core->bus;
381  
382 +       if (bus->drv_cc.core->id.rev == 38 
383 +               && (bus->drv_cc.status & (1 << 4)) != 0) {
384 +#ifdef CONFIG_BCMA_NFLASH
385 +               pr_info("found nand flash.\n");
386 +               bus->drv_cc.flash_type = BCMA_NFLASH;
387 +#else
388 +               pr_info("NAND flash not supported.\n");
389 +#endif
390 +               return;
391 +       }
392 +
393         switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
394         case BCMA_CC_FLASHT_STSER:
395         case BCMA_CC_FLASHT_ATSER:
396 --- a/drivers/bcma/Kconfig
397 +++ b/drivers/bcma/Kconfig
398 @@ -43,6 +43,11 @@ config BCMA_SFLASH
399         depends on BCMA_DRIVER_MIPS
400         default y
401  
402 +config BCMA_NFLASH
403 +       bool
404 +       depends on BCMA_DRIVER_MIPS
405 +       default y
406 +
407  config BCMA_DRIVER_MIPS
408         bool "BCMA Broadcom MIPS core driver"
409         depends on BCMA && MIPS
410 --- a/drivers/bcma/Makefile
411 +++ b/drivers/bcma/Makefile
412 @@ -1,6 +1,7 @@
413  bcma-y                                 += main.o scan.o core.o sprom.o
414  bcma-y                                 += driver_chipcommon.o driver_chipcommon_pmu.o
415  bcma-$(CONFIG_BCMA_SFLASH)             += driver_chipcommon_sflash.o
416 +bcma-$(CONFIG_BCMA_NFLASH)             += driver_chipcommon_nflash.o
417  bcma-y                                 += driver_pci.o
418  bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE)        += driver_pci_host.o
419  bcma-$(CONFIG_BCMA_DRIVER_MIPS)                += driver_mips.o
420 --- /dev/null
421 +++ b/drivers/mtd/nand/bcm47xx_nand.c
422 @@ -0,0 +1,506 @@
423 +/*
424 + * BCMA nand flash interface
425 + *
426 + * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
427 + * Copyright 2010, Broadcom Corporation
428 + *
429 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
430 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
431 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
432 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
433 + *
434 + */
435 +
436 +#define pr_fmt(fmt) "bcm47xx_nflash: " fmt
437 +#include <linux/module.h>
438 +#include <linux/slab.h>
439 +#include <linux/ioport.h>
440 +#include <linux/sched.h>
441 +#include <linux/mtd/mtd.h>
442 +#include <linux/mtd/map.h>
443 +#include <linux/mtd/partitions.h>
444 +#include <linux/errno.h>
445 +#include <linux/delay.h>
446 +#include <linux/platform_device.h>
447 +#include <bcm47xx.h>
448 +#include <bus.h>
449 +#include <linux/cramfs_fs.h>
450 +#include <linux/romfs_fs.h>
451 +#include <linux/magic.h>
452 +#include <linux/byteorder/generic.h>
453 +#include <linux/mtd/bcm47xx_nand.h>
454 +#include <linux/mtd/nand.h>
455 +
456 +static int bcm47xx_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip);
457 +static int bcm47xx_erase(struct mtd_info *mtd, unsigned int addr, unsigned int len);
458 +
459 +/* Private Global variable */
460 +static u32 read_offset = 0;
461 +static u32 write_offset;
462 +
463 +static int
464 +nflash_mtd_poll(struct bcm47xx_nflash *nflash, unsigned int offset, int timeout)
465 +{
466 +       unsigned long now = jiffies;
467 +       int ret = 0;
468 +
469 +       for (;;) {
470 +               if (!bcma_nflash_poll(nflash->bcc)) {
471 +                       ret = 0;
472 +                       break;
473 +               }
474 +               if (time_after(jiffies, now + timeout)) {
475 +                       pr_err("timeout while polling\n");
476 +                       ret = -ETIMEDOUT;
477 +                       break;
478 +               }
479 +               udelay(1);
480 +       }
481 +
482 +       return ret;
483 +}
484 +
485 +static int
486 +bcm47xx_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
487 +{
488 +       struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
489 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
490 +       int bytes, ret = 0;
491 +       u32 extra = 0;
492 +       u8 *tmpbuf = NULL;
493 +       int size;
494 +       u32 offset, blocksize, mask, off;
495 +       u32 skip_bytes = 0;
496 +       int need_copy = 0;
497 +       u8 *ptr = NULL;
498 +
499 +       /* Check address range */
500 +       if (!len)
501 +               return 0;
502 +       if ((from + len) > mtd->size)
503 +               return -EINVAL;
504 +       offset = from;
505 +       if ((offset & (NFL_SECTOR_SIZE - 1)) != 0) {
506 +               extra = offset & (NFL_SECTOR_SIZE - 1);
507 +               offset -= extra;
508 +               len += extra;
509 +               need_copy = 1;
510 +       }
511 +       size = (len + (NFL_SECTOR_SIZE - 1)) & ~(NFL_SECTOR_SIZE - 1);
512 +       if (size != len) {
513 +               need_copy = 1;
514 +       }
515 +       if (!need_copy) {
516 +               ptr = buf;
517 +       } else {
518 +               tmpbuf = (u8 *)kmalloc(size, GFP_KERNEL);
519 +               ptr = tmpbuf;
520 +       }
521 +
522 +       blocksize = mtd->erasesize;
523 +       mask = blocksize - 1;
524 +       *retlen = 0;
525 +       while (len > 0) {
526 +               off = offset + skip_bytes;
527 +               if ((bytes = bcma_nflash_read(nflash->bcc, off, NFL_SECTOR_SIZE, ptr)) < 0) {
528 +                       ret = bytes;
529 +                       goto done;
530 +               }
531 +               if (bytes > len)
532 +                       bytes = len;
533 +               offset += bytes;
534 +               len -= bytes;
535 +               ptr += bytes;
536 +               *retlen += bytes;
537 +       }
538 +
539 +done:
540 +       if (tmpbuf) {
541 +               *retlen -= extra;
542 +               memcpy(buf, tmpbuf+extra, *retlen);
543 +               kfree(tmpbuf);
544 +       }
545 +
546 +       return ret;
547 +}
548 +
549 +static void bcm47xx_write(struct mtd_info *mtd, u32 to, const u_char *buf, u32 len)
550 +{
551 +       struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
552 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
553 +       u32 offset, blocksize, mask, off;
554 +       int read_len;
555 +       u32 copy_len, write_len, from;
556 +       u_char *write_ptr, *block;
557 +       const u_char *ptr;
558 +       int ret, bytes;
559 +
560 +       /* Check address range */
561 +       if (!len) {
562 +               pr_err("Error: Attempted to write too small data\n");
563 +               return;
564 +       }
565 +
566 +       if (!to)
567 +               return;
568 +
569 +       if ((to + len) > mtd->size) {
570 +               pr_err("Error: Attempted to write too large data\n");
571 +               return;
572 +       }
573 +
574 +       ptr = buf;
575 +       block = NULL;
576 +       offset = to;
577 +       blocksize = mtd->erasesize;
578 +       if (!(block = kmalloc(blocksize, GFP_KERNEL)))
579 +               return;
580 +       mask = blocksize - 1;
581 +       while (len) {
582 +               /* Align offset */
583 +               from = offset & ~mask;
584 +               /* Copy existing data into holding block if necessary */
585 +               if (((offset & (blocksize-1)) != 0) || (len < blocksize)) {
586 +                       if ((ret = bcm47xx_read(mtd, from, blocksize, &read_len, block)))
587 +                               goto done;
588 +                       if (read_len != blocksize) {
589 +                               ret = -EINVAL;
590 +                               goto done;
591 +                       }
592 +               }
593 +       
594 +               /* Copy input data into holding block */
595 +               copy_len = min(len, blocksize - (offset & mask));
596 +               memcpy(block + (offset & mask), ptr, copy_len);
597 +               off = (uint) from;
598 +               /* Erase block */
599 +               if ((ret = bcm47xx_erase(mtd, off, blocksize)) < 0)
600 +                       goto done;
601 +               /* Write holding block */
602 +               write_ptr = block;
603 +               write_len = blocksize;
604 +               if ((bytes = bcma_nflash_write(nflash->bcc, (uint)from, (uint)write_len, (u8 *) write_ptr)) != 0) {
605 +                       ret = bytes;
606 +                       goto done;
607 +               }
608 +               offset += copy_len;
609 +               if (len < copy_len)
610 +                       len = 0;
611 +               else
612 +                       len -= copy_len;
613 +               ptr += copy_len;
614 +       }
615 +
616 +done:
617 +       if (block)
618 +               kfree(block);
619 +       return;
620 +}
621 +
622 +static int bcm47xx_erase(struct mtd_info *mtd, unsigned int addr, unsigned int len)
623 +{
624 +       struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
625 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
626 +
627 +       /* Check address range */
628 +       if (!len)
629 +               return 1;
630 +       if ((addr + len) > mtd->size)
631 +               return 1;
632 +
633 +       if (bcma_nflash_erase(nflash->bcc, addr)) {
634 +               pr_err("ERASE: nflash erase error\n");
635 +               return 1;
636 +       }
637 +
638 +       if (nflash_mtd_poll(nflash, addr, 10 * HZ)) {
639 +               pr_err("ERASE: nflash_mtd_poll error\n");
640 +               return 1;
641 +       }
642 +       
643 +       return 0;
644 +}
645 +
646 +/* This functions is used by upper layer to checks if device is ready */
647 +static int bcm47xx_dev_ready(struct mtd_info *mtd)
648 +{
649 +       return 1;
650 +}
651 +
652 +/* Issue a nand flash command */
653 +static inline void bcm47xx_nflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
654 +{
655 +       bcma_cc_write32(cc, NAND_CMD_START, opcode);
656 +       bcma_cc_read32(cc,  NAND_CMD_START);
657 +}
658 +
659 +static void bcm47xx_command(struct mtd_info *mtd, unsigned command,
660 +                               int column, int page_addr)
661 +{
662 +       struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
663 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
664 +       u32 pagesize = 1 << nchip->page_shift;
665 +
666 +       /* Command pre-processing step */
667 +       switch (command) {
668 +       case NAND_CMD_RESET:
669 +               bcm47xx_nflash_cmd(nflash->bcc, NCMD_FLASH_RESET);
670 +               break;
671 +
672 +       case NAND_CMD_STATUS:
673 +               nflash->next_opcode = NAND_CMD_STATUS;
674 +               read_offset = 0;
675 +               write_offset = 0;
676 +               break;
677 +
678 +       case NAND_CMD_READ0:
679 +               read_offset = page_addr * pagesize;
680 +               nflash->next_opcode = 0;
681 +               break;
682 +
683 +       case NAND_CMD_READOOB:
684 +               read_offset = page_addr * pagesize;
685 +               nflash->next_opcode = 0;
686 +               break;
687 +
688 +       case NAND_CMD_SEQIN:
689 +               write_offset = page_addr * pagesize;
690 +               nflash->next_opcode = 0;
691 +               break;
692 +
693 +       case NAND_CMD_PAGEPROG:
694 +               nflash->next_opcode = 0;
695 +               break;
696 +
697 +       case NAND_CMD_READID:
698 +               read_offset = column;
699 +               bcm47xx_nflash_cmd(nflash->bcc, NCMD_ID_RD);
700 +               nflash->next_opcode = NAND_DEVID;
701 +               break;
702 +
703 +       case NAND_CMD_ERASE1:
704 +               nflash->next_opcode = 0;
705 +               bcm47xx_erase(mtd, page_addr*pagesize, pagesize);
706 +               break;
707 +       
708 +       case NAND_CMD_ERASE2:
709 +               break;
710 +
711 +       case NAND_CMD_RNDOUT:
712 +               if (column > mtd->writesize)
713 +                       read_offset += (column - mtd->writesize);
714 +               else 
715 +                       read_offset += column;
716 +               break;
717 +
718 +       default:
719 +               pr_err("COMMAND not supported %x\n", command);
720 +               nflash->next_opcode = 0;
721 +               break;
722 +       }
723 +}
724 +
725 +/* This function is used by upper layer for select and
726 + * deselect of the NAND chip.
727 + * It is dummy function. */
728 +static void bcm47xx_select_chip(struct mtd_info *mtd, int chip)
729 +{
730 +}
731 +
732 +static u_char bcm47xx_read_byte(struct mtd_info *mtd)
733 +{
734 +       struct nand_chip *nchip = mtd->priv;
735 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
736 +       uint8_t ret = 0;
737 +       static u32 id;
738 +
739 +       if (nflash->next_opcode == 0)
740 +               return ret;
741 +
742 +       if (nflash->next_opcode == NAND_CMD_STATUS)
743 +               return NAND_STATUS_WP; 
744 +
745 +       id = bcma_cc_read32(nflash->bcc, nflash->next_opcode);
746 +
747 +       if (nflash->next_opcode == NAND_DEVID) {
748 +               ret = (id >> (8*read_offset)) & 0xff;
749 +               read_offset++;
750 +       }
751 +
752 +       return ret;
753 +}
754 +
755 +static uint16_t bcm47xx_read_word(struct mtd_info *mtd)
756 +{
757 +       loff_t from = read_offset;
758 +       uint16_t buf = 0;
759 +       int bytes;
760 +
761 +       bcm47xx_read(mtd, from, sizeof(buf), &bytes, (u_char *)&buf);
762 +       return buf;
763 +}
764 +
765 +/* Write data of length len to buffer buf. The data to be
766 + * written on NAND Flash is first copied to RAMbuffer. After the Data Input
767 + * Operation by the NFC, the data is written to NAND Flash */
768 +static void bcm47xx_write_buf(struct mtd_info *mtd,
769 +                               const u_char *buf, int len)
770 +{
771 +       bcm47xx_write(mtd, write_offset, buf, len);
772 +}
773 +
774 +/* Read the data buffer from the NAND Flash. To read the data from NAND
775 + * Flash first the data output cycle is initiated by the NFC, which copies
776 + * the data to RAMbuffer. This data of length len is then copied to buffer buf.
777 + */
778 +static void bcm47xx_read_buf(struct mtd_info *mtd, u_char *buf, int len)
779 +{
780 +       loff_t from = read_offset;
781 +       int bytes;
782 +
783 +       bcm47xx_read(mtd, from, len, &bytes, buf);
784 +}
785 +
786 +/* Used by the upper layer to verify the data in NAND Flash
787 + * with the data in the buf. */
788 +static int bcm47xx_verify_buf(struct mtd_info *mtd,
789 +                               const u_char *buf, int len)
790 +{
791 +       return -EFAULT;
792 +}
793 +
794 +static int bcm47xx_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
795 +{
796 +       struct nand_chip *nchip = mtd->priv;
797 +       struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
798 +       int i;
799 +       uint off;
800 +       u32 pagesize = 1 << nchip->page_shift;
801 +       u32 blocksize = mtd->erasesize;
802 +
803 +       if ((ofs >> 20) >= nflash->size)
804 +               return 1;
805 +       if ((ofs & (blocksize - 1)) != 0)
806 +               return 1;
807 +
808 +       for (i = 0; i < 2; i++) {
809 +               off = ofs + pagesize;
810 +               bcma_cc_write32(nflash->bcc, NAND_CMD_ADDR, off);
811 +               bcm47xx_nflash_cmd(nflash->bcc, NCMD_SPARE_RD);
812 +               if (bcma_nflash_poll(nflash->bcc) < 0)
813 +                       break;
814 +               if ((bcma_cc_read32(nflash->bcc, NAND_INTFC_STATUS) & NIST_SPARE_VALID) != NIST_SPARE_VALID)
815 +                       return 1;
816 +               if ((bcma_cc_read32(nflash->bcc, NAND_SPARE_RD0) & 0xff) != 0xff)
817 +                       return 1;
818 +       }
819 +       return 0;
820 +}
821 +
822 +const char *part_probes[] = { "cmdlinepart", NULL };
823 +static int bcm47xx_probe(struct platform_device *pdev)
824 +{
825 +       struct nand_chip *nchip;
826 +       struct mtd_info *mtd;
827 +       struct bcm47xx_nflash *nflash = dev_get_platdata(&pdev->dev);
828 +       int ret = 0;
829 +
830 +       mtd = &nflash->mtd;
831 +       nchip = &nflash->nand;
832 +
833 +       /* Register with MTD */
834 +       mtd->priv = nchip;
835 +       mtd->owner = THIS_MODULE;
836 +       mtd->dev.parent = &pdev->dev;
837 +
838 +       /* 50 us command delay time */
839 +       nchip->chip_delay = 50;
840 +
841 +       nchip->priv = nflash;
842 +       nchip->dev_ready = bcm47xx_dev_ready;
843 +       nchip->cmdfunc = bcm47xx_command;
844 +       nchip->select_chip = bcm47xx_select_chip;
845 +       nchip->read_byte = bcm47xx_read_byte;
846 +       nchip->read_word = bcm47xx_read_word;
847 +       nchip->write_buf = bcm47xx_write_buf;
848 +       nchip->read_buf = bcm47xx_read_buf;
849 +       nchip->verify_buf = bcm47xx_verify_buf;
850 +       nchip->block_bad = bcm47xx_block_bad;
851 +       nchip->options = NAND_SKIP_BBTSCAN;
852 +
853 +       /* Not known */
854 +       nchip->ecc.mode = NAND_ECC_NONE;
855 +
856 +       /* first scan to find the device and get the page size */
857 +       if (nand_scan_ident(mtd, 1, NULL)) {
858 +               pr_err("nand_scan_ident failed\n");
859 +               ret = -ENXIO;
860 +               goto done;
861 +       }
862 +       nflash->bcc->nflash.size = mtd->size;
863 +       nflash->bcc->nflash.pagesize = 1 << nchip->page_shift;
864 +       nflash->bcc->nflash.blocksize = mtd->erasesize;
865 +       bcm47xx_nflash.size = mtd->size;
866 +
867 +       /* second phase scan */
868 +       if (nand_scan_tail(mtd)) {
869 +               pr_err("nand_scan_tail failed\n");
870 +               ret = -ENXIO;
871 +               goto done;
872 +       }
873 +
874 +       mtd->name = "bcm47xx-nflash";
875 +       mtd->flags |= MTD_WRITEABLE;
876 +       ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL, 0);
877 +
878 +       if (ret) {
879 +               pr_err("mtd_device_register failed\n");
880 +               return ret;
881 +       }
882 +       
883 +       return 0;
884 +
885 +done:
886 +       return ret;
887 +}
888 +
889 +static int __devexit bcm47xx_remove(struct platform_device *pdev)
890 +{
891 +       struct bcm47xx_nflash *nflash = dev_get_platdata(&pdev->dev);
892 +       struct mtd_info *mtd = &nflash->mtd;
893 +
894 +       if (nflash) {
895 +               /* Release resources, unregister device */
896 +               nand_release(mtd);
897 +       }
898 +
899 +       return 0;
900 +}
901 +
902 +static struct platform_driver bcm47xx_driver = {
903 +       .remove = __devexit_p(bcm47xx_remove),
904 +       .driver = {
905 +               .name = "bcm47xx_nflash",
906 +               .owner = THIS_MODULE,
907 +       },
908 +};
909 +
910 +static int __init init_bcm47xx_nflash(void)
911 +{
912 +       int ret = platform_driver_probe(&bcm47xx_driver, bcm47xx_probe);
913 +
914 +       if (ret)
915 +               pr_err("error registering platform driver: %i\n", ret);
916 +       return ret;
917 +}
918 +
919 +static void __exit exit_bcm47xx_nflash(void)
920 +{
921 +       platform_driver_unregister(&bcm47xx_driver);
922 +}
923 +
924 +module_init(init_bcm47xx_nflash);
925 +module_exit(exit_bcm47xx_nflash);
926 +
927 +MODULE_LICENSE("GPL");
928 +MODULE_DESCRIPTION("BCM47XX NAND flash driver");
929 --- a/drivers/mtd/nand/Kconfig
930 +++ b/drivers/mtd/nand/Kconfig
931 @@ -537,4 +537,12 @@ config MTD_NAND_FSMC
932           Enables support for NAND Flash chips on the ST Microelectronics
933           Flexible Static Memory Controller (FSMC)
934  
935 +config MTD_NAND_BCM47XX
936 +       tristate "bcm47xx nand flash support"
937 +       default y
938 +       depends on BCM47XX
939 +       select MTD_PARTITIONS
940 +       help
941 +         Support for bcm47xx nand flash
942 +
943  endif # MTD_NAND
944 --- a/drivers/mtd/nand/Makefile
945 +++ b/drivers/mtd/nand/Makefile
946 @@ -49,5 +49,6 @@ obj-$(CONFIG_MTD_NAND_MPC5121_NFC)    += mp
947  obj-$(CONFIG_MTD_NAND_RICOH)           += r852.o
948  obj-$(CONFIG_MTD_NAND_JZ4740)          += jz4740_nand.o
949  obj-$(CONFIG_MTD_NAND_GPMI_NAND)       += gpmi-nand/
950 +obj-$(CONFIG_MTD_NAND_BCM47XX)         += bcm47xx_nand.o
951  
952  nand-objs := nand_base.o nand_bbt.o
953 --- a/include/linux/bcma/bcma_driver_chipcommon.h
954 +++ b/include/linux/bcma/bcma_driver_chipcommon.h
955 @@ -376,6 +376,7 @@ struct bcma_chipcommon_pmu {
956  enum bcma_flash_type {
957         BCMA_PFLASH,
958         BCMA_SFLASH,
959 +       BCMA_NFLASH,
960  };
961  
962  struct bcma_pflash {
963 @@ -392,6 +393,14 @@ struct bcma_sflash {
964  };
965  #endif /* CONFIG_BCMA_SFLASH */
966  
967 +#ifdef CONFIG_BCMA_NFLASH
968 +struct bcma_nflash {
969 +       u32 blocksize;          /* Block size */
970 +       u32 pagesize;           /* Page size */
971 +       u32 size;               /* Total size in bytes */
972 +};
973 +#endif
974 +
975  struct bcma_serial_port {
976         void *regs;
977         unsigned long clockspeed;
978 @@ -417,6 +426,9 @@ struct bcma_drv_cc {
979  #ifdef CONFIG_BCMA_SFLASH
980                 struct bcma_sflash sflash;
981  #endif /* CONFIG_BCMA_SFLASH */
982 +#ifdef CONFIG_BCMA_NFLASH
983 +               struct bcma_nflash nflash;
984 +#endif
985         };
986  
987         int nr_serial_ports;
988 @@ -483,4 +495,13 @@ int bcma_sflash_commit(struct bcma_drv_c
989                              const u8 *buf);
990  #endif /* CONFIG_BCMA_SFLASH */
991  
992 +#ifdef CONFIG_BCMA_NFLASH
993 +/* Chipcommon nflash support. */
994 +int bcma_nflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len, u8 *buf);
995 +int bcma_nflash_poll(struct bcma_drv_cc *cc);
996 +int bcma_nflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len, const u8 *buf);
997 +int bcma_nflash_erase(struct bcma_drv_cc *cc, u32 offset);
998 +int bcma_nflash_commit(struct bcma_drv_cc *cc, u32 offset, u32 len, const u8 *buf);
999 +#endif
1000 +
1001  #endif /* LINUX_BCMA_DRIVER_CC_H_ */
1002 --- /dev/null
1003 +++ b/include/linux/mtd/bcm47xx_nand.h
1004 @@ -0,0 +1,134 @@
1005 +/*
1006 + * Broadcom chipcommon NAND flash interface
1007 + *
1008 + * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
1009 + * Copyright (C) 2009, Broadcom Corporation
1010 + * All Rights Reserved.
1011 + * 
1012 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
1013 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
1014 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
1015 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
1016 + *
1017 + */
1018 +
1019 +#ifndef _nflash_h_
1020 +#define _nflash_h_
1021 +
1022 +#define  NAND_FLASH1                                           0x1fc00000  /* MIPS Flash Region 1 */
1023 +
1024 +/* nand_cmd_start commands */
1025 +#define        NCMD_NULL                                               0
1026 +#define        NCMD_PAGE_RD                                    1
1027 +#define        NCMD_SPARE_RD                                   2
1028 +#define        NCMD_STATUS_RD                                  3
1029 +#define        NCMD_PAGE_PROG                                  4
1030 +#define        NCMD_SPARE_PROG                         5
1031 +#define        NCMD_COPY_BACK                                  6
1032 +#define        NCMD_ID_RD                                              7
1033 +#define        NCMD_BLOCK_ERASE                                8
1034 +#define        NCMD_FLASH_RESET                                9
1035 +#define        NCMD_LOCK                                               0xa
1036 +#define        NCMD_LOCK_DOWN                                  0xb
1037 +#define        NCMD_UNLOCK                                             0xc
1038 +#define        NCMD_LOCK_STATUS                                0xd
1039 +
1040 +/* nand_acc_control */
1041 +#define        NAC_RD_ECC_EN                                   0x80000000
1042 +#define        NAC_WR_ECC_EN                                   0x40000000
1043 +#define        NAC_RD_ECC_BLK0_EN                      0x20000000
1044 +#define        NAC_FAST_PGM_RDIN                               0x10000000
1045 +#define        NAC_RD_ERASED_ECC_EN                    0x08000000
1046 +#define        NAC_PARTIAL_PAGE_EN                     0x04000000
1047 +#define        NAC_PAGE_HIT_EN                         0x01000000
1048 +#define        NAC_ECC_LEVEL0                                  0x00f00000
1049 +#define        NAC_ECC_LEVEL                                   0x000f0000
1050 +#define        NAC_SPARE_SIZE0                         0x00003f00
1051 +#define        NAC_SPARE_SIZE                                  0x0000003f
1052 +
1053 +/* nand_config */
1054 +#define        NCF_CONFIG_LOCK                         0x80000000
1055 +#define        NCF_BLOCK_SIZE_MASK                     0x70000000
1056 +#define        NCF_BLOCK_SIZE_SHIFT                    28
1057 +#define        NCF_DEVICE_SIZE_MASK                    0x0f000000
1058 +#define        NCF_DEVICE_SIZE_SHIFT           24
1059 +#define        NCF_DEVICE_WIDTH                                0x00800000
1060 +#define        NCF_PAGE_SIZE_MASK                      0x00300000
1061 +#define        NCF_PAGE_SIZE_SHIFT                     20
1062 +#define        NCF_FULL_ADDR_BYTES_MASK        0x00070000
1063 +#define        NCF_FULL_ADDR_BYTES_SHIFT       16
1064 +#define        NCF_COL_ADDR_BYTES_MASK         0x00007000
1065 +#define        NCF_COL_ADDR_BYTES_SHIFT        12
1066 +#define        NCF_BLK_ADDR_BYTES_MASK         0x00000700
1067 +#define        NCF_BLK_ADDR_BYTES_SHIFT        8
1068 +
1069 +/* nand_intfc_status */
1070 +#define        NIST_CTRL_READY                         0x80000000
1071 +#define        NIST_FLASH_READY                                0x40000000
1072 +#define        NIST_CACHE_VALID                                0x20000000
1073 +#define        NIST_SPARE_VALID                                0x10000000
1074 +#define        NIST_ERASED                                             0x08000000
1075 +#define        NIST_STATUS                                             0x000000ff
1076 +
1077 +#define        NFL_SECTOR_SIZE                         512
1078 +
1079 +#define        NFL_TABLE_END                                   0xffffffff
1080 +#define        NFL_BOOT_SIZE                                   0x200000
1081 +#define        NFL_BOOT_OS_SIZE                                0x2000000
1082 +
1083 +/* Nand flash MLC controller registers (corerev >= 38) */
1084 +#define        NAND_REVISION                                   0xC00
1085 +#define        NAND_CMD_START                                  0xC04
1086 +#define        NAND_CMD_ADDR_X                         0xC08
1087 +#define        NAND_CMD_ADDR                                   0xC0C
1088 +#define        NAND_CMD_END_ADDR                               0xC10
1089 +#define        NAND_CS_NAND_SELECT                     0xC14
1090 +#define        NAND_CS_NAND_XOR                                0xC18
1091 +#define        NAND_SPARE_RD0                                  0xC20
1092 +#define        NAND_SPARE_RD4                                  0xC24
1093 +#define        NAND_SPARE_RD8                                  0xC28
1094 +#define        NAND_SPARE_RD12                         0xC2C
1095 +#define        NAND_SPARE_WR0                                  0xC30
1096 +#define        NAND_SPARE_WR4                                  0xC34
1097 +#define        NAND_SPARE_WR8                                  0xC38
1098 +#define        NAND_SPARE_WR12                         0xC3C
1099 +#define        NAND_ACC_CONTROL                                0xC40
1100 +#define        NAND_CONFIG                                             0xC48
1101 +#define        NAND_TIMING_1                                   0xC50
1102 +#define        NAND_TIMING_2                                   0xC54
1103 +#define        NAND_SEMAPHORE                                  0xC58
1104 +#define        NAND_DEVID                                              0xC60
1105 +#define        NAND_DEVID_X                                    0xC64
1106 +#define        NAND_BLOCK_LOCK_STATUS          0xC68
1107 +#define        NAND_INTFC_STATUS                               0xC6C
1108 +#define        NAND_ECC_CORR_ADDR_X                    0xC70
1109 +#define        NAND_ECC_CORR_ADDR                      0xC74
1110 +#define        NAND_ECC_UNC_ADDR_X                     0xC78
1111 +#define        NAND_ECC_UNC_ADDR                               0xC7C
1112 +#define        NAND_READ_ERROR_COUNT           0xC80
1113 +#define        NAND_CORR_STAT_THRESHOLD        0xC84
1114 +#define        NAND_READ_ADDR_X                                0xC90
1115 +#define        NAND_READ_ADDR                                  0xC94
1116 +#define        NAND_PAGE_PROGRAM_ADDR_X        0xC98
1117 +#define        NAND_PAGE_PROGRAM_ADDR          0xC9C
1118 +#define        NAND_COPY_BACK_ADDR_X           0xCA0
1119 +#define        NAND_COPY_BACK_ADDR                     0xCA4
1120 +#define        NAND_BLOCK_ERASE_ADDR_X         0xCA8
1121 +#define        NAND_BLOCK_ERASE_ADDR           0xCAC
1122 +#define        NAND_INV_READ_ADDR_X                    0xCB0
1123 +#define        NAND_INV_READ_ADDR                      0xCB4
1124 +#define        NAND_BLK_WR_PROTECT                     0xCC0
1125 +#define        NAND_ACC_CONTROL_CS1                    0xCD0
1126 +#define        NAND_CONFIG_CS1                         0xCD4
1127 +#define        NAND_TIMING_1_CS1                               0xCD8
1128 +#define        NAND_TIMING_2_CS1                               0xCDC
1129 +#define        NAND_SPARE_RD16                         0xD30
1130 +#define        NAND_SPARE_RD20                         0xD34
1131 +#define        NAND_SPARE_RD24                         0xD38
1132 +#define        NAND_SPARE_RD28                         0xD3C
1133 +#define        NAND_CACHE_ADDR                         0xD40
1134 +#define        NAND_CACHE_DATA                         0xD44
1135 +#define        NAND_CTRL_CONFIG                                0xD48
1136 +#define        NAND_CTRL_STATUS                                0xD4C
1137 +
1138 +#endif /* _nflash_h_ */