kernel: update bcma and ssb to master-2012-10-18 from wireless-testing
[openwrt.git] / target / linux / brcm47xx / patches-3.3 / 021-bcma-add-serial-flash-support-to-bcma.patch
diff --git a/target/linux/brcm47xx/patches-3.3/021-bcma-add-serial-flash-support-to-bcma.patch b/target/linux/brcm47xx/patches-3.3/021-bcma-add-serial-flash-support-to-bcma.patch
deleted file mode 100644 (file)
index 7382636..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
---- a/drivers/bcma/Kconfig
-+++ b/drivers/bcma/Kconfig
-@@ -38,6 +38,11 @@ config BCMA_HOST_SOC
-       bool
-       depends on BCMA_DRIVER_MIPS
-+config BCMA_SFLASH
-+      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,5 +1,6 @@
- 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-y                                        += driver_pci.o
- bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE)       += driver_pci_host.o
- bcma-$(CONFIG_BCMA_DRIVER_MIPS)               += driver_mips.o
---- a/drivers/bcma/bcma_private.h
-+++ b/drivers/bcma/bcma_private.h
-@@ -51,6 +51,11 @@ void bcma_chipco_serial_init(struct bcma
- u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
- u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
-+#ifdef CONFIG_BCMA_SFLASH
-+/* driver_chipcommon_sflash.c */
-+int bcma_sflash_init(struct bcma_drv_cc *cc);
-+#endif /* CONFIG_BCMA_SFLASH */
-+
- #ifdef CONFIG_BCMA_HOST_PCI
- /* host_pci.c */
- extern int __init bcma_host_pci_init(void);
---- /dev/null
-+++ b/drivers/bcma/driver_chipcommon_sflash.c
-@@ -0,0 +1,398 @@
-+/*
-+ * Broadcom SiliconBackplane chipcommon serial flash interface
-+ *
-+ * Copyright 2011, Jonas Gorski <jonas.gorski@gmail.com>
-+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
-+ * 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 "bcma_private.h"
-+
-+#define NUM_RETRIES   3
-+
-+
-+/* Issue a serial flash command */
-+static inline void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
-+{
-+      bcma_cc_write32(cc, BCMA_CC_FLASHCTL,
-+                      BCMA_CC_FLASHCTL_START | opcode);
-+      while (bcma_cc_read32(cc, BCMA_CC_FLASHCTL) & BCMA_CC_FLASHCTL_BUSY)
-+              ;
-+}
-+
-+
-+static inline void bcma_sflash_write_u8(struct bcma_drv_cc *cc,
-+                                      u32 offset, u8 byte)
-+{
-+      bcma_cc_write32(cc, BCMA_CC_FLASHADDR, offset);
-+      bcma_cc_write32(cc, BCMA_CC_FLASHDATA, byte);
-+}
-+
-+/* Initialize serial flash access */
-+int bcma_sflash_init(struct bcma_drv_cc *cc)
-+{
-+      u32 id, id2;
-+
-+      memset(&cc->sflash, 0, sizeof(struct bcma_sflash));
-+
-+      switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
-+      case BCMA_CC_FLASHT_STSER:
-+              /* Probe for ST chips */
-+              bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_DP);
-+              bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 0);
-+              bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
-+              id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
-+              cc->sflash.blocksize = 64 * 1024;
-+              switch (id) {
-+              case 0x11:
-+                      /* ST M25P20 2 Mbit Serial Flash */
-+                      cc->sflash.numblocks = 4;
-+                      break;
-+              case 0x12:
-+                      /* ST M25P40 4 Mbit Serial Flash */
-+                      cc->sflash.numblocks = 8;
-+                      break;
-+              case 0x13:
-+                      /* ST M25P80 8 Mbit Serial Flash */
-+                      cc->sflash.numblocks = 16;
-+                      break;
-+              case 0x14:
-+                      /* ST M25P16 16 Mbit Serial Flash */
-+                      cc->sflash.numblocks = 32;
-+                      break;
-+              case 0x15:
-+                      /* ST M25P32 32 Mbit Serial Flash */
-+                      cc->sflash.numblocks = 64;
-+                      break;
-+              case 0x16:
-+                      /* ST M25P64 64 Mbit Serial Flash */
-+                      cc->sflash.numblocks = 128;
-+                      break;
-+              case 0x17:
-+                      /* ST M25FL128 128 Mbit Serial Flash */
-+                      cc->sflash.numblocks = 256;
-+                      break;
-+              case 0xbf:
-+                      /* All of the following flashes are SST with
-+                       * 4KB subsectors. Others should be added but
-+                       * We'll have to revamp the way we identify them
-+                       * since RES is not eough to disambiguate them.
-+                       */
-+                      cc->sflash.blocksize = 4 * 1024;
-+                      bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 1);
-+                      bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
-+                      id2 = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
-+                      switch (id2) {
-+                      case 1:
-+                              /* SST25WF512 512 Kbit Serial Flash */
-+                      case 0x48:
-+                              /* SST25VF512 512 Kbit Serial Flash */
-+                              cc->sflash.numblocks = 16;
-+                              break;
-+                      case 2:
-+                              /* SST25WF010 1 Mbit Serial Flash */
-+                      case 0x49:
-+                              /* SST25VF010 1 Mbit Serial Flash */
-+                              cc->sflash.numblocks = 32;
-+                              break;
-+                      case 3:
-+                              /* SST25WF020 2 Mbit Serial Flash */
-+                      case 0x43:
-+                              /* SST25VF020 2 Mbit Serial Flash */
-+                              cc->sflash.numblocks = 64;
-+                              break;
-+                      case 4:
-+                              /* SST25WF040 4 Mbit Serial Flash */
-+                      case 0x44:
-+                              /* SST25VF040 4 Mbit Serial Flash */
-+                      case 0x8d:
-+                              /* SST25VF040B 4 Mbit Serial Flash */
-+                              cc->sflash.numblocks = 128;
-+                              break;
-+                      case 5:
-+                              /* SST25WF080 8 Mbit Serial Flash */
-+                      case 0x8e:
-+                              /* SST25VF080B 8 Mbit Serial Flash */
-+                              cc->sflash.numblocks = 256;
-+                              break;
-+                      case 0x41:
-+                              /* SST25VF016 16 Mbit Serial Flash */
-+                              cc->sflash.numblocks = 512;
-+                              break;
-+                      case 0x4a:
-+                              /* SST25VF032 32 Mbit Serial Flash */
-+                              cc->sflash.numblocks = 1024;
-+                              break;
-+                      case 0x4b:
-+                              /* SST25VF064 64 Mbit Serial Flash */
-+                              cc->sflash.numblocks = 2048;
-+                              break;
-+                      }
-+                      break;
-+              }
-+              break;
-+
-+      case BCMA_CC_FLASHT_ATSER:
-+              /* Probe for Atmel chips */
-+              bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS);
-+              id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA) & 0x3c;
-+              switch (id) {
-+              case 0xc:
-+                      /* Atmel AT45DB011 1Mbit Serial Flash */
-+                      cc->sflash.blocksize = 256;
-+                      cc->sflash.numblocks = 512;
-+                      break;
-+              case 0x14:
-+                      /* Atmel AT45DB021 2Mbit Serial Flash */
-+                      cc->sflash.blocksize = 256;
-+                      cc->sflash.numblocks = 1024;
-+                      break;
-+              case 0x1c:
-+                      /* Atmel AT45DB041 4Mbit Serial Flash */
-+                      cc->sflash.blocksize = 256;
-+                      cc->sflash.numblocks = 2048;
-+                      break;
-+              case 0x24:
-+                      /* Atmel AT45DB081 8Mbit Serial Flash */
-+                      cc->sflash.blocksize = 256;
-+                      cc->sflash.numblocks = 4096;
-+                      break;
-+              case 0x2c:
-+                      /* Atmel AT45DB161 16Mbit Serial Flash */
-+                      cc->sflash.blocksize = 512;
-+                      cc->sflash.numblocks = 4096;
-+                      break;
-+              case 0x34:
-+                      /* Atmel AT45DB321 32Mbit Serial Flash */
-+                      cc->sflash.blocksize = 512;
-+                      cc->sflash.numblocks = 8192;
-+                      break;
-+              case 0x3c:
-+                      /* Atmel AT45DB642 64Mbit Serial Flash */
-+                      cc->sflash.blocksize = 1024;
-+                      cc->sflash.numblocks = 8192;
-+                      break;
-+              }
-+              break;
-+      }
-+
-+      cc->sflash.size = cc->sflash.blocksize * cc->sflash.numblocks;
-+
-+      return cc->sflash.size ? 0 : -ENODEV;
-+}
-+
-+/* Read len bytes starting at offset into buf. Returns number of bytes read. */
-+int bcma_sflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len, u8 *buf)
-+{
-+      u8 *from, *to;
-+      u32 cnt, i;
-+
-+      if (!len)
-+              return 0;
-+
-+      if ((offset + len) > cc->sflash.size)
-+              return -EINVAL;
-+
-+      if ((len >= 4) && (offset & 3))
-+              cnt = 4 - (offset & 3);
-+      else if ((len >= 4) && ((u32)buf & 3))
-+              cnt = 4 - ((u32)buf & 3);
-+      else
-+              cnt = len;
-+
-+      from = (u8 *)KSEG0ADDR(BCMA_FLASH2 + offset);
-+
-+      to = (u8 *)buf;
-+
-+      if (cnt < 4) {
-+              for (i = 0; i < cnt; i++) {
-+                      *to = readb(from);
-+                      from++;
-+                      to++;
-+              }
-+              return cnt;
-+      }
-+
-+      while (cnt >= 4) {
-+              *(u32 *)to = readl(from);
-+              from += 4;
-+              to += 4;
-+              cnt -= 4;
-+      }
-+
-+      return len - cnt;
-+}
-+
-+/* Poll for command completion. Returns zero when complete. */
-+int bcma_sflash_poll(struct bcma_drv_cc *cc, u32 offset)
-+{
-+      if (offset >= cc->sflash.size)
-+              return -22;
-+
-+      switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
-+      case BCMA_CC_FLASHT_STSER:
-+              /* Check for ST Write In Progress bit */
-+              bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RDSR);
-+              return bcma_cc_read32(cc, BCMA_CC_FLASHDATA)
-+                              & BCMA_CC_FLASHDATA_ST_WIP;
-+      case BCMA_CC_FLASHT_ATSER:
-+              /* Check for Atmel Ready bit */
-+              bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS);
-+              return !(bcma_cc_read32(cc, BCMA_CC_FLASHDATA)
-+                              & BCMA_CC_FLASHDATA_AT_READY);
-+      }
-+
-+      return 0;
-+}
-+
-+
-+static int sflash_st_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
-+                         const u8 *buf)
-+{
-+      int written = 1;
-+
-+      /* Enable writes */
-+      bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_WREN);
-+      bcma_sflash_write_u8(cc, offset, *buf++);
-+      /* Issue a page program with CSA bit set */
-+      bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_CSA | BCMA_CC_FLASHCTL_ST_PP);
-+      offset++;
-+      len--;
-+      while (len > 0) {
-+              if ((offset & 255) == 0) {
-+                      /* Page boundary, poll droping cs and return */
-+                      bcma_cc_write32(cc, BCMA_CC_FLASHCTL, 0);
-+                      udelay(1);
-+                      if (!bcma_sflash_poll(cc, offset)) {
-+                              /* Flash rejected command */
-+                              return -EAGAIN;
-+                      }
-+                      return written;
-+              } else {
-+                      /* Write single byte */
-+                      bcma_sflash_cmd(cc,
-+                                      BCMA_CC_FLASHCTL_ST_CSA |
-+                                      *buf++);
-+              }
-+              written++;
-+              offset++;
-+              len--;
-+      }
-+      /* All done, drop cs & poll */
-+      bcma_cc_write32(cc, BCMA_CC_FLASHCTL, 0);
-+      udelay(1);
-+      if (!bcma_sflash_poll(cc, offset)) {
-+              /* Flash rejected command */
-+              return -EAGAIN;
-+      }
-+      return written;
-+}
-+
-+static int sflash_at_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
-+                         const u8 *buf)
-+{
-+      struct bcma_sflash *sfl = &cc->sflash;
-+      u32 page, byte, mask;
-+      int ret = 0;
-+
-+      mask = sfl->blocksize - 1;
-+      page = (offset & ~mask) << 1;
-+      byte = offset & mask;
-+      /* Read main memory page into buffer 1 */
-+      if (byte || (len < sfl->blocksize)) {
-+              int i = 100;
-+              bcma_cc_write32(cc, BCMA_CC_FLASHADDR, page);
-+              bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_BUF1_LOAD);
-+              /* 250 us for AT45DB321B */
-+              while (i > 0 && bcma_sflash_poll(cc, offset)) {
-+                      udelay(10);
-+                      i--;
-+              }
-+              BUG_ON(!bcma_sflash_poll(cc, offset));
-+      }
-+      /* Write into buffer 1 */
-+      for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) {
-+              bcma_sflash_write_u8(cc, byte++, *buf++);
-+              bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_BUF1_WRITE);
-+      }
-+      /* Write buffer 1 into main memory page */
-+      bcma_cc_write32(cc, BCMA_CC_FLASHADDR, page);
-+      bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_BUF1_PROGRAM);
-+
-+      return ret;
-+}
-+
-+/* Write len bytes starting at offset into buf. Returns number of bytes
-+ * written. Caller should poll for completion.
-+ */
-+int bcma_sflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
-+                    const u8 *buf)
-+{
-+      struct bcma_sflash *sfl;
-+      int ret = 0, tries = NUM_RETRIES;
-+
-+      if (!len)
-+              return 0;
-+
-+      if ((offset + len) > cc->sflash.size)
-+              return -EINVAL;
-+
-+      sfl = &cc->sflash;
-+      switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
-+      case BCMA_CC_FLASHT_STSER:
-+              do {
-+                      ret = sflash_st_write(cc, offset, len, buf);
-+                      tries--;
-+              } while (ret == -EAGAIN && tries > 0);
-+
-+              if (ret == -EAGAIN && tries == 0) {
-+                      bcma_info(cc->core->bus, "ST Flash rejected write\n");
-+                      ret = -EIO;
-+              }
-+              break;
-+      case BCMA_CC_FLASHT_ATSER:
-+              ret = sflash_at_write(cc, offset, len, buf);
-+              break;
-+      }
-+
-+      return ret;
-+}
-+
-+/* Erase a region. Returns number of bytes scheduled for erasure.
-+ * Caller should poll for completion.
-+ */
-+int bcma_sflash_erase(struct bcma_drv_cc *cc, u32 offset)
-+{
-+      struct bcma_sflash *sfl;
-+
-+      if (offset >= cc->sflash.size)
-+              return -EINVAL;
-+
-+      sfl = &cc->sflash;
-+      switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
-+      case BCMA_CC_FLASHT_STSER:
-+              bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_WREN);
-+              bcma_cc_write32(cc, BCMA_CC_FLASHADDR, offset);
-+              /* Newer flashes have "sub-sectors" which can be erased independently
-+               * with a new command: ST_SSE. The ST_SE command erases 64KB just as
-+               * before.
-+               */
-+              if (sfl->blocksize < (64 * 1024))
-+                      bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_SSE);
-+              else
-+                      bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_SE);
-+              return sfl->blocksize;
-+      case BCMA_CC_FLASHT_ATSER:
-+              bcma_cc_write32(cc, BCMA_CC_FLASHADDR, offset << 1);
-+              bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_PAGE_ERASE);
-+              return sfl->blocksize;
-+      }
-+
-+      return 0;
-+}
---- a/drivers/bcma/driver_mips.c
-+++ b/drivers/bcma/driver_mips.c
-@@ -185,7 +185,13 @@ static void bcma_core_mips_flash_detect(
-       switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
-       case BCMA_CC_FLASHT_STSER:
-       case BCMA_CC_FLASHT_ATSER:
--              bcma_err(bus, "Serial flash not supported.\n");
-+#ifdef CONFIG_BCMA_SFLASH
-+              bcma_info(bus, "found serial flash.\n");
-+              bus->drv_cc.flash_type = BCMA_SFLASH;
-+              bcma_sflash_init(&bus->drv_cc);
-+#else
-+              bcma_info(bus, "serial flash not supported.\n");
-+#endif /* CONFIG_BCMA_SFLASH */
-               break;
-       case BCMA_CC_FLASHT_PARA:
-               bcma_info(bus, "found parallel flash.\n");
---- a/include/linux/bcma/bcma_driver_chipcommon.h
-+++ b/include/linux/bcma/bcma_driver_chipcommon.h
-@@ -435,6 +435,7 @@ struct bcma_chipcommon_pmu {
- #ifdef CONFIG_BCMA_DRIVER_MIPS
- enum bcma_flash_type {
-       BCMA_PFLASH,
-+      BCMA_SFLASH,
- };
- struct bcma_pflash {
-@@ -443,6 +444,14 @@ struct bcma_pflash {
-       u32 window_size;
- };
-+#ifdef CONFIG_BCMA_SFLASH
-+struct bcma_sflash {
-+      u32 blocksize;          /* Block size */
-+      u32 numblocks;          /* Number of blocks */
-+      u32 size;               /* Total size in bytes */
-+};
-+#endif /* CONFIG_BCMA_SFLASH */
-+
- struct bcma_serial_port {
-       void *regs;
-       unsigned long clockspeed;
-@@ -465,6 +474,9 @@ struct bcma_drv_cc {
-       enum bcma_flash_type flash_type;
-       union {
-               struct bcma_pflash pflash;
-+#ifdef CONFIG_BCMA_SFLASH
-+              struct bcma_sflash sflash;
-+#endif /* CONFIG_BCMA_SFLASH */
-       };
-       int nr_serial_ports;
-@@ -520,4 +532,14 @@ extern void bcma_chipco_regctl_maskset(s
-                                      u32 offset, u32 mask, u32 set);
- extern void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid);
-+#ifdef CONFIG_BCMA_SFLASH
-+/* Chipcommon sflash support. */
-+int bcma_sflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len,
-+                         u8 *buf);
-+int bcma_sflash_poll(struct bcma_drv_cc *cc, u32 offset);
-+int bcma_sflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
-+                          const u8 *buf);
-+int bcma_sflash_erase(struct bcma_drv_cc *cc, u32 offset);
-+#endif /* CONFIG_BCMA_SFLASH */
-+
- #endif /* LINUX_BCMA_DRIVER_CC_H_ */