brcm47xx: add support for NAND flash on devices using bcma
authorHauke Mehrtens <hauke@hauke-m.de>
Wed, 14 Mar 2012 22:59:39 +0000 (22:59 +0000)
committerHauke Mehrtens <hauke@hauke-m.de>
Wed, 14 Mar 2012 22:59:39 +0000 (22:59 +0000)
This patch add support for the NAND flash on BCM5357 based devices like the WNR3500Lv2.

Thank you Tathagata Das <tathagata@alumnux.com> for the patch

SVN-Revision: 30943

14 files changed:
target/linux/brcm47xx/config-3.2
target/linux/brcm47xx/patches-3.2/030-bcm47xx-bcma-nandflash.patch [new file with mode: 0644]
target/linux/brcm47xx/patches-3.2/042-bcma-export-bcma_pcie_read.patch
target/linux/brcm47xx/patches-3.2/043-bcma-make-some-functions-__devinit.patch
target/linux/brcm47xx/patches-3.2/044-bcma-add-PCIe-host-controller.patch
target/linux/brcm47xx/patches-3.2/114-MIPS-BCM47xx-Setup-and-register-serial-early.patch
target/linux/brcm47xx/patches-3.2/196-MIPS-BCM47XX-return-number-of-written-bytes-in-nvram.patch
target/linux/brcm47xx/patches-3.2/198-MIPS-BCM47XX-move-and-extend-sprom-parsing.patch
target/linux/brcm47xx/patches-3.2/199-MIPS-BCM47XX-provide-sprom-to-bcma-bus.patch
target/linux/brcm47xx/patches-3.2/231-bcma_reorder_sprom_fill.patch
target/linux/brcm47xx/patches-3.2/400-arch-bcm47xx.patch
target/linux/brcm47xx/patches-3.2/820-wgt634u-nvram-fix.patch
target/linux/brcm47xx/patches-3.2/980-wnr834b_no_cardbus_invariant.patch
target/linux/brcm47xx/patches-3.2/999-wl_exports.patch

index e4641ed10e230a986574e38ad10e93a0c6fbcc09..39fac67ad2863e7dc2d01f070fadf2c8f07be764 100644 (file)
@@ -24,6 +24,7 @@ CONFIG_BCMA_DRIVER_PCI_HOSTMODE=y
 CONFIG_BCMA_HOST_PCI=y
 CONFIG_BCMA_HOST_PCI_POSSIBLE=y
 CONFIG_BCMA_HOST_SOC=y
+CONFIG_BCMA_NFLASH=y
 CONFIG_BCMA_POSSIBLE=y
 CONFIG_BCMA_SFLASH=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -94,6 +95,10 @@ CONFIG_MIPS_MT_DISABLED=y
 CONFIG_MTD_BCM47XX_PARTS=y
 CONFIG_MTD_BCM47XX_PFLASH=y
 CONFIG_MTD_BCM47XX_SFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_BCM47XX=y
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_SM_COMMON is not set
 CONFIG_NEED_DMA_MAP_STATE=y
 CONFIG_NEED_PER_CPU_KM=y
 CONFIG_PAGEFLAGS_EXTENDED=y
diff --git a/target/linux/brcm47xx/patches-3.2/030-bcm47xx-bcma-nandflash.patch b/target/linux/brcm47xx/patches-3.2/030-bcm47xx-bcma-nandflash.patch
new file mode 100644 (file)
index 0000000..4f4386e
--- /dev/null
@@ -0,0 +1,1138 @@
+--- a/arch/mips/bcm47xx/bus.c
++++ b/arch/mips/bcm47xx/bus.c
+@@ -2,6 +2,7 @@
+  * BCM947xx nvram variable access
+  *
+  * Copyright (C) 2011 Hauke Mehrtens <hauke@hauke-m.de>
++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -92,3 +93,9 @@ void bcm47xx_sflash_struct_ssb_init(stru
+       sflash->numblocks = scc->sflash.numblocks;
+       sflash->size = scc->sflash.size;
+ }
++
++void bcm47xx_nflash_struct_bcma_init(struct bcm47xx_nflash *nflash, struct bcma_drv_cc *bcc)
++{
++      nflash->nflash_type = BCM47XX_BUS_TYPE_BCMA;
++      nflash->bcc = bcc;
++}
+--- a/arch/mips/bcm47xx/nvram.c
++++ b/arch/mips/bcm47xx/nvram.c
+@@ -4,6 +4,7 @@
+  * Copyright (C) 2005 Broadcom Corporation
+  * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+  * Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -21,6 +22,7 @@
+ #include <asm/mach-bcm47xx/nvram.h>
+ #include <asm/mach-bcm47xx/bcm47xx.h>
+ #include <asm/mach-bcm47xx/bus.h>
++#include <linux/mtd/bcm47xx_nand.h>
+ static char nvram_buf[NVRAM_SPACE];
+@@ -137,6 +139,51 @@ found:
+       return 0;
+ }
++static int early_nvram_init_nflash(void)
++{
++      struct nvram_header *header;
++      u32 off;
++      int ret;
++      int len;
++      u32 flash_size = bcm47xx_nflash.size;
++      u8 tmpbuf[NFL_SECTOR_SIZE];
++      int i;
++      u32 *src, *dst;
++
++      /* check if the struct is already initilized */
++      if (!flash_size)
++              return -1;
++      
++      cfe_env = 0;
++
++      off = FLASH_MIN;
++      while (off <= flash_size) {
++              ret = bcma_nflash_read(bcm47xx_nflash.bcc, off, NFL_SECTOR_SIZE, tmpbuf);
++              if (ret != NFL_SECTOR_SIZE)
++                      goto done;
++              header = (struct nvram_header *)tmpbuf;
++              if (header->magic == NVRAM_HEADER)
++                      goto found;
++              off <<= 1;
++      }
++
++      ret = -1;
++      goto done;
++
++found:
++      len = header->len;
++      header = (struct nvram_header *) KSEG1ADDR(NAND_FLASH1 + off);
++      src = (u32 *) header;
++      dst = (u32 *) nvram_buf;
++      for (i = 0; i < sizeof(struct nvram_header); i += 4)
++              *dst++ = *src++;
++      for (; i < len && i < NVRAM_SPACE; i += 4)
++              *dst++ = *src++;
++      ret = 0;
++done:
++      return ret;
++}
++
+ static void early_nvram_init(void)
+ {
+       int err = 0;
+@@ -163,6 +210,10 @@ static void early_nvram_init(void)
+                       err = early_nvram_init_sflash();
+                       if (err < 0)
+                               printk(KERN_WARNING "can not read from flash: %i\n", err);
++              } else if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_NFLASH) {
++                      err = early_nvram_init_nflash();
++                      if (err < 0)
++                              printk(KERN_WARNING "can not read from nflash: %i\n", err);
+               } else {
+                       printk(KERN_WARNING "unknow flash type\n");
+               }
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -4,6 +4,7 @@
+  *  Copyright (C) 2006 Michael Buesch <m@bues.ch>
+  *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
+  *  Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
++ *  Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
+  *
+  *  This program is free software; you can redistribute  it and/or modify it
+  *  under  the terms of  the GNU General  Public License as published by the
+@@ -46,6 +47,7 @@ enum bcm47xx_bus_type bcm47xx_bus_type;
+ EXPORT_SYMBOL(bcm47xx_bus_type);
+ struct bcm47xx_sflash bcm47xx_sflash;
++struct bcm47xx_nflash bcm47xx_nflash;
+ static void bcm47xx_machine_restart(char *command)
+ {
+@@ -325,6 +327,9 @@ static void __init bcm47xx_register_bcma
+       if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_SFLASH)
+               bcm47xx_sflash_struct_bcma_init(&bcm47xx_sflash, &bcm47xx_bus.bcma.bus.drv_cc);
++      
++      if (bcm47xx_bus.bcma.bus.drv_cc.flash_type == BCMA_NFLASH)
++              bcm47xx_nflash_struct_bcma_init(&bcm47xx_nflash, &bcm47xx_bus.bcma.bus.drv_cc);
+ }
+ #endif
+@@ -395,6 +400,19 @@ static struct platform_device bcm47xx_sf
+       .num_resources  = 1,
+ };
++static struct resource bcm47xx_nflash_resource = {
++      .name   = "bcm47xx_nflash",
++      .start  = 0,
++      .end    = 0,
++      .flags  = 0,
++};
++
++static struct platform_device bcm47xx_nflash_dev = {
++      .name           = "bcm47xx_nflash",
++      .resource       = &bcm47xx_nflash_resource,
++      .num_resources  = 1,
++};
++
+ static int __init bcm47xx_register_flash(void)
+ {
+ #ifdef CONFIG_BCM47XX_SSB
+@@ -429,6 +447,9 @@ static int __init bcm47xx_register_flash
+               } else if (drv_cc->flash_type == BCMA_SFLASH) {
+                       bcm47xx_sflash_dev.dev.platform_data = &bcm47xx_sflash;
+                       return platform_device_register(&bcm47xx_sflash_dev);
++              } else if (drv_cc->flash_type == BCMA_NFLASH) {
++                      bcm47xx_nflash_dev.dev.platform_data = &bcm47xx_nflash;
++                      return platform_device_register(&bcm47xx_nflash_dev);
+               } else {
+                       printk(KERN_ERR "No flash device found\n");
+                       return -1;
+--- a/arch/mips/include/asm/mach-bcm47xx/bus.h
++++ b/arch/mips/include/asm/mach-bcm47xx/bus.h
+@@ -2,6 +2,7 @@
+  * BCM947xx nvram variable access
+  *
+  * Copyright (C) 2011 Hauke Mehrtens <hauke@hauke-m.de>
++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
+  *
+  * This program is free software; you can redistribute  it and/or modify it
+  * under  the terms of  the GNU General  Public License as published by the
+@@ -13,6 +14,7 @@
+ #include <linux/bcma/bcma.h>
+ #include <linux/mtd/mtd.h>
+ #include <bcm47xx.h>
++#include <linux/mtd/nand.h>
+ struct bcm47xx_sflash {
+       enum bcm47xx_bus_type sflash_type;
+@@ -38,3 +40,18 @@ void bcm47xx_sflash_struct_bcma_init(str
+ void bcm47xx_sflash_struct_ssb_init(struct bcm47xx_sflash *sflash, struct ssb_chipcommon *scc);
+ extern struct bcm47xx_sflash bcm47xx_sflash;
++
++struct bcm47xx_nflash {
++      enum bcm47xx_bus_type nflash_type;
++      struct bcma_drv_cc *bcc;
++
++      u32 size;               /* Total size in bytes */
++      u32 next_opcode; /* Next expected command from upper NAND layer */
++
++      struct mtd_info mtd;
++      struct nand_chip nand;
++};
++
++void bcm47xx_nflash_struct_bcma_init(struct bcm47xx_nflash *nflash, struct bcma_drv_cc *bcc);
++
++extern struct bcm47xx_nflash bcm47xx_nflash;
+--- a/drivers/bcma/bcma_private.h
++++ b/drivers/bcma/bcma_private.h
+@@ -46,6 +46,11 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr
+ int bcma_sflash_init(struct bcma_drv_cc *cc);
+ #endif /* CONFIG_BCMA_SFLASH */
++#ifdef CONFIG_BCMA_NFLASH
++/* driver_chipcommon_nflash.c */
++int bcma_nflash_init(struct bcma_drv_cc *cc);
++#endif /* CONFIG_BCMA_NFLASH */
++
+ #ifdef CONFIG_BCMA_HOST_PCI
+ /* host_pci.c */
+ extern int __init bcma_host_pci_init(void);
+--- /dev/null
++++ b/drivers/bcma/driver_chipcommon_nflash.c
+@@ -0,0 +1,154 @@
++/*
++ * BCMA nand flash interface
++ *
++ * Copyright 2011, Tathagata Das <tathagata@alumnux.com>
++ * Copyright 2010, Broadcom Corporation
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/bcma/bcma.h>
++#include <linux/bcma/bcma_driver_chipcommon.h>
++#include <linux/delay.h>
++#include <linux/mtd/bcm47xx_nand.h>
++#include <linux/mtd/nand.h>
++
++#include "bcma_private.h"
++
++/* Issue a nand flash command */
++static inline void bcma_nflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
++{
++      bcma_cc_write32(cc, NAND_CMD_START, opcode);
++      bcma_cc_read32(cc,  NAND_CMD_START);
++}
++
++/* Check offset and length */
++static int bcma_nflash_offset_is_valid(struct bcma_drv_cc *cc, u32 offset, u32 len, u32 mask)
++{
++      if ((offset & mask) != 0 || (len & mask) != 0) {
++              pr_err("%s(): Address is not aligned. offset: %x, len: %x, mask: %x\n", __func__, offset, len, mask);
++              return 1;
++      }
++
++      if ((((offset + len) >> 20) >= cc->nflash.size) &&
++              (((offset + len) & ((1 << 20) - 1)) != 0)) {
++              pr_err("%s(): Address is outside Flash memory region. offset: %x, len: %x, mask: %x\n", __func__, offset, len, mask);
++              return 1;
++      }
++
++      return 0;
++}
++
++/* Read len bytes starting at offset into buf. Returns number of bytes read. */
++int bcma_nflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len, u8 *buf)
++{
++      u32 mask;
++      int i;
++      u32 *to, val, res;
++
++      mask = NFL_SECTOR_SIZE - 1;
++      if (bcma_nflash_offset_is_valid(cc, offset, len, mask))
++              return 0;
++
++      to = (u32 *)buf;
++      res = len;
++      while (res > 0) {
++              bcma_cc_write32(cc, NAND_CMD_ADDR, offset);
++              bcma_nflash_cmd(cc, NCMD_PAGE_RD);
++              if (bcma_nflash_poll(cc) < 0)
++                      break;
++              val = bcma_cc_read32(cc, NAND_INTFC_STATUS);
++              if ((val & NIST_CACHE_VALID) == 0)
++                      break;
++              bcma_cc_write32(cc, NAND_CACHE_ADDR, 0);
++              for (i = 0; i < NFL_SECTOR_SIZE; i += 4, to++) {
++                      *to = bcma_cc_read32(cc, NAND_CACHE_DATA);
++              }
++              res -= NFL_SECTOR_SIZE;
++              offset += NFL_SECTOR_SIZE;
++      }
++      return (len - res);
++}
++
++#define NF_RETRIES   1000000
++
++/* Poll for command completion. Returns zero when complete. */
++int bcma_nflash_poll(struct bcma_drv_cc *cc)
++{
++      u32 retries = NF_RETRIES;
++      u32 pollmask = NIST_CTRL_READY|NIST_FLASH_READY;
++      u32 mask;
++
++      while (retries--) {
++              mask = bcma_cc_read32(cc, NAND_INTFC_STATUS) & pollmask;
++              if (mask == pollmask)
++                      return 0;
++              cpu_relax();
++      }
++
++      if (!retries) {
++              pr_err("bcma_nflash_poll: not ready\n");
++              return -1;
++      }
++
++      return 0;
++}
++
++/* Write len bytes starting at offset into buf. Returns success (0) or failure (!0).
++ * Should poll for completion.
++ */
++int bcma_nflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
++                          const u8 *buf)
++{
++      u32 mask;
++      int i;
++      u32 *from, res, reg;
++
++      mask = cc->nflash.pagesize - 1;
++      if (bcma_nflash_offset_is_valid(cc, offset, len, mask))
++              return 1;
++      
++      /* disable partial page enable */
++      reg = bcma_cc_read32(cc, NAND_ACC_CONTROL);
++      reg &= ~NAC_PARTIAL_PAGE_EN;
++      bcma_cc_write32(cc, NAND_ACC_CONTROL, reg);
++
++      from = (u32 *)buf;
++      res = len;
++      while (res > 0) {
++              bcma_cc_write32(cc, NAND_CACHE_ADDR, 0);
++              for (i = 0; i < cc->nflash.pagesize; i += 4, from++) {
++                      if (i % 512 == 0)
++                              bcma_cc_write32(cc, NAND_CMD_ADDR, i);
++                      bcma_cc_write32(cc, NAND_CACHE_DATA, *from);
++              }
++              bcma_cc_write32(cc, NAND_CMD_ADDR, offset + cc->nflash.pagesize - 512);
++              bcma_nflash_cmd(cc, NCMD_PAGE_PROG);
++              if (bcma_nflash_poll(cc) < 0)
++                      break;
++              res -= cc->nflash.pagesize;
++              offset += cc->nflash.pagesize;
++      }
++
++      if (res <= 0)
++              return 0;
++      else
++              return (len - res);
++}
++
++/* Erase a region. Returns success (0) or failure (-1). 
++ * Poll for completion.
++ */
++int bcma_nflash_erase(struct bcma_drv_cc *cc, u32 offset)
++{
++      if ((offset >> 20) >= cc->nflash.size)
++              return -1;
++      if ((offset & (cc->nflash.blocksize - 1)) != 0)
++              return -1;
++
++      bcma_cc_write32(cc, NAND_CMD_ADDR, offset);
++      bcma_nflash_cmd(cc, NCMD_BLOCK_ERASE);
++      if (bcma_nflash_poll(cc) < 0)
++              return -1;
++      return 0;
++}
+--- a/drivers/bcma/driver_mips.c
++++ b/drivers/bcma/driver_mips.c
+@@ -6,6 +6,7 @@
+  * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+  * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
+  * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
+  *
+  * Licensed under the GNU/GPL. See COPYING for details.
+  */
+@@ -182,6 +183,17 @@ static void bcma_core_mips_flash_detect(
+ {
+       struct bcma_bus *bus = mcore->core->bus;
++      if (bus->drv_cc.core->id.rev == 38 
++              && (bus->drv_cc.status & (1 << 4)) != 0) {
++#ifdef CONFIG_BCMA_NFLASH
++              pr_info("found nand flash.\n");
++              bus->drv_cc.flash_type = BCMA_NFLASH;
++#else
++              pr_info("NAND flash not supported.\n");
++#endif
++              return;
++      }
++
+       switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
+       case BCMA_CC_FLASHT_STSER:
+       case BCMA_CC_FLASHT_ATSER:
+--- a/drivers/bcma/Kconfig
++++ b/drivers/bcma/Kconfig
+@@ -43,6 +43,11 @@ config BCMA_SFLASH
+       depends on BCMA_DRIVER_MIPS
+       default y
++config BCMA_NFLASH
++      bool
++      depends on BCMA_DRIVER_MIPS
++      default y
++
+ config BCMA_DRIVER_MIPS
+       bool "BCMA Broadcom MIPS core driver"
+       depends on BCMA && MIPS
+--- a/drivers/bcma/Makefile
++++ b/drivers/bcma/Makefile
+@@ -1,6 +1,7 @@
+ bcma-y                                        += main.o scan.o core.o sprom.o
+ bcma-y                                        += driver_chipcommon.o driver_chipcommon_pmu.o
+ bcma-$(CONFIG_BCMA_SFLASH)            += driver_chipcommon_sflash.o
++bcma-$(CONFIG_BCMA_NFLASH)            += driver_chipcommon_nflash.o
+ bcma-y                                        += driver_pci.o
+ bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE)       += driver_pci_host.o
+ bcma-$(CONFIG_BCMA_DRIVER_MIPS)               += driver_mips.o
+--- /dev/null
++++ b/drivers/mtd/nand/bcm47xx_nand.c
+@@ -0,0 +1,506 @@
++/*
++ * BCMA nand flash interface
++ *
++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
++ * Copyright 2010, Broadcom Corporation
++ *
++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
++ *
++ */
++
++#define pr_fmt(fmt) "bcm47xx_nflash: " fmt
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/ioport.h>
++#include <linux/sched.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <bcm47xx.h>
++#include <bus.h>
++#include <linux/cramfs_fs.h>
++#include <linux/romfs_fs.h>
++#include <linux/magic.h>
++#include <linux/byteorder/generic.h>
++#include <linux/mtd/bcm47xx_nand.h>
++#include <linux/mtd/nand.h>
++
++static int bcm47xx_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip);
++static int bcm47xx_erase(struct mtd_info *mtd, unsigned int addr, unsigned int len);
++
++/* Private Global variable */
++static u32 read_offset = 0;
++static u32 write_offset;
++
++static int
++nflash_mtd_poll(struct bcm47xx_nflash *nflash, unsigned int offset, int timeout)
++{
++      unsigned long now = jiffies;
++      int ret = 0;
++
++      for (;;) {
++              if (!bcma_nflash_poll(nflash->bcc)) {
++                      ret = 0;
++                      break;
++              }
++              if (time_after(jiffies, now + timeout)) {
++                      pr_err("timeout while polling\n");
++                      ret = -ETIMEDOUT;
++                      break;
++              }
++              udelay(1);
++      }
++
++      return ret;
++}
++
++static int
++bcm47xx_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
++{
++      struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
++      struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
++      int bytes, ret = 0;
++      u32 extra = 0;
++      u8 *tmpbuf = NULL;
++      int size;
++      u32 offset, blocksize, mask, off;
++      u32 skip_bytes = 0;
++      int need_copy = 0;
++      u8 *ptr = NULL;
++
++      /* Check address range */
++      if (!len)
++              return 0;
++      if ((from + len) > mtd->size)
++              return -EINVAL;
++      offset = from;
++      if ((offset & (NFL_SECTOR_SIZE - 1)) != 0) {
++              extra = offset & (NFL_SECTOR_SIZE - 1);
++              offset -= extra;
++              len += extra;
++              need_copy = 1;
++      }
++      size = (len + (NFL_SECTOR_SIZE - 1)) & ~(NFL_SECTOR_SIZE - 1);
++      if (size != len) {
++              need_copy = 1;
++      }
++      if (!need_copy) {
++              ptr = buf;
++      } else {
++              tmpbuf = (u8 *)kmalloc(size, GFP_KERNEL);
++              ptr = tmpbuf;
++      }
++
++      blocksize = mtd->erasesize;
++      mask = blocksize - 1;
++      *retlen = 0;
++      while (len > 0) {
++              off = offset + skip_bytes;
++              if ((bytes = bcma_nflash_read(nflash->bcc, off, NFL_SECTOR_SIZE, ptr)) < 0) {
++                      ret = bytes;
++                      goto done;
++              }
++              if (bytes > len)
++                      bytes = len;
++              offset += bytes;
++              len -= bytes;
++              ptr += bytes;
++              *retlen += bytes;
++      }
++
++done:
++      if (tmpbuf) {
++              *retlen -= extra;
++              memcpy(buf, tmpbuf+extra, *retlen);
++              kfree(tmpbuf);
++      }
++
++      return ret;
++}
++
++static void bcm47xx_write(struct mtd_info *mtd, u32 to, const u_char *buf, u32 len)
++{
++      struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
++      struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
++      u32 offset, blocksize, mask, off;
++      int read_len;
++      u32 copy_len, write_len, from;
++      u_char *write_ptr, *block;
++      const u_char *ptr;
++      int ret, bytes;
++
++      /* Check address range */
++      if (!len) {
++              pr_err("Error: Attempted to write too small data\n");
++              return;
++      }
++
++      if (!to)
++              return;
++
++      if ((to + len) > mtd->size) {
++              pr_err("Error: Attempted to write too large data\n");
++              return;
++      }
++
++      ptr = buf;
++      block = NULL;
++      offset = to;
++      blocksize = mtd->erasesize;
++      if (!(block = kmalloc(blocksize, GFP_KERNEL)))
++              return;
++      mask = blocksize - 1;
++      while (len) {
++              /* Align offset */
++              from = offset & ~mask;
++              /* Copy existing data into holding block if necessary */
++              if (((offset & (blocksize-1)) != 0) || (len < blocksize)) {
++                      if ((ret = bcm47xx_read(mtd, from, blocksize, &read_len, block)))
++                              goto done;
++                      if (read_len != blocksize) {
++                              ret = -EINVAL;
++                              goto done;
++                      }
++              }
++      
++              /* Copy input data into holding block */
++              copy_len = min(len, blocksize - (offset & mask));
++              memcpy(block + (offset & mask), ptr, copy_len);
++              off = (uint) from;
++              /* Erase block */
++              if ((ret = bcm47xx_erase(mtd, off, blocksize)) < 0)
++                      goto done;
++              /* Write holding block */
++              write_ptr = block;
++              write_len = blocksize;
++              if ((bytes = bcma_nflash_write(nflash->bcc, (uint)from, (uint)write_len, (u8 *) write_ptr)) != 0) {
++                      ret = bytes;
++                      goto done;
++              }
++              offset += copy_len;
++              if (len < copy_len)
++                      len = 0;
++              else
++                      len -= copy_len;
++              ptr += copy_len;
++      }
++
++done:
++      if (block)
++              kfree(block);
++      return;
++}
++
++static int bcm47xx_erase(struct mtd_info *mtd, unsigned int addr, unsigned int len)
++{
++      struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
++      struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
++
++      /* Check address range */
++      if (!len)
++              return 1;
++      if ((addr + len) > mtd->size)
++              return 1;
++
++      if (bcma_nflash_erase(nflash->bcc, addr)) {
++              pr_err("ERASE: nflash erase error\n");
++              return 1;
++      }
++
++      if (nflash_mtd_poll(nflash, addr, 10 * HZ)) {
++              pr_err("ERASE: nflash_mtd_poll error\n");
++              return 1;
++      }
++      
++      return 0;
++}
++
++/* This functions is used by upper layer to checks if device is ready */
++static int bcm47xx_dev_ready(struct mtd_info *mtd)
++{
++      return 1;
++}
++
++/* Issue a nand flash command */
++static inline void bcm47xx_nflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
++{
++      bcma_cc_write32(cc, NAND_CMD_START, opcode);
++      bcma_cc_read32(cc,  NAND_CMD_START);
++}
++
++static void bcm47xx_command(struct mtd_info *mtd, unsigned command,
++                              int column, int page_addr)
++{
++      struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
++      struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
++      u32 pagesize = 1 << nchip->page_shift;
++
++      /* Command pre-processing step */
++      switch (command) {
++      case NAND_CMD_RESET:
++              bcm47xx_nflash_cmd(nflash->bcc, NCMD_FLASH_RESET);
++              break;
++
++      case NAND_CMD_STATUS:
++              nflash->next_opcode = NAND_CMD_STATUS;
++              read_offset = 0;
++              write_offset = 0;
++              break;
++
++      case NAND_CMD_READ0:
++              read_offset = page_addr * pagesize;
++              nflash->next_opcode = 0;
++              break;
++
++      case NAND_CMD_READOOB:
++              read_offset = page_addr * pagesize;
++              nflash->next_opcode = 0;
++              break;
++
++      case NAND_CMD_SEQIN:
++              write_offset = page_addr * pagesize;
++              nflash->next_opcode = 0;
++              break;
++
++      case NAND_CMD_PAGEPROG:
++              nflash->next_opcode = 0;
++              break;
++
++      case NAND_CMD_READID:
++              read_offset = column;
++              bcm47xx_nflash_cmd(nflash->bcc, NCMD_ID_RD);
++              nflash->next_opcode = NAND_DEVID;
++              break;
++
++      case NAND_CMD_ERASE1:
++              nflash->next_opcode = 0;
++              bcm47xx_erase(mtd, page_addr*pagesize, pagesize);
++              break;
++      
++      case NAND_CMD_ERASE2:
++              break;
++
++      case NAND_CMD_RNDOUT:
++              if (column > mtd->writesize)
++                      read_offset += (column - mtd->writesize);
++              else 
++                      read_offset += column;
++              break;
++
++      default:
++              pr_err("COMMAND not supported %x\n", command);
++              nflash->next_opcode = 0;
++              break;
++      }
++}
++
++/* This function is used by upper layer for select and
++ * deselect of the NAND chip.
++ * It is dummy function. */
++static void bcm47xx_select_chip(struct mtd_info *mtd, int chip)
++{
++}
++
++static u_char bcm47xx_read_byte(struct mtd_info *mtd)
++{
++      struct nand_chip *nchip = mtd->priv;
++      struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
++      uint8_t ret = 0;
++      static u32 id;
++
++      if (nflash->next_opcode == 0)
++              return ret;
++
++      if (nflash->next_opcode == NAND_CMD_STATUS)
++              return NAND_STATUS_WP; 
++
++      id = bcma_cc_read32(nflash->bcc, nflash->next_opcode);
++
++      if (nflash->next_opcode == NAND_DEVID) {
++              ret = (id >> (8*read_offset)) & 0xff;
++              read_offset++;
++      }
++
++      return ret;
++}
++
++static uint16_t bcm47xx_read_word(struct mtd_info *mtd)
++{
++      loff_t from = read_offset;
++      uint16_t buf = 0;
++      int bytes;
++
++      bcm47xx_read(mtd, from, sizeof(buf), &bytes, (u_char *)&buf);
++      return buf;
++}
++
++/* Write data of length len to buffer buf. The data to be
++ * written on NAND Flash is first copied to RAMbuffer. After the Data Input
++ * Operation by the NFC, the data is written to NAND Flash */
++static void bcm47xx_write_buf(struct mtd_info *mtd,
++                              const u_char *buf, int len)
++{
++      bcm47xx_write(mtd, write_offset, buf, len);
++}
++
++/* Read the data buffer from the NAND Flash. To read the data from NAND
++ * Flash first the data output cycle is initiated by the NFC, which copies
++ * the data to RAMbuffer. This data of length len is then copied to buffer buf.
++ */
++static void bcm47xx_read_buf(struct mtd_info *mtd, u_char *buf, int len)
++{
++      loff_t from = read_offset;
++      int bytes;
++
++      bcm47xx_read(mtd, from, len, &bytes, buf);
++}
++
++/* Used by the upper layer to verify the data in NAND Flash
++ * with the data in the buf. */
++static int bcm47xx_verify_buf(struct mtd_info *mtd,
++                              const u_char *buf, int len)
++{
++      return -EFAULT;
++}
++
++static int bcm47xx_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
++{
++      struct nand_chip *nchip = mtd->priv;
++      struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
++      int i;
++      uint off;
++      u32 pagesize = 1 << nchip->page_shift;
++      u32 blocksize = mtd->erasesize;
++
++      if ((ofs >> 20) >= nflash->size)
++              return 1;
++      if ((ofs & (blocksize - 1)) != 0)
++              return 1;
++
++      for (i = 0; i < 2; i++) {
++              off = ofs + pagesize;
++              bcma_cc_write32(nflash->bcc, NAND_CMD_ADDR, off);
++              bcm47xx_nflash_cmd(nflash->bcc, NCMD_SPARE_RD);
++              if (bcma_nflash_poll(nflash->bcc) < 0)
++                      break;
++              if ((bcma_cc_read32(nflash->bcc, NAND_INTFC_STATUS) & NIST_SPARE_VALID) != NIST_SPARE_VALID)
++                      return 1;
++              if ((bcma_cc_read32(nflash->bcc, NAND_SPARE_RD0) & 0xff) != 0xff)
++                      return 1;
++      }
++      return 0;
++}
++
++const char *part_probes[] = { "cmdlinepart", NULL };
++static int bcm47xx_probe(struct platform_device *pdev)
++{
++      struct nand_chip *nchip;
++      struct mtd_info *mtd;
++      struct bcm47xx_nflash *nflash = dev_get_platdata(&pdev->dev);
++      int ret = 0;
++
++      mtd = &nflash->mtd;
++      nchip = &nflash->nand;
++
++      /* Register with MTD */
++      mtd->priv = nchip;
++      mtd->owner = THIS_MODULE;
++      mtd->dev.parent = &pdev->dev;
++
++      /* 50 us command delay time */
++      nchip->chip_delay = 50;
++
++      nchip->priv = nflash;
++      nchip->dev_ready = bcm47xx_dev_ready;
++      nchip->cmdfunc = bcm47xx_command;
++      nchip->select_chip = bcm47xx_select_chip;
++      nchip->read_byte = bcm47xx_read_byte;
++      nchip->read_word = bcm47xx_read_word;
++      nchip->write_buf = bcm47xx_write_buf;
++      nchip->read_buf = bcm47xx_read_buf;
++      nchip->verify_buf = bcm47xx_verify_buf;
++      nchip->block_bad = bcm47xx_block_bad;
++      nchip->options = NAND_SKIP_BBTSCAN;
++
++      /* Not known */
++      nchip->ecc.mode = NAND_ECC_NONE;
++
++      /* first scan to find the device and get the page size */
++      if (nand_scan_ident(mtd, 1, NULL)) {
++              pr_err("nand_scan_ident failed\n");
++              ret = -ENXIO;
++              goto done;
++      }
++      nflash->bcc->nflash.size = mtd->size;
++      nflash->bcc->nflash.pagesize = 1 << nchip->page_shift;
++      nflash->bcc->nflash.blocksize = mtd->erasesize;
++      bcm47xx_nflash.size = mtd->size;
++
++      /* second phase scan */
++      if (nand_scan_tail(mtd)) {
++              pr_err("nand_scan_tail failed\n");
++              ret = -ENXIO;
++              goto done;
++      }
++
++      mtd->name = "bcm47xx-nflash";
++      mtd->flags |= MTD_WRITEABLE;
++      ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL, 0);
++
++      if (ret) {
++              pr_err("mtd_device_register failed\n");
++              return ret;
++      }
++      
++      return 0;
++
++done:
++      return ret;
++}
++
++static int __devexit bcm47xx_remove(struct platform_device *pdev)
++{
++      struct bcm47xx_nflash *nflash = dev_get_platdata(&pdev->dev);
++      struct mtd_info *mtd = &nflash->mtd;
++
++      if (nflash) {
++              /* Release resources, unregister device */
++              nand_release(mtd);
++      }
++
++      return 0;
++}
++
++static struct platform_driver bcm47xx_driver = {
++      .remove = __devexit_p(bcm47xx_remove),
++      .driver = {
++              .name = "bcm47xx_nflash",
++              .owner = THIS_MODULE,
++      },
++};
++
++static int __init init_bcm47xx_nflash(void)
++{
++      int ret = platform_driver_probe(&bcm47xx_driver, bcm47xx_probe);
++
++      if (ret)
++              pr_err("error registering platform driver: %i\n", ret);
++      return ret;
++}
++
++static void __exit exit_bcm47xx_nflash(void)
++{
++      platform_driver_unregister(&bcm47xx_driver);
++}
++
++module_init(init_bcm47xx_nflash);
++module_exit(exit_bcm47xx_nflash);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("BCM47XX NAND flash driver");
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -537,4 +537,12 @@ config MTD_NAND_FSMC
+         Enables support for NAND Flash chips on the ST Microelectronics
+         Flexible Static Memory Controller (FSMC)
++config MTD_NAND_BCM47XX
++      tristate "bcm47xx nand flash support"
++      default y
++      depends on BCM47XX
++      select MTD_PARTITIONS
++      help
++        Support for bcm47xx nand flash
++
+ endif # MTD_NAND
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -49,5 +49,6 @@ obj-$(CONFIG_MTD_NAND_MPC5121_NFC)   += mp
+ obj-$(CONFIG_MTD_NAND_RICOH)          += r852.o
+ obj-$(CONFIG_MTD_NAND_JZ4740)         += jz4740_nand.o
+ obj-$(CONFIG_MTD_NAND_GPMI_NAND)      += gpmi-nand/
++obj-$(CONFIG_MTD_NAND_BCM47XX)                += bcm47xx_nand.o
+ nand-objs := nand_base.o nand_bbt.o
+--- a/include/linux/bcma/bcma_driver_chipcommon.h
++++ b/include/linux/bcma/bcma_driver_chipcommon.h
+@@ -376,6 +376,7 @@ struct bcma_chipcommon_pmu {
+ enum bcma_flash_type {
+       BCMA_PFLASH,
+       BCMA_SFLASH,
++      BCMA_NFLASH,
+ };
+ struct bcma_pflash {
+@@ -392,6 +393,14 @@ struct bcma_sflash {
+ };
+ #endif /* CONFIG_BCMA_SFLASH */
++#ifdef CONFIG_BCMA_NFLASH
++struct bcma_nflash {
++      u32 blocksize;          /* Block size */
++      u32 pagesize;           /* Page size */
++      u32 size;               /* Total size in bytes */
++};
++#endif
++
+ struct bcma_serial_port {
+       void *regs;
+       unsigned long clockspeed;
+@@ -417,6 +426,9 @@ struct bcma_drv_cc {
+ #ifdef CONFIG_BCMA_SFLASH
+               struct bcma_sflash sflash;
+ #endif /* CONFIG_BCMA_SFLASH */
++#ifdef CONFIG_BCMA_NFLASH
++              struct bcma_nflash nflash;
++#endif
+       };
+       int nr_serial_ports;
+@@ -483,4 +495,13 @@ int bcma_sflash_commit(struct bcma_drv_c
+                            const u8 *buf);
+ #endif /* CONFIG_BCMA_SFLASH */
++#ifdef CONFIG_BCMA_NFLASH
++/* Chipcommon nflash support. */
++int bcma_nflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len, u8 *buf);
++int bcma_nflash_poll(struct bcma_drv_cc *cc);
++int bcma_nflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len, const u8 *buf);
++int bcma_nflash_erase(struct bcma_drv_cc *cc, u32 offset);
++int bcma_nflash_commit(struct bcma_drv_cc *cc, u32 offset, u32 len, const u8 *buf);
++#endif
++
+ #endif /* LINUX_BCMA_DRIVER_CC_H_ */
+--- /dev/null
++++ b/include/linux/mtd/bcm47xx_nand.h
+@@ -0,0 +1,134 @@
++/*
++ * Broadcom chipcommon NAND flash interface
++ *
++ * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
++ * Copyright (C) 2009, Broadcom Corporation
++ * All Rights Reserved.
++ * 
++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
++ *
++ */
++
++#ifndef _nflash_h_
++#define _nflash_h_
++
++#define  NAND_FLASH1                                          0x1fc00000  /* MIPS Flash Region 1 */
++
++/* nand_cmd_start commands */
++#define       NCMD_NULL                                               0
++#define       NCMD_PAGE_RD                                    1
++#define       NCMD_SPARE_RD                                   2
++#define       NCMD_STATUS_RD                                  3
++#define       NCMD_PAGE_PROG                                  4
++#define       NCMD_SPARE_PROG                         5
++#define       NCMD_COPY_BACK                                  6
++#define       NCMD_ID_RD                                              7
++#define       NCMD_BLOCK_ERASE                                8
++#define       NCMD_FLASH_RESET                                9
++#define       NCMD_LOCK                                               0xa
++#define       NCMD_LOCK_DOWN                                  0xb
++#define       NCMD_UNLOCK                                             0xc
++#define       NCMD_LOCK_STATUS                                0xd
++
++/* nand_acc_control */
++#define       NAC_RD_ECC_EN                                   0x80000000
++#define       NAC_WR_ECC_EN                                   0x40000000
++#define       NAC_RD_ECC_BLK0_EN                      0x20000000
++#define       NAC_FAST_PGM_RDIN                               0x10000000
++#define       NAC_RD_ERASED_ECC_EN                    0x08000000
++#define       NAC_PARTIAL_PAGE_EN                     0x04000000
++#define       NAC_PAGE_HIT_EN                         0x01000000
++#define       NAC_ECC_LEVEL0                                  0x00f00000
++#define       NAC_ECC_LEVEL                                   0x000f0000
++#define       NAC_SPARE_SIZE0                         0x00003f00
++#define       NAC_SPARE_SIZE                                  0x0000003f
++
++/* nand_config */
++#define       NCF_CONFIG_LOCK                         0x80000000
++#define       NCF_BLOCK_SIZE_MASK                     0x70000000
++#define       NCF_BLOCK_SIZE_SHIFT                    28
++#define       NCF_DEVICE_SIZE_MASK                    0x0f000000
++#define       NCF_DEVICE_SIZE_SHIFT           24
++#define       NCF_DEVICE_WIDTH                                0x00800000
++#define       NCF_PAGE_SIZE_MASK                      0x00300000
++#define       NCF_PAGE_SIZE_SHIFT                     20
++#define       NCF_FULL_ADDR_BYTES_MASK        0x00070000
++#define       NCF_FULL_ADDR_BYTES_SHIFT       16
++#define       NCF_COL_ADDR_BYTES_MASK         0x00007000
++#define       NCF_COL_ADDR_BYTES_SHIFT        12
++#define       NCF_BLK_ADDR_BYTES_MASK         0x00000700
++#define       NCF_BLK_ADDR_BYTES_SHIFT        8
++
++/* nand_intfc_status */
++#define       NIST_CTRL_READY                         0x80000000
++#define       NIST_FLASH_READY                                0x40000000
++#define       NIST_CACHE_VALID                                0x20000000
++#define       NIST_SPARE_VALID                                0x10000000
++#define       NIST_ERASED                                             0x08000000
++#define       NIST_STATUS                                             0x000000ff
++
++#define       NFL_SECTOR_SIZE                         512
++
++#define       NFL_TABLE_END                                   0xffffffff
++#define       NFL_BOOT_SIZE                                   0x200000
++#define       NFL_BOOT_OS_SIZE                                0x2000000
++
++/* Nand flash MLC controller registers (corerev >= 38) */
++#define       NAND_REVISION                                   0xC00
++#define       NAND_CMD_START                                  0xC04
++#define       NAND_CMD_ADDR_X                         0xC08
++#define       NAND_CMD_ADDR                                   0xC0C
++#define       NAND_CMD_END_ADDR                               0xC10
++#define       NAND_CS_NAND_SELECT                     0xC14
++#define       NAND_CS_NAND_XOR                                0xC18
++#define       NAND_SPARE_RD0                                  0xC20
++#define       NAND_SPARE_RD4                                  0xC24
++#define       NAND_SPARE_RD8                                  0xC28
++#define       NAND_SPARE_RD12                         0xC2C
++#define       NAND_SPARE_WR0                                  0xC30
++#define       NAND_SPARE_WR4                                  0xC34
++#define       NAND_SPARE_WR8                                  0xC38
++#define       NAND_SPARE_WR12                         0xC3C
++#define       NAND_ACC_CONTROL                                0xC40
++#define       NAND_CONFIG                                             0xC48
++#define       NAND_TIMING_1                                   0xC50
++#define       NAND_TIMING_2                                   0xC54
++#define       NAND_SEMAPHORE                                  0xC58
++#define       NAND_DEVID                                              0xC60
++#define       NAND_DEVID_X                                    0xC64
++#define       NAND_BLOCK_LOCK_STATUS          0xC68
++#define       NAND_INTFC_STATUS                               0xC6C
++#define       NAND_ECC_CORR_ADDR_X                    0xC70
++#define       NAND_ECC_CORR_ADDR                      0xC74
++#define       NAND_ECC_UNC_ADDR_X                     0xC78
++#define       NAND_ECC_UNC_ADDR                               0xC7C
++#define       NAND_READ_ERROR_COUNT           0xC80
++#define       NAND_CORR_STAT_THRESHOLD        0xC84
++#define       NAND_READ_ADDR_X                                0xC90
++#define       NAND_READ_ADDR                                  0xC94
++#define       NAND_PAGE_PROGRAM_ADDR_X        0xC98
++#define       NAND_PAGE_PROGRAM_ADDR          0xC9C
++#define       NAND_COPY_BACK_ADDR_X           0xCA0
++#define       NAND_COPY_BACK_ADDR                     0xCA4
++#define       NAND_BLOCK_ERASE_ADDR_X         0xCA8
++#define       NAND_BLOCK_ERASE_ADDR           0xCAC
++#define       NAND_INV_READ_ADDR_X                    0xCB0
++#define       NAND_INV_READ_ADDR                      0xCB4
++#define       NAND_BLK_WR_PROTECT                     0xCC0
++#define       NAND_ACC_CONTROL_CS1                    0xCD0
++#define       NAND_CONFIG_CS1                         0xCD4
++#define       NAND_TIMING_1_CS1                               0xCD8
++#define       NAND_TIMING_2_CS1                               0xCDC
++#define       NAND_SPARE_RD16                         0xD30
++#define       NAND_SPARE_RD20                         0xD34
++#define       NAND_SPARE_RD24                         0xD38
++#define       NAND_SPARE_RD28                         0xD3C
++#define       NAND_CACHE_ADDR                         0xD40
++#define       NAND_CACHE_DATA                         0xD44
++#define       NAND_CTRL_CONFIG                                0xD48
++#define       NAND_CTRL_STATUS                                0xD4C
++
++#endif /* _nflash_h_ */
index 70bb497bf220eae773ac9347e3e1bb2d1d5fa9eb..062a29d2f114a31103c56a0b642d110f8b65badf 100644 (file)
@@ -13,9 +13,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 
 --- a/drivers/bcma/bcma_private.h
 +++ b/drivers/bcma/bcma_private.h
-@@ -46,6 +46,8 @@ u32 bcma_pmu_get_clockcpu(struct bcma_dr
- int bcma_sflash_init(struct bcma_drv_cc *cc);
- #endif /* CONFIG_BCMA_SFLASH */
+@@ -51,6 +51,8 @@ int bcma_sflash_init(struct bcma_drv_cc
+ int bcma_nflash_init(struct bcma_drv_cc *cc);
+ #endif /* CONFIG_BCMA_NFLASH */
  
 +u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
 +
index 2534a3a6b7e4f15009358e77939b00b3903a8a4f..340172d44fac50d5f5b4369f629d4c2cdec9c982 100644 (file)
@@ -28,7 +28,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  void bcma_bus_unregister(struct bcma_bus *bus);
  int __init bcma_bus_early_register(struct bcma_bus *bus,
                                   struct bcma_device *core_cc,
-@@ -55,7 +55,7 @@ extern void __exit bcma_host_pci_exit(vo
+@@ -60,7 +60,7 @@ extern void __exit bcma_host_pci_exit(vo
  #endif /* CONFIG_BCMA_HOST_PCI */
  
  #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
index 2afd09aeed18e4d82996479a4acf778adff03b2d..850b52428d95130323a991f4f7134c467e2eed67 100644 (file)
@@ -96,7 +96,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +}
 --- a/drivers/bcma/bcma_private.h
 +++ b/drivers/bcma/bcma_private.h
-@@ -55,6 +55,7 @@ extern void __exit bcma_host_pci_exit(vo
+@@ -60,6 +60,7 @@ extern void __exit bcma_host_pci_exit(vo
  #endif /* CONFIG_BCMA_HOST_PCI */
  
  #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
index 12028c4a4f3300354f4c3fd42bea214e158719f8..ddf257b55be199032f4d0ffda86de0543b390ca5 100644 (file)
@@ -15,7 +15,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 
 --- a/arch/mips/bcm47xx/setup.c
 +++ b/arch/mips/bcm47xx/setup.c
-@@ -32,6 +32,8 @@
+@@ -33,6 +33,8 @@
  #include <linux/ssb/ssb_embedded.h>
  #include <linux/bcma/bcma_soc.h>
  #include <linux/platform_device.h>
@@ -24,7 +24,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  #include <asm/bootinfo.h>
  #include <asm/reboot.h>
  #include <asm/time.h>
-@@ -279,6 +281,31 @@ static int bcm47xx_get_invariants(struct
+@@ -281,6 +283,31 @@ static int bcm47xx_get_invariants(struct
        return 0;
  }
  
@@ -56,7 +56,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  static void __init bcm47xx_register_ssb(void)
  {
        int err;
-@@ -311,6 +338,10 @@ static void __init bcm47xx_register_ssb(
+@@ -313,6 +340,10 @@ static void __init bcm47xx_register_ssb(
                        memcpy(&mcore->serial_ports[1], &port, sizeof(port));
                }
        }
index 926ec844c78609001c1a16f14a5d0f65d9105a93..ce226f36e2374995d8b87d0dbcf7f5f243e611cf 100644 (file)
@@ -12,7 +12,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 
 --- a/arch/mips/bcm47xx/nvram.c
 +++ b/arch/mips/bcm47xx/nvram.c
-@@ -192,8 +192,7 @@ int nvram_getenv(char *name, char *val,
+@@ -243,8 +243,7 @@ int nvram_getenv(char *name, char *val,
                value = eq + 1;
                if ((eq - var) == strlen(name) &&
                        strncmp(var, name, (eq - var)) == 0) {
index a8272cd4c0f211bd86f64718cc8a61834ba4d6f0..b817d8adfff7ca7504b626d252adc26f82c68c81 100644 (file)
@@ -28,7 +28,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  obj-$(CONFIG_BCM47XX_SSB)     += wgt634u.o
 --- a/arch/mips/bcm47xx/setup.c
 +++ b/arch/mips/bcm47xx/setup.c
-@@ -91,156 +91,7 @@ static void bcm47xx_machine_halt(void)
+@@ -93,156 +93,7 @@ static void bcm47xx_machine_halt(void)
  }
  
  #ifdef CONFIG_BCM47XX_SSB
index e3d2527929518449609b2fd473947160dc517b48..c96813c85705fb04771f2a3d55c2327c2d616c03 100644 (file)
@@ -20,10 +20,10 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
   *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
 - *  Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
 + *  Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
+  *  Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
   *
   *  This program is free software; you can redistribute  it and/or modify it
-  *  under  the terms of  the GNU General  Public License as published by the
-@@ -91,7 +91,7 @@ static void bcm47xx_machine_halt(void)
+@@ -93,7 +93,7 @@ static void bcm47xx_machine_halt(void)
  }
  
  #ifdef CONFIG_BCM47XX_SSB
@@ -32,7 +32,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  {
        char prefix[10];
  
-@@ -108,7 +108,7 @@ static int bcm47xx_get_sprom(struct ssb_
+@@ -110,7 +110,7 @@ static int bcm47xx_get_sprom(struct ssb_
  }
  
  static int bcm47xx_get_invariants(struct ssb_bus *bus,
@@ -41,7 +41,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  {
        char buf[20];
  
-@@ -163,7 +163,7 @@ static void __init bcm47xx_register_ssb(
+@@ -165,7 +165,7 @@ static void __init bcm47xx_register_ssb(
        char buf[100];
        struct ssb_mipscore *mcore;
  
@@ -50,7 +50,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
        if (err)
                printk(KERN_WARNING "bcm47xx: someone else already registered"
                        " a ssb SPROM callback handler (err %d)\n", err);
-@@ -197,10 +197,41 @@ static void __init bcm47xx_register_ssb(
+@@ -199,10 +199,41 @@ static void __init bcm47xx_register_ssb(
  #endif
  
  #ifdef CONFIG_BCM47XX_BCMA
index c991ed313f06822f93496cb345653f3bdc68f6a6..ae7b7d4dcd698155b28204d266d1dbdb317a4f68 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/bcm47xx/setup.c
 +++ b/arch/mips/bcm47xx/setup.c
-@@ -96,6 +96,7 @@ static int bcm47xx_get_sprom_ssb(struct
+@@ -98,6 +98,7 @@ static int bcm47xx_get_sprom_ssb(struct
        char prefix[10];
  
        if (bus->bustype == SSB_BUSTYPE_PCI) {
@@ -8,7 +8,7 @@
                snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
                         bus->host_pci->bus->number + 1,
                         PCI_SLOT(bus->host_pci->devfn));
-@@ -124,6 +125,7 @@ static int bcm47xx_get_invariants(struct
+@@ -126,6 +127,7 @@ static int bcm47xx_get_invariants(struct
        if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
                iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
  
@@ -16,7 +16,7 @@
        bcm47xx_fill_sprom(&iv->sprom, NULL);
  
        if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
-@@ -203,12 +205,14 @@ static int bcm47xx_get_sprom_bcma(struct
+@@ -205,12 +207,14 @@ static int bcm47xx_get_sprom_bcma(struct
        struct bcma_device *core;
  
        if (bus->hosttype == BCMA_HOSTTYPE_PCI) {
index 38a1fce6430a6f75b03a19ca643a446e43709726..df98b12d49c84fd8b627013c29f6b4f1e5790f0b 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/bcm47xx/nvram.c
 +++ b/arch/mips/bcm47xx/nvram.c
-@@ -198,3 +198,30 @@ int nvram_getenv(char *name, char *val,
+@@ -249,3 +249,30 @@ int nvram_getenv(char *name, char *val,
        return NVRAM_ERR_ENVNOTFOUND;
  }
  EXPORT_SYMBOL(nvram_getenv);
@@ -33,7 +33,7 @@
 +EXPORT_SYMBOL(nvram_get);
 --- a/arch/mips/bcm47xx/setup.c
 +++ b/arch/mips/bcm47xx/setup.c
-@@ -355,3 +355,20 @@ static int __init bcm47xx_register_flash
+@@ -376,3 +376,20 @@ static int __init bcm47xx_register_flash
        return -1;
  }
  fs_initcall(bcm47xx_register_flash);
index 3ccaa9557b00345975cd1f35d58790c51c5661f8..3414ad7310fb992bbb2247ba7f723abe8edf6bc3 100644 (file)
@@ -245,8 +245,8 @@ out the configuration than the in kernel cfe config reader.
 +
 --- a/arch/mips/bcm47xx/nvram.c
 +++ b/arch/mips/bcm47xx/nvram.c
-@@ -23,6 +23,8 @@
- #include <asm/mach-bcm47xx/bus.h>
+@@ -25,6 +25,8 @@
+ #include <linux/mtd/bcm47xx_nand.h>
  
  static char nvram_buf[NVRAM_SPACE];
 +static int cfe_env;
@@ -254,7 +254,7 @@ out the configuration than the in kernel cfe config reader.
  
  /* Probe for NVRAM header */
  static void early_nvram_init_pflash(void)
-@@ -59,6 +61,25 @@ static void early_nvram_init_pflash(void
+@@ -61,6 +63,25 @@ static void early_nvram_init_pflash(void
                break;
  #endif
        }
@@ -280,7 +280,7 @@ out the configuration than the in kernel cfe config reader.
  
        off = FLASH_MIN;
        while (off <= lim) {
-@@ -181,6 +202,12 @@ int nvram_getenv(char *name, char *val,
+@@ -232,6 +253,12 @@ int nvram_getenv(char *name, char *val,
        if (!nvram_buf[0])
                early_nvram_init();
  
@@ -293,7 +293,7 @@ out the configuration than the in kernel cfe config reader.
        /* Look for name=value and return value */
        var = &nvram_buf[sizeof(struct nvram_header)];
        end = nvram_buf + sizeof(nvram_buf) - 2;
-@@ -209,6 +236,9 @@ char *nvram_get(const char *name)
+@@ -260,6 +287,9 @@ char *nvram_get(const char *name)
        if (!nvram_buf[0])
                early_nvram_init();
  
index da43422d6fd3d6047554fe5d485e3e277f5cafc7..58dfd8afed50a7636f5ac9c9d0fb3fd437cb2925 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/bcm47xx/setup.c
 +++ b/arch/mips/bcm47xx/setup.c
-@@ -131,6 +131,10 @@ static int bcm47xx_get_invariants(struct
+@@ -133,6 +133,10 @@ static int bcm47xx_get_invariants(struct
        if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
                iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
  
index 5f8e8d3508b0843cb59c31f136bf5d213fa6d80d..550f4c968373ed2d656ffaacec924cbfed6afc67 100644 (file)
@@ -1,8 +1,8 @@
 --- a/arch/mips/bcm47xx/nvram.c
 +++ b/arch/mips/bcm47xx/nvram.c
-@@ -22,7 +22,8 @@
- #include <asm/mach-bcm47xx/bcm47xx.h>
+@@ -24,7 +24,8 @@
  #include <asm/mach-bcm47xx/bus.h>
+ #include <linux/mtd/bcm47xx_nand.h>
  
 -static char nvram_buf[NVRAM_SPACE];
 +char nvram_buf[NVRAM_SPACE];