brcm47xx: add fallback sprom for pci devices without an own sprom.
authorHauke Mehrtens <hauke@hauke-m.de>
Sun, 1 May 2011 20:28:35 +0000 (20:28 +0000)
committerHauke Mehrtens <hauke@hauke-m.de>
Sun, 1 May 2011 20:28:35 +0000 (20:28 +0000)
If there is no sprom on an ssb based pci device on the brcm47xx
architecture ssb now asks the architecture code to look into the nvram
to get some sprom data for this device. Now we are able to read out
pci/1/1/ foo or pci/1/3/ foo config options.

This will fix some problems where the wireless devices does not got an
mac address and the following message was show:
ssb: WARNING: Invalid SPROM CRC (corrupt SPROM)

SVN-Revision: 26801

26 files changed:
package/broadcom-wl/patches/003-compat-2.6.35.patch
package/broadcom-wl/patches/910-fallback-sprom.patch
target/linux/brcm47xx/patches-2.6.37/031-ssb-add-callback-for-sprom.patch [new file with mode: 0644]
target/linux/brcm47xx/patches-2.6.37/032-bcm47xx-extend-bcm47xx_fill_sprom-with-prefix.patch [new file with mode: 0644]
target/linux/brcm47xx/patches-2.6.37/033-bcm47xx-register-fallback-callback.patch [new file with mode: 0644]
target/linux/brcm47xx/patches-2.6.37/034-bcm47xx-extend-and-fix-fill-sprom.patch [new file with mode: 0644]
target/linux/brcm47xx/patches-2.6.37/400-arch-bcm47xx.patch
target/linux/brcm47xx/patches-2.6.37/820-wgt634u-nvram-fix.patch
target/linux/brcm47xx/patches-2.6.37/977-ssb_export_fallback_sprom.patch [deleted file]
target/linux/brcm47xx/patches-2.6.37/980-wnr834b_no_cardbus_invariant.patch [new file with mode: 0644]
target/linux/brcm47xx/patches-2.6.38/031-ssb-add-callback-for-sprom.patch [new file with mode: 0644]
target/linux/brcm47xx/patches-2.6.38/032-bcm47xx-extend-bcm47xx_fill_sprom-with-prefix.patch [new file with mode: 0644]
target/linux/brcm47xx/patches-2.6.38/033-bcm47xx-register-fallback-callback.patch [new file with mode: 0644]
target/linux/brcm47xx/patches-2.6.38/034-bcm47xx-extend-and-fix-fill-sprom.patch [new file with mode: 0644]
target/linux/brcm47xx/patches-2.6.38/400-arch-bcm47xx.patch
target/linux/brcm47xx/patches-2.6.38/820-wgt634u-nvram-fix.patch
target/linux/brcm47xx/patches-2.6.38/977-ssb_export_fallback_sprom.patch [deleted file]
target/linux/brcm47xx/patches-2.6.38/980-wnr834b_no_cardbus_invariant.patch [new file with mode: 0644]
target/linux/brcm63xx/patches-2.6.37/110-gpiodev.patch
target/linux/brcm63xx/patches-2.6.37/180-udc_preliminary_support.patch
target/linux/brcm63xx/patches-2.6.37/200-extended-platform-devices.patch
target/linux/brcm63xx/patches-2.6.37/200-spi-board-info.patch
target/linux/brcm63xx/patches-2.6.37/240-spi.patch
target/linux/brcm63xx/patches-2.6.37/260-no_ehci_over_current_check.patch
target/linux/brcm63xx/patches-2.6.37/500-ssb-add-callback-for-sprom.patch [new file with mode: 0644]
target/linux/brcm63xx/patches-2.6.37/977-ssb_export_fallback_sprom.patch

index 3bb786c1405c23bafccf138624be1028a85c339d..a51cfcdf60571c06e38303eecbd779cc5bb8b2e7 100644 (file)
@@ -1,19 +1,17 @@
 --- a/driver/wl_linux.c
 +++ b/driver/wl_linux.c
-@@ -2082,8 +2082,12 @@ static void
+@@ -2082,7 +2082,11 @@ static void
  _wl_set_multicast_list(struct net_device *dev)
  {
        wl_info_t *wl;
 +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34)
        struct dev_mc_list *mclist;
--      int i;
 +#else
 +      struct netdev_hw_addr *ha;
 +#endif
-+      int i = 0;
+       int i;
  
        if (!dev)
-               return;
 @@ -2098,14 +2102,23 @@ _wl_set_multicast_list(struct net_device
                wl->pub->allmulti = (dev->flags & IFF_ALLMULTI)? TRUE: FALSE;
  
index 2bcd77b9a87575c6f3b7d55223102274b9bed02a..407ec5ac1694721bdecab27ced98a10d998eb238 100644 (file)
@@ -1,72 +1,68 @@
 --- a/driver/bcmsrom.c
 +++ b/driver/bcmsrom.c
-@@ -39,6 +39,10 @@
+@@ -39,6 +39,11 @@
  #include <sbsdpcmdev.h>
  #endif 
  
-+#ifdef CONFIG_SSB
++#if defined(CONFIG_SSB_PCIHOST) && defined(CONFIG_BOARD_BCM963XX)
 +#include <linux/ssb/ssb.h>
++extern struct ssb_sprom bcm63xx_sprom;
 +#endif
 +
  #ifdef WLTEST
  #include <sbsprom.h>
  #endif /* WLTEST */
-@@ -2058,6 +2062,11 @@ BCMATTACHFN(initvars_srom_pci)(si_t *sih
+@@ -2058,6 +2063,10 @@ BCMATTACHFN(initvars_srom_pci)(si_t *sih
        bool flash = FALSE;
        int err = 0;
  
-+#ifdef CONFIG_SSB
-+      struct ssb_sprom *fbrom;
++#if defined(CONFIG_SSB_PCIHOST) && defined(CONFIG_BOARD_BCM963XX)
 +      char eabuf[18];
 +#endif
 +
        /*
         * Apply CRC over SROM content regardless SROM is present or not,
         * and use variable <devpath>sromrev's existance in flash to decide
-@@ -2120,6 +2129,62 @@ BCMATTACHFN(initvars_srom_pci)(si_t *sih
+@@ -2120,6 +2130,58 @@ BCMATTACHFN(initvars_srom_pci)(si_t *sih
                        goto varscont;
                }
  
-+#ifdef CONFIG_SSB
++#if defined(CONFIG_SSB_PCIHOST) && defined(CONFIG_BOARD_BCM963XX)
 +              base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS);
 +
 +              if( base != NULL )
 +              {
 +                      varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
 +
-+                      /* Try to load ssb fallback sprom */
-+                      if ((fbrom = ssb_get_fallback_sprom()) != NULL)
-+                      {
-+                              printk("Got version %i SPROM from SSB\n", fbrom->revision);
++                      printk("Got version %i SPROM from SSB\n", bcm63xx_sprom.revision);
 +
-+                              varbuf_append(&b, vstr_sromrev, fbrom->revision);
-+                              varbuf_append(&b, vstr_boardrev, fbrom->board_rev);
++                      varbuf_append(&b, vstr_sromrev, bcm63xx_sprom.revision);
++                      varbuf_append(&b, vstr_boardrev, bcm63xx_sprom.board_rev);
 +
-+                              /* ToDo: map fbrom->country_code */
-+                              varbuf_append(&b, vstr_noccode);
++                      /* ToDo: map bcm63xx_sprom.country_code */
++                      varbuf_append(&b, vstr_noccode);
 +
-+                              varbuf_append(&b, vstr_aa2g, fbrom->ant_available_bg);
++                      varbuf_append(&b, vstr_aa2g, bcm63xx_sprom.ant_available_bg);
 +
-+                              varbuf_append(&b, vstr_pa0b[0], fbrom->pa0b0);
-+                              varbuf_append(&b, vstr_pa1b[0], fbrom->pa1b0);
-+                              varbuf_append(&b, vstr_pa0b[1], fbrom->pa0b1);
-+                              varbuf_append(&b, vstr_pa1b[1], fbrom->pa1b1);
-+                              varbuf_append(&b, vstr_pa0b[2], fbrom->pa0b2);
-+                              varbuf_append(&b, vstr_pa1b[2], fbrom->pa1b2);
++                      varbuf_append(&b, vstr_pa0b[0], bcm63xx_sprom.pa0b0);
++                      varbuf_append(&b, vstr_pa1b[0], bcm63xx_sprom.pa1b0);
++                      varbuf_append(&b, vstr_pa0b[1], bcm63xx_sprom.pa0b1);
++                      varbuf_append(&b, vstr_pa1b[1], bcm63xx_sprom.pa1b1);
++                      varbuf_append(&b, vstr_pa0b[2], bcm63xx_sprom.pa0b2);
++                      varbuf_append(&b, vstr_pa1b[2], bcm63xx_sprom.pa1b2);
 +
-+                              varbuf_append(&b, vstr_pa0maxpwr, fbrom->maxpwr_bg);
-+                              varbuf_append(&b, vstr_pa0itssit, fbrom->itssi_bg);
++                      varbuf_append(&b, vstr_pa0maxpwr, bcm63xx_sprom.maxpwr_bg);
++                      varbuf_append(&b, vstr_pa0itssit, bcm63xx_sprom.itssi_bg);
 +
-+                              varbuf_append(&b, vstr_boardflags, (fbrom->boardflags_hi << 16) | fbrom->boardflags_lo);
-+                              varbuf_append(&b, vstr_boardflags2, (fbrom->boardflags2_hi << 16) | fbrom->boardflags2_lo);
++                      varbuf_append(&b, vstr_boardflags, (bcm63xx_sprom.boardflags_hi << 16) | bcm63xx_sprom.boardflags_lo);
++                      varbuf_append(&b, vstr_boardflags2, (bcm63xx_sprom.boardflags2_hi << 16) | bcm63xx_sprom.boardflags2_lo);
 +
-+                              snprintf(eabuf, sizeof(eabuf), "%02x:%02x:%02x:%02x:%02x:%02x",
-+                                      fbrom->il0mac[0], fbrom->il0mac[1], fbrom->il0mac[2],
-+                                      fbrom->il0mac[3], fbrom->il0mac[4], fbrom->il0mac[5]
-+                              );
++                      snprintf(eabuf, sizeof(eabuf), "%02x:%02x:%02x:%02x:%02x:%02x",
++                              bcm63xx_sprom.il0mac[0], bcm63xx_sprom.il0mac[1], bcm63xx_sprom.il0mac[2],
++                              bcm63xx_sprom.il0mac[3], bcm63xx_sprom.il0mac[4], bcm63xx_sprom.il0mac[5]
++                      );
 +
-+                              varbuf_append(&b, vstr_macaddr, eabuf);
-+                      }
++                      varbuf_append(&b, vstr_macaddr, eabuf);
 +
 +                      /* final nullbyte terminator */
 +                      ASSERT(b.size >= 1);
diff --git a/target/linux/brcm47xx/patches-2.6.37/031-ssb-add-callback-for-sprom.patch b/target/linux/brcm47xx/patches-2.6.37/031-ssb-add-callback-for-sprom.patch
new file mode 100644 (file)
index 0000000..1bb2f0f
--- /dev/null
@@ -0,0 +1,142 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -643,6 +643,17 @@ static struct ssb_sprom bcm63xx_sprom =
+       .boardflags_lo          = 0x2848,
+       .boardflags_hi          = 0x0000,
+ };
++
++int bcm63xx_get_fallback_sprom(struct ssb_bus *bus)
++{
++      if (bus->bustype == SSB_BUSTYPE_PCI) {
++              memcpy(&bus->sprom, &bcm63xx_sprom, sizeof(struct ssb_sprom));
++              return 0;
++      } else {
++              printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
++              return -EINVAL;
++      }
++}
+ #endif
+ /*
+@@ -793,8 +804,9 @@ void __init board_prom_init(void)
+       if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
+               memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+               memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+-              if (ssb_arch_set_fallback_sprom(&bcm63xx_sprom) < 0)
+-                      printk(KERN_ERR "failed to register fallback SPROM\n");
++              if (ssb_arch_register_fallback_sprom(
++                              &bcm63xx_get_fallback_sprom) < 0)
++                      printk(KERN_ERR PFX "failed to register fallback SPROM\n");
+       }
+ #endif
+ }
+--- a/drivers/ssb/pci.c
++++ b/drivers/ssb/pci.c
+@@ -662,7 +662,6 @@ static int sprom_extract(struct ssb_bus
+ static int ssb_pci_sprom_get(struct ssb_bus *bus,
+                            struct ssb_sprom *sprom)
+ {
+-      const struct ssb_sprom *fallback;
+       int err;
+       u16 *buf;
+@@ -707,10 +706,14 @@ static int ssb_pci_sprom_get(struct ssb_
+               if (err) {
+                       /* All CRC attempts failed.
+                        * Maybe there is no SPROM on the device?
+-                       * If we have a fallback, use that. */
+-                      fallback = ssb_get_fallback_sprom();
+-                      if (fallback) {
+-                              memcpy(sprom, fallback, sizeof(*sprom));
++                       * Now we ask the arch code if there is some sprom
++                       * avaliable for this device in some other storage */
++                      err = ssb_fill_sprom_with_fallback(bus);
++                      if (err) {
++                              ssb_printk(KERN_WARNING PFX "WARNING: Using"
++                                         " fallback SPROM failed (err %d)\n",
++                                         err);
++                      } else {
+                               err = 0;
+                               goto out_free;
+                       }
+--- a/drivers/ssb/sprom.c
++++ b/drivers/ssb/sprom.c
+@@ -17,7 +17,7 @@
+ #include <linux/slab.h>
+-static const struct ssb_sprom *fallback_sprom;
++static int(*get_fallback_sprom)(struct ssb_bus *dev);
+ static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
+@@ -145,13 +145,14 @@ out:
+ }
+ /**
+- * ssb_arch_set_fallback_sprom - Set a fallback SPROM for use if no SPROM is found.
++ * ssb_arch_register_fallback_sprom - Registers a method providing a fallback
++ * SPROM if no SPROM is found.
+  *
+- * @sprom: The SPROM data structure to register.
++ * @sprom_callback: The callbcak function.
+  *
+- * With this function the architecture implementation may register a fallback
+- * SPROM data structure. The fallback is only used for PCI based SSB devices,
+- * where no valid SPROM can be found in the shadow registers.
++ * With this function the architecture implementation may register a callback
++ * handler which wills the SPROM data structure. The fallback is only used for
++ * PCI based SSB devices, where no valid SPROM can be found in the shadow registers.
+  *
+  * This function is useful for weird architectures that have a half-assed SSB device
+  * hardwired to their PCI bus.
+@@ -163,18 +164,21 @@ out:
+  *
+  * This function is available for architecture code, only. So it is not exported.
+  */
+-int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom)
++int ssb_arch_register_fallback_sprom(int (*sprom_callback)(struct ssb_bus *bus))
+ {
+-      if (fallback_sprom)
++      if (get_fallback_sprom)
+               return -EEXIST;
+-      fallback_sprom = sprom;
++      get_fallback_sprom = sprom_callback;
+       return 0;
+ }
+-const struct ssb_sprom *ssb_get_fallback_sprom(void)
++int ssb_fill_sprom_with_fallback(struct ssb_bus *bus)
+ {
+-      return fallback_sprom;
++      if (!get_fallback_sprom)
++              return -ENOENT;
++
++      return get_fallback_sprom(bus);
+ }
+ /* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */
+--- a/drivers/ssb/ssb_private.h
++++ b/drivers/ssb/ssb_private.h
+@@ -171,7 +171,7 @@ ssize_t ssb_attr_sprom_store(struct ssb_
+                            const char *buf, size_t count,
+                            int (*sprom_check_crc)(const u16 *sprom, size_t size),
+                            int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom));
+-extern const struct ssb_sprom *ssb_get_fallback_sprom(void);
++extern int ssb_fill_sprom_with_fallback(struct ssb_bus *bus);
+ /* core.c */
+--- a/include/linux/ssb/ssb.h
++++ b/include/linux/ssb/ssb.h
+@@ -404,7 +404,8 @@ extern bool ssb_is_sprom_available(struc
+ /* Set a fallback SPROM.
+  * See kdoc at the function definition for complete documentation. */
+-extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
++extern int ssb_arch_register_fallback_sprom(
++              int (*sprom_callback)(struct ssb_bus *bus));
+ /* Suspend a SSB bus.
+  * Call this from the parent bus suspend routine. */
diff --git a/target/linux/brcm47xx/patches-2.6.37/032-bcm47xx-extend-bcm47xx_fill_sprom-with-prefix.patch b/target/linux/brcm47xx/patches-2.6.37/032-bcm47xx-extend-bcm47xx_fill_sprom-with-prefix.patch
new file mode 100644 (file)
index 0000000..acf65bd
--- /dev/null
@@ -0,0 +1,69 @@
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -59,10 +59,23 @@ static void bcm47xx_machine_halt(void)
+ }
+ #define READ_FROM_NVRAM(_outvar, name, buf) \
+-      if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\
++      if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
+               sprom->_outvar = simple_strtoul(buf, NULL, 0);
+-static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
++static inline int nvram_getprefix(const char *prefix, char *name,
++                                char *buf, int len)
++{
++      if (prefix) {
++              char key[100];
++
++              snprintf(key, sizeof(key), "%s%s", prefix, name);
++              return nvram_getenv(key, buf, len);
++      }
++
++      return nvram_getenv(name, buf, len);
++}
++
++static void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
+ {
+       char buf[100];
+       u32 boardflags;
+@@ -71,11 +84,11 @@ static void bcm47xx_fill_sprom(struct ss
+       sprom->revision = 1; /* Fallback: Old hardware does not define this. */
+       READ_FROM_NVRAM(revision, "sromrev", buf);
+-      if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
++      if (nvram_getprefix(prefix, "il0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->il0mac);
+-      if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
++      if (nvram_getprefix(prefix, "et0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et0mac);
+-      if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
++      if (nvram_getprefix(prefix, "et1macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et1mac);
+       READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf);
+       READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf);
+@@ -127,14 +140,14 @@ static void bcm47xx_fill_sprom(struct ss
+       READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf);
+       READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf);
+-      if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) {
++      if (nvram_getprefix(prefix, "boardflags", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags_lo = (boardflags & 0x0000FFFFU);
+                       sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16;
+               }
+       }
+-      if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) {
++      if (nvram_getprefix(prefix, "boardflags2", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags2_lo = (boardflags & 0x0000FFFFU);
+@@ -160,7 +173,7 @@ static int bcm47xx_get_invariants(struct
+       if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
+               iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
+-      bcm47xx_fill_sprom(&iv->sprom);
++      bcm47xx_fill_sprom(&iv->sprom, NULL);
+       if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
+               iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
diff --git a/target/linux/brcm47xx/patches-2.6.37/033-bcm47xx-register-fallback-callback.patch b/target/linux/brcm47xx/patches-2.6.37/033-bcm47xx-register-fallback-callback.patch
new file mode 100644 (file)
index 0000000..f63deac
--- /dev/null
@@ -0,0 +1,48 @@
+--- a/arch/mips/bcm47xx/nvram.c
++++ b/arch/mips/bcm47xx/nvram.c
+@@ -23,7 +23,7 @@
+ static char nvram_buf[NVRAM_SPACE];
+ /* Probe for NVRAM header */
+-static void __init early_nvram_init(void)
++static void early_nvram_init(void)
+ {
+       struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+       struct nvram_header *header;
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -156,6 +156,22 @@ static void bcm47xx_fill_sprom(struct ss
+       }
+ }
++int bcm47xx_get_sprom(struct ssb_bus *bus)
++{
++      char prefix[10];
++
++      if (bus->bustype == SSB_BUSTYPE_PCI) {
++              snprintf(prefix, sizeof(prefix), "pci/%x/%x/",
++                       bus->host_pci->bus->number + 1,
++                       PCI_SLOT(bus->host_pci->devfn));
++              bcm47xx_fill_sprom(&bus->sprom, prefix);
++              return 0;
++      } else {
++              printk(KERN_WARNING "bcm47xx: unable to fill SPROM for given bustype.\n");
++              return -EINVAL;
++      }
++}
++
+ static int bcm47xx_get_invariants(struct ssb_bus *bus,
+                                  struct ssb_init_invariants *iv)
+ {
+@@ -212,6 +228,11 @@ void __init plat_mem_setup(void)
+       char buf[100];
+       struct ssb_mipscore *mcore;
++      err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom);
++      if (err)
++              printk(KERN_WARNING "bcm47xx: someone else already registered"
++                      " a ssb SPROM callback handler (err %d)\n", err);
++
+       err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
+                                     bcm47xx_get_invariants);
+       if (err)
diff --git a/target/linux/brcm47xx/patches-2.6.37/034-bcm47xx-extend-and-fix-fill-sprom.patch b/target/linux/brcm47xx/patches-2.6.37/034-bcm47xx-extend-and-fix-fill-sprom.patch
new file mode 100644 (file)
index 0000000..490ca67
--- /dev/null
@@ -0,0 +1,122 @@
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -62,6 +62,11 @@ static void bcm47xx_machine_halt(void)
+       if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
+               sprom->_outvar = simple_strtoul(buf, NULL, 0);
++#define READ_FROM_NVRAM2(_outvar, name1, name2, buf) \
++      if (nvram_getprefix(prefix, name1, buf, sizeof(buf)) >= 0 || \
++          nvram_getprefix(prefix, name2, buf, sizeof(buf)) >= 0)\
++              sprom->_outvar = simple_strtoul(buf, NULL, 0);
++
+ static inline int nvram_getprefix(const char *prefix, char *name,
+                                 char *buf, int len)
+ {
+@@ -75,6 +80,27 @@ static inline int nvram_getprefix(const
+       return nvram_getenv(name, buf, len);
+ }
++static u32 nvram_getu32(const char *name, char *buf, int len)
++{
++      int rv;
++      char key[100];
++      u16 var0, var1;
++
++      snprintf(key, sizeof(key), "%s0", name);
++      rv = nvram_getenv(key, buf, len);
++      /* return 0 here so this looks like unset */
++      if (rv < 0)
++              return 0;
++      var0 = simple_strtoul(buf, NULL, 0);
++
++      snprintf(key, sizeof(key), "%s1", name);
++      rv = nvram_getenv(key, buf, len);
++      if (rv < 0)
++              return 0;
++      var1 = simple_strtoul(buf, NULL, 0);
++      return var1 << 16 | var0;
++}
++
+ static void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
+ {
+       char buf[100];
+@@ -84,7 +110,8 @@ static void bcm47xx_fill_sprom(struct ss
+       sprom->revision = 1; /* Fallback: Old hardware does not define this. */
+       READ_FROM_NVRAM(revision, "sromrev", buf);
+-      if (nvram_getprefix(prefix, "il0macaddr", buf, sizeof(buf)) >= 0)
++      if (nvram_getprefix(prefix, "il0macaddr", buf, sizeof(buf)) >= 0 ||
+++         nvram_getprefix(prefix, "macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->il0mac);
+       if (nvram_getprefix(prefix, "et0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et0mac);
+@@ -110,20 +137,36 @@ static void bcm47xx_fill_sprom(struct ss
+       READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf);
+       READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf);
+       READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf);
+-      READ_FROM_NVRAM(gpio0, "wl0gpio0", buf);
+-      READ_FROM_NVRAM(gpio1, "wl0gpio1", buf);
+-      READ_FROM_NVRAM(gpio2, "wl0gpio2", buf);
+-      READ_FROM_NVRAM(gpio3, "wl0gpio3", buf);
+-      READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf);
+-      READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf);
+-      READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf);
+-      READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf);
+-      READ_FROM_NVRAM(itssi_a, "pa1itssit", buf);
+-      READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf);
++      READ_FROM_NVRAM2(gpio0, "ledbh0", "wl0gpio0", buf);
++      READ_FROM_NVRAM2(gpio1, "ledbh1", "wl0gpio1", buf);
++      READ_FROM_NVRAM2(gpio2, "ledbh2", "wl0gpio2", buf);
++      READ_FROM_NVRAM2(gpio3, "ledbh3", "wl0gpio3", buf);
++      READ_FROM_NVRAM2(maxpwr_bg, "maxp2ga0", "pa0maxpwr", buf);
++      READ_FROM_NVRAM2(maxpwr_al, "maxp5gla0", "pa1lomaxpwr", buf);
++      READ_FROM_NVRAM2(maxpwr_a, "maxp5ga0", "pa1maxpwr", buf);
++      READ_FROM_NVRAM2(maxpwr_ah, "maxp5gha0", "pa1himaxpwr", buf);
++      READ_FROM_NVRAM2(itssi_bg, "itt5ga0", "pa0itssit", buf);
++      READ_FROM_NVRAM2(itssi_a, "itt2ga0", "pa1itssit", buf);
+       READ_FROM_NVRAM(tri2g, "tri2g", buf);
+       READ_FROM_NVRAM(tri5gl, "tri5gl", buf);
+       READ_FROM_NVRAM(tri5g, "tri5g", buf);
+       READ_FROM_NVRAM(tri5gh, "tri5gh", buf);
++      READ_FROM_NVRAM(txpid2g[0], "txpid2ga0", buf);
++      READ_FROM_NVRAM(txpid2g[1], "txpid2ga1", buf);
++      READ_FROM_NVRAM(txpid2g[2], "txpid2ga2", buf);
++      READ_FROM_NVRAM(txpid2g[3], "txpid2ga3", buf);
++      READ_FROM_NVRAM(txpid5g[0], "txpid5ga0", buf);
++      READ_FROM_NVRAM(txpid5g[1], "txpid5ga1", buf);
++      READ_FROM_NVRAM(txpid5g[2], "txpid5ga2", buf);
++      READ_FROM_NVRAM(txpid5g[3], "txpid5ga3", buf);
++      READ_FROM_NVRAM(txpid5gl[0], "txpid5gla0", buf);
++      READ_FROM_NVRAM(txpid5gl[1], "txpid5gla1", buf);
++      READ_FROM_NVRAM(txpid5gl[2], "txpid5gla2", buf);
++      READ_FROM_NVRAM(txpid5gl[3], "txpid5gla3", buf);
++      READ_FROM_NVRAM(txpid5gh[0], "txpid5gha0", buf);
++      READ_FROM_NVRAM(txpid5gh[1], "txpid5gha1", buf);
++      READ_FROM_NVRAM(txpid5gh[2], "txpid5gha2", buf);
++      READ_FROM_NVRAM(txpid5gh[3], "txpid5gha3", buf);
+       READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf);
+       READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf);
+       READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf);
+@@ -135,10 +178,18 @@ static void bcm47xx_fill_sprom(struct ss
+       READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf);
+       READ_FROM_NVRAM(bxa5g, "bxa5g", buf);
+       READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf);
+-      READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf);
+-      READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf);
+-      READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf);
+-      READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf);
++
++      sprom->ofdm2gpo = nvram_getu32("ofdm2gpo", buf, sizeof(buf));
++      sprom->ofdm5glpo = nvram_getu32("ofdm5glpo", buf, sizeof(buf));
++      sprom->ofdm5gpo = nvram_getu32("ofdm5gpo", buf, sizeof(buf));
++      sprom->ofdm5ghpo = nvram_getu32("ofdm5ghpo", buf, sizeof(buf));
++
++      READ_FROM_NVRAM(antenna_gain.ghz24.a0, "ag0", buf);
++      READ_FROM_NVRAM(antenna_gain.ghz24.a1, "ag1", buf);
++      READ_FROM_NVRAM(antenna_gain.ghz24.a2, "ag2", buf);
++      READ_FROM_NVRAM(antenna_gain.ghz24.a3, "ag3", buf);
++      memcpy(&sprom->antenna_gain.ghz5, &sprom->antenna_gain.ghz24,
++             sizeof(sprom->antenna_gain.ghz5));
+       if (nvram_getprefix(prefix, "boardflags", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
index abb2044f7872a7f42163f74fb9e34bd2c6833da7..5ccb62fc6fb4e6da7fc264bc9f15b6fad8f00128 100644 (file)
@@ -33,7 +33,7 @@
 +EXPORT_SYMBOL(nvram_get);
 --- a/arch/mips/bcm47xx/setup.c
 +++ b/arch/mips/bcm47xx/setup.c
-@@ -226,3 +226,20 @@ void __init plat_mem_setup(void)
+@@ -311,3 +311,20 @@ void __init plat_mem_setup(void)
        _machine_halt = bcm47xx_machine_halt;
        pm_power_off = bcm47xx_machine_halt;
  }
index 9ed4a4de4a92c0bcd7f5a536f7d51f63bea2463e..29e12a81b9208d01315ca6d31668aa29b5175e89 100644 (file)
@@ -253,8 +253,8 @@ out the configuration than the in kernel cfe config reader.
 +extern char *cfe_env_get(char *nv_buf, const char *name);
  
  /* Probe for NVRAM header */
- static void __init early_nvram_init(void)
-@@ -33,6 +35,25 @@ static void __init early_nvram_init(void
+ static void early_nvram_init(void)
+@@ -33,6 +35,25 @@ static void early_nvram_init(void)
  
        base = mcore->flash_window;
        lim = mcore->flash_window_size;
diff --git a/target/linux/brcm47xx/patches-2.6.37/977-ssb_export_fallback_sprom.patch b/target/linux/brcm47xx/patches-2.6.37/977-ssb_export_fallback_sprom.patch
deleted file mode 100644 (file)
index 4ce9ba1..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
---- a/drivers/ssb/sprom.c
-+++ b/drivers/ssb/sprom.c
-@@ -176,6 +176,7 @@ const struct ssb_sprom *ssb_get_fallback
- {
-       return fallback_sprom;
- }
-+EXPORT_SYMBOL(ssb_get_fallback_sprom);
- /* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */
- bool ssb_is_sprom_available(struct ssb_bus *bus)
---- a/include/linux/ssb/ssb.h
-+++ b/include/linux/ssb/ssb.h
-@@ -412,6 +412,7 @@ extern bool ssb_is_sprom_available(struc
- /* Set a fallback SPROM.
-  * See kdoc at the function definition for complete documentation. */
- extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
-+extern const struct ssb_sprom *ssb_get_fallback_sprom(void);
- /* Suspend a SSB bus.
-  * Call this from the parent bus suspend routine. */
diff --git a/target/linux/brcm47xx/patches-2.6.37/980-wnr834b_no_cardbus_invariant.patch b/target/linux/brcm47xx/patches-2.6.37/980-wnr834b_no_cardbus_invariant.patch
new file mode 100644 (file)
index 0000000..1d6e069
--- /dev/null
@@ -0,0 +1,13 @@
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -245,6 +245,10 @@ static int bcm47xx_get_invariants(struct
+       if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
+               iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
++      /* Do not indicate cardbus for Netgear WNR834B V1 and V2 */
++      if (iv->boardinfo.type == 0x0472 && iv->has_cardbus_slot)
++              iv->has_cardbus_slot = 0;
++
+       return 0;
+ }
diff --git a/target/linux/brcm47xx/patches-2.6.38/031-ssb-add-callback-for-sprom.patch b/target/linux/brcm47xx/patches-2.6.38/031-ssb-add-callback-for-sprom.patch
new file mode 100644 (file)
index 0000000..1bb2f0f
--- /dev/null
@@ -0,0 +1,142 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -643,6 +643,17 @@ static struct ssb_sprom bcm63xx_sprom =
+       .boardflags_lo          = 0x2848,
+       .boardflags_hi          = 0x0000,
+ };
++
++int bcm63xx_get_fallback_sprom(struct ssb_bus *bus)
++{
++      if (bus->bustype == SSB_BUSTYPE_PCI) {
++              memcpy(&bus->sprom, &bcm63xx_sprom, sizeof(struct ssb_sprom));
++              return 0;
++      } else {
++              printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
++              return -EINVAL;
++      }
++}
+ #endif
+ /*
+@@ -793,8 +804,9 @@ void __init board_prom_init(void)
+       if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
+               memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+               memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+-              if (ssb_arch_set_fallback_sprom(&bcm63xx_sprom) < 0)
+-                      printk(KERN_ERR "failed to register fallback SPROM\n");
++              if (ssb_arch_register_fallback_sprom(
++                              &bcm63xx_get_fallback_sprom) < 0)
++                      printk(KERN_ERR PFX "failed to register fallback SPROM\n");
+       }
+ #endif
+ }
+--- a/drivers/ssb/pci.c
++++ b/drivers/ssb/pci.c
+@@ -662,7 +662,6 @@ static int sprom_extract(struct ssb_bus
+ static int ssb_pci_sprom_get(struct ssb_bus *bus,
+                            struct ssb_sprom *sprom)
+ {
+-      const struct ssb_sprom *fallback;
+       int err;
+       u16 *buf;
+@@ -707,10 +706,14 @@ static int ssb_pci_sprom_get(struct ssb_
+               if (err) {
+                       /* All CRC attempts failed.
+                        * Maybe there is no SPROM on the device?
+-                       * If we have a fallback, use that. */
+-                      fallback = ssb_get_fallback_sprom();
+-                      if (fallback) {
+-                              memcpy(sprom, fallback, sizeof(*sprom));
++                       * Now we ask the arch code if there is some sprom
++                       * avaliable for this device in some other storage */
++                      err = ssb_fill_sprom_with_fallback(bus);
++                      if (err) {
++                              ssb_printk(KERN_WARNING PFX "WARNING: Using"
++                                         " fallback SPROM failed (err %d)\n",
++                                         err);
++                      } else {
+                               err = 0;
+                               goto out_free;
+                       }
+--- a/drivers/ssb/sprom.c
++++ b/drivers/ssb/sprom.c
+@@ -17,7 +17,7 @@
+ #include <linux/slab.h>
+-static const struct ssb_sprom *fallback_sprom;
++static int(*get_fallback_sprom)(struct ssb_bus *dev);
+ static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
+@@ -145,13 +145,14 @@ out:
+ }
+ /**
+- * ssb_arch_set_fallback_sprom - Set a fallback SPROM for use if no SPROM is found.
++ * ssb_arch_register_fallback_sprom - Registers a method providing a fallback
++ * SPROM if no SPROM is found.
+  *
+- * @sprom: The SPROM data structure to register.
++ * @sprom_callback: The callbcak function.
+  *
+- * With this function the architecture implementation may register a fallback
+- * SPROM data structure. The fallback is only used for PCI based SSB devices,
+- * where no valid SPROM can be found in the shadow registers.
++ * With this function the architecture implementation may register a callback
++ * handler which wills the SPROM data structure. The fallback is only used for
++ * PCI based SSB devices, where no valid SPROM can be found in the shadow registers.
+  *
+  * This function is useful for weird architectures that have a half-assed SSB device
+  * hardwired to their PCI bus.
+@@ -163,18 +164,21 @@ out:
+  *
+  * This function is available for architecture code, only. So it is not exported.
+  */
+-int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom)
++int ssb_arch_register_fallback_sprom(int (*sprom_callback)(struct ssb_bus *bus))
+ {
+-      if (fallback_sprom)
++      if (get_fallback_sprom)
+               return -EEXIST;
+-      fallback_sprom = sprom;
++      get_fallback_sprom = sprom_callback;
+       return 0;
+ }
+-const struct ssb_sprom *ssb_get_fallback_sprom(void)
++int ssb_fill_sprom_with_fallback(struct ssb_bus *bus)
+ {
+-      return fallback_sprom;
++      if (!get_fallback_sprom)
++              return -ENOENT;
++
++      return get_fallback_sprom(bus);
+ }
+ /* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */
+--- a/drivers/ssb/ssb_private.h
++++ b/drivers/ssb/ssb_private.h
+@@ -171,7 +171,7 @@ ssize_t ssb_attr_sprom_store(struct ssb_
+                            const char *buf, size_t count,
+                            int (*sprom_check_crc)(const u16 *sprom, size_t size),
+                            int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom));
+-extern const struct ssb_sprom *ssb_get_fallback_sprom(void);
++extern int ssb_fill_sprom_with_fallback(struct ssb_bus *bus);
+ /* core.c */
+--- a/include/linux/ssb/ssb.h
++++ b/include/linux/ssb/ssb.h
+@@ -404,7 +404,8 @@ extern bool ssb_is_sprom_available(struc
+ /* Set a fallback SPROM.
+  * See kdoc at the function definition for complete documentation. */
+-extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
++extern int ssb_arch_register_fallback_sprom(
++              int (*sprom_callback)(struct ssb_bus *bus));
+ /* Suspend a SSB bus.
+  * Call this from the parent bus suspend routine. */
diff --git a/target/linux/brcm47xx/patches-2.6.38/032-bcm47xx-extend-bcm47xx_fill_sprom-with-prefix.patch b/target/linux/brcm47xx/patches-2.6.38/032-bcm47xx-extend-bcm47xx_fill_sprom-with-prefix.patch
new file mode 100644 (file)
index 0000000..acf65bd
--- /dev/null
@@ -0,0 +1,69 @@
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -59,10 +59,23 @@ static void bcm47xx_machine_halt(void)
+ }
+ #define READ_FROM_NVRAM(_outvar, name, buf) \
+-      if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\
++      if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
+               sprom->_outvar = simple_strtoul(buf, NULL, 0);
+-static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
++static inline int nvram_getprefix(const char *prefix, char *name,
++                                char *buf, int len)
++{
++      if (prefix) {
++              char key[100];
++
++              snprintf(key, sizeof(key), "%s%s", prefix, name);
++              return nvram_getenv(key, buf, len);
++      }
++
++      return nvram_getenv(name, buf, len);
++}
++
++static void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
+ {
+       char buf[100];
+       u32 boardflags;
+@@ -71,11 +84,11 @@ static void bcm47xx_fill_sprom(struct ss
+       sprom->revision = 1; /* Fallback: Old hardware does not define this. */
+       READ_FROM_NVRAM(revision, "sromrev", buf);
+-      if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
++      if (nvram_getprefix(prefix, "il0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->il0mac);
+-      if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
++      if (nvram_getprefix(prefix, "et0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et0mac);
+-      if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
++      if (nvram_getprefix(prefix, "et1macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et1mac);
+       READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf);
+       READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf);
+@@ -127,14 +140,14 @@ static void bcm47xx_fill_sprom(struct ss
+       READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf);
+       READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf);
+-      if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) {
++      if (nvram_getprefix(prefix, "boardflags", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags_lo = (boardflags & 0x0000FFFFU);
+                       sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16;
+               }
+       }
+-      if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) {
++      if (nvram_getprefix(prefix, "boardflags2", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags2_lo = (boardflags & 0x0000FFFFU);
+@@ -160,7 +173,7 @@ static int bcm47xx_get_invariants(struct
+       if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
+               iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
+-      bcm47xx_fill_sprom(&iv->sprom);
++      bcm47xx_fill_sprom(&iv->sprom, NULL);
+       if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
+               iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
diff --git a/target/linux/brcm47xx/patches-2.6.38/033-bcm47xx-register-fallback-callback.patch b/target/linux/brcm47xx/patches-2.6.38/033-bcm47xx-register-fallback-callback.patch
new file mode 100644 (file)
index 0000000..f63deac
--- /dev/null
@@ -0,0 +1,48 @@
+--- a/arch/mips/bcm47xx/nvram.c
++++ b/arch/mips/bcm47xx/nvram.c
+@@ -23,7 +23,7 @@
+ static char nvram_buf[NVRAM_SPACE];
+ /* Probe for NVRAM header */
+-static void __init early_nvram_init(void)
++static void early_nvram_init(void)
+ {
+       struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+       struct nvram_header *header;
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -156,6 +156,22 @@ static void bcm47xx_fill_sprom(struct ss
+       }
+ }
++int bcm47xx_get_sprom(struct ssb_bus *bus)
++{
++      char prefix[10];
++
++      if (bus->bustype == SSB_BUSTYPE_PCI) {
++              snprintf(prefix, sizeof(prefix), "pci/%x/%x/",
++                       bus->host_pci->bus->number + 1,
++                       PCI_SLOT(bus->host_pci->devfn));
++              bcm47xx_fill_sprom(&bus->sprom, prefix);
++              return 0;
++      } else {
++              printk(KERN_WARNING "bcm47xx: unable to fill SPROM for given bustype.\n");
++              return -EINVAL;
++      }
++}
++
+ static int bcm47xx_get_invariants(struct ssb_bus *bus,
+                                  struct ssb_init_invariants *iv)
+ {
+@@ -212,6 +228,11 @@ void __init plat_mem_setup(void)
+       char buf[100];
+       struct ssb_mipscore *mcore;
++      err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom);
++      if (err)
++              printk(KERN_WARNING "bcm47xx: someone else already registered"
++                      " a ssb SPROM callback handler (err %d)\n", err);
++
+       err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
+                                     bcm47xx_get_invariants);
+       if (err)
diff --git a/target/linux/brcm47xx/patches-2.6.38/034-bcm47xx-extend-and-fix-fill-sprom.patch b/target/linux/brcm47xx/patches-2.6.38/034-bcm47xx-extend-and-fix-fill-sprom.patch
new file mode 100644 (file)
index 0000000..490ca67
--- /dev/null
@@ -0,0 +1,122 @@
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -62,6 +62,11 @@ static void bcm47xx_machine_halt(void)
+       if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
+               sprom->_outvar = simple_strtoul(buf, NULL, 0);
++#define READ_FROM_NVRAM2(_outvar, name1, name2, buf) \
++      if (nvram_getprefix(prefix, name1, buf, sizeof(buf)) >= 0 || \
++          nvram_getprefix(prefix, name2, buf, sizeof(buf)) >= 0)\
++              sprom->_outvar = simple_strtoul(buf, NULL, 0);
++
+ static inline int nvram_getprefix(const char *prefix, char *name,
+                                 char *buf, int len)
+ {
+@@ -75,6 +80,27 @@ static inline int nvram_getprefix(const
+       return nvram_getenv(name, buf, len);
+ }
++static u32 nvram_getu32(const char *name, char *buf, int len)
++{
++      int rv;
++      char key[100];
++      u16 var0, var1;
++
++      snprintf(key, sizeof(key), "%s0", name);
++      rv = nvram_getenv(key, buf, len);
++      /* return 0 here so this looks like unset */
++      if (rv < 0)
++              return 0;
++      var0 = simple_strtoul(buf, NULL, 0);
++
++      snprintf(key, sizeof(key), "%s1", name);
++      rv = nvram_getenv(key, buf, len);
++      if (rv < 0)
++              return 0;
++      var1 = simple_strtoul(buf, NULL, 0);
++      return var1 << 16 | var0;
++}
++
+ static void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
+ {
+       char buf[100];
+@@ -84,7 +110,8 @@ static void bcm47xx_fill_sprom(struct ss
+       sprom->revision = 1; /* Fallback: Old hardware does not define this. */
+       READ_FROM_NVRAM(revision, "sromrev", buf);
+-      if (nvram_getprefix(prefix, "il0macaddr", buf, sizeof(buf)) >= 0)
++      if (nvram_getprefix(prefix, "il0macaddr", buf, sizeof(buf)) >= 0 ||
+++         nvram_getprefix(prefix, "macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->il0mac);
+       if (nvram_getprefix(prefix, "et0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et0mac);
+@@ -110,20 +137,36 @@ static void bcm47xx_fill_sprom(struct ss
+       READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf);
+       READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf);
+       READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf);
+-      READ_FROM_NVRAM(gpio0, "wl0gpio0", buf);
+-      READ_FROM_NVRAM(gpio1, "wl0gpio1", buf);
+-      READ_FROM_NVRAM(gpio2, "wl0gpio2", buf);
+-      READ_FROM_NVRAM(gpio3, "wl0gpio3", buf);
+-      READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf);
+-      READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf);
+-      READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf);
+-      READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf);
+-      READ_FROM_NVRAM(itssi_a, "pa1itssit", buf);
+-      READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf);
++      READ_FROM_NVRAM2(gpio0, "ledbh0", "wl0gpio0", buf);
++      READ_FROM_NVRAM2(gpio1, "ledbh1", "wl0gpio1", buf);
++      READ_FROM_NVRAM2(gpio2, "ledbh2", "wl0gpio2", buf);
++      READ_FROM_NVRAM2(gpio3, "ledbh3", "wl0gpio3", buf);
++      READ_FROM_NVRAM2(maxpwr_bg, "maxp2ga0", "pa0maxpwr", buf);
++      READ_FROM_NVRAM2(maxpwr_al, "maxp5gla0", "pa1lomaxpwr", buf);
++      READ_FROM_NVRAM2(maxpwr_a, "maxp5ga0", "pa1maxpwr", buf);
++      READ_FROM_NVRAM2(maxpwr_ah, "maxp5gha0", "pa1himaxpwr", buf);
++      READ_FROM_NVRAM2(itssi_bg, "itt5ga0", "pa0itssit", buf);
++      READ_FROM_NVRAM2(itssi_a, "itt2ga0", "pa1itssit", buf);
+       READ_FROM_NVRAM(tri2g, "tri2g", buf);
+       READ_FROM_NVRAM(tri5gl, "tri5gl", buf);
+       READ_FROM_NVRAM(tri5g, "tri5g", buf);
+       READ_FROM_NVRAM(tri5gh, "tri5gh", buf);
++      READ_FROM_NVRAM(txpid2g[0], "txpid2ga0", buf);
++      READ_FROM_NVRAM(txpid2g[1], "txpid2ga1", buf);
++      READ_FROM_NVRAM(txpid2g[2], "txpid2ga2", buf);
++      READ_FROM_NVRAM(txpid2g[3], "txpid2ga3", buf);
++      READ_FROM_NVRAM(txpid5g[0], "txpid5ga0", buf);
++      READ_FROM_NVRAM(txpid5g[1], "txpid5ga1", buf);
++      READ_FROM_NVRAM(txpid5g[2], "txpid5ga2", buf);
++      READ_FROM_NVRAM(txpid5g[3], "txpid5ga3", buf);
++      READ_FROM_NVRAM(txpid5gl[0], "txpid5gla0", buf);
++      READ_FROM_NVRAM(txpid5gl[1], "txpid5gla1", buf);
++      READ_FROM_NVRAM(txpid5gl[2], "txpid5gla2", buf);
++      READ_FROM_NVRAM(txpid5gl[3], "txpid5gla3", buf);
++      READ_FROM_NVRAM(txpid5gh[0], "txpid5gha0", buf);
++      READ_FROM_NVRAM(txpid5gh[1], "txpid5gha1", buf);
++      READ_FROM_NVRAM(txpid5gh[2], "txpid5gha2", buf);
++      READ_FROM_NVRAM(txpid5gh[3], "txpid5gha3", buf);
+       READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf);
+       READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf);
+       READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf);
+@@ -135,10 +178,18 @@ static void bcm47xx_fill_sprom(struct ss
+       READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf);
+       READ_FROM_NVRAM(bxa5g, "bxa5g", buf);
+       READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf);
+-      READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf);
+-      READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf);
+-      READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf);
+-      READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf);
++
++      sprom->ofdm2gpo = nvram_getu32("ofdm2gpo", buf, sizeof(buf));
++      sprom->ofdm5glpo = nvram_getu32("ofdm5glpo", buf, sizeof(buf));
++      sprom->ofdm5gpo = nvram_getu32("ofdm5gpo", buf, sizeof(buf));
++      sprom->ofdm5ghpo = nvram_getu32("ofdm5ghpo", buf, sizeof(buf));
++
++      READ_FROM_NVRAM(antenna_gain.ghz24.a0, "ag0", buf);
++      READ_FROM_NVRAM(antenna_gain.ghz24.a1, "ag1", buf);
++      READ_FROM_NVRAM(antenna_gain.ghz24.a2, "ag2", buf);
++      READ_FROM_NVRAM(antenna_gain.ghz24.a3, "ag3", buf);
++      memcpy(&sprom->antenna_gain.ghz5, &sprom->antenna_gain.ghz24,
++             sizeof(sprom->antenna_gain.ghz5));
+       if (nvram_getprefix(prefix, "boardflags", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
index abb2044f7872a7f42163f74fb9e34bd2c6833da7..5ccb62fc6fb4e6da7fc264bc9f15b6fad8f00128 100644 (file)
@@ -33,7 +33,7 @@
 +EXPORT_SYMBOL(nvram_get);
 --- a/arch/mips/bcm47xx/setup.c
 +++ b/arch/mips/bcm47xx/setup.c
-@@ -226,3 +226,20 @@ void __init plat_mem_setup(void)
+@@ -311,3 +311,20 @@ void __init plat_mem_setup(void)
        _machine_halt = bcm47xx_machine_halt;
        pm_power_off = bcm47xx_machine_halt;
  }
index 9ed4a4de4a92c0bcd7f5a536f7d51f63bea2463e..29e12a81b9208d01315ca6d31668aa29b5175e89 100644 (file)
@@ -253,8 +253,8 @@ out the configuration than the in kernel cfe config reader.
 +extern char *cfe_env_get(char *nv_buf, const char *name);
  
  /* Probe for NVRAM header */
- static void __init early_nvram_init(void)
-@@ -33,6 +35,25 @@ static void __init early_nvram_init(void
+ static void early_nvram_init(void)
+@@ -33,6 +35,25 @@ static void early_nvram_init(void)
  
        base = mcore->flash_window;
        lim = mcore->flash_window_size;
diff --git a/target/linux/brcm47xx/patches-2.6.38/977-ssb_export_fallback_sprom.patch b/target/linux/brcm47xx/patches-2.6.38/977-ssb_export_fallback_sprom.patch
deleted file mode 100644 (file)
index 4ce9ba1..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
---- a/drivers/ssb/sprom.c
-+++ b/drivers/ssb/sprom.c
-@@ -176,6 +176,7 @@ const struct ssb_sprom *ssb_get_fallback
- {
-       return fallback_sprom;
- }
-+EXPORT_SYMBOL(ssb_get_fallback_sprom);
- /* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */
- bool ssb_is_sprom_available(struct ssb_bus *bus)
---- a/include/linux/ssb/ssb.h
-+++ b/include/linux/ssb/ssb.h
-@@ -412,6 +412,7 @@ extern bool ssb_is_sprom_available(struc
- /* Set a fallback SPROM.
-  * See kdoc at the function definition for complete documentation. */
- extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
-+extern const struct ssb_sprom *ssb_get_fallback_sprom(void);
- /* Suspend a SSB bus.
-  * Call this from the parent bus suspend routine. */
diff --git a/target/linux/brcm47xx/patches-2.6.38/980-wnr834b_no_cardbus_invariant.patch b/target/linux/brcm47xx/patches-2.6.38/980-wnr834b_no_cardbus_invariant.patch
new file mode 100644 (file)
index 0000000..1d6e069
--- /dev/null
@@ -0,0 +1,13 @@
+--- a/arch/mips/bcm47xx/setup.c
++++ b/arch/mips/bcm47xx/setup.c
+@@ -245,6 +245,10 @@ static int bcm47xx_get_invariants(struct
+       if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
+               iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
++      /* Do not indicate cardbus for Netgear WNR834B V1 and V2 */
++      if (iv->boardinfo.type == 0x0472 && iv->has_cardbus_slot)
++              iv->has_cardbus_slot = 0;
++
+       return 0;
+ }
index 99ee29f91041ddbf25ef24e27030533c6c4a5159..fc99f53455171c08a51e24849d41f546deb61be0 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
 +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
-@@ -852,6 +852,10 @@ static struct platform_device mtd_dev = 
+@@ -852,6 +852,10 @@ static struct platform_device mtd_dev =
        .num_resources          = ARRAY_SIZE(mtd_resources),
  };
  
index 2f6a27e06ac19dc3e7fcc46499d9d7aec8e4bfe7..6011db71e243ccc8e41774ae4f0f0fc9f1eb941d 100644 (file)
@@ -17,7 +17,7 @@
  };
  
  static struct board_info __initdata board_rta1025w_16 = {
-@@ -1001,6 +1004,9 @@ int __init board_register_devices(void)
+@@ -1002,6 +1005,9 @@ int __init board_register_devices(void)
        if (board.has_dsp)
                bcm63xx_dsp_register(&board.dsp);
  
   * SPI clock
   */
  static void spi_set(struct clk *clk, int enable)
-@@ -208,6 +232,8 @@ struct clk *clk_get(struct device *dev, 
+@@ -208,6 +232,8 @@ struct clk *clk_get(struct device *dev,
                return &clk_ephy;
        if (!strcmp(id, "usbh"))
                return &clk_usbh;
index 70637e5d482388fc0dc2323672bc67812cac3622..e9619d472354efad53958cacabecece92196e3bd 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
 +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
-@@ -1007,6 +1007,9 @@ int __init board_register_devices(void)
+@@ -1008,6 +1008,9 @@ int __init board_register_devices(void)
        if (board.has_udc0)
                bcm63xx_udc_register();
  
index d73d6f0ac7344fda6d99fbd029f5852118255c43..fc39eb4ce91a6ae0912cdbf9c3c3fb060fcbb21e 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
 +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
-@@ -1010,6 +1010,9 @@ int __init board_register_devices(void)
+@@ -1011,6 +1011,9 @@ int __init board_register_devices(void)
        if (board.num_devs)
                platform_add_devices(board.devs, board.num_devs);
  
index 5a81a08995eccd990d1c088d9ae257c82fddd123..35c490c4df9be589830cf5a77994ba0524cb0d0f 100644 (file)
  #include <board_bcm963xx.h>
  
  #define PFX   "board_bcm963xx: "
-@@ -1586,6 +1587,9 @@ int __init board_register_devices(void)
+@@ -1587,6 +1588,9 @@ int __init board_register_devices(void)
        if (board.num_spis)
                spi_register_board_info(board.spis, board.num_spis);
  
index 816343e6399ef9d8d54ef9c473bedec93c894796..513ff999a0d64fc3a200f83cd5eaf5c3f86a892c 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/usb/host/ehci-hub.c
 +++ b/drivers/usb/host/ehci-hub.c
-@@ -861,11 +861,13 @@ static int ehci_hub_control (
+@@ -882,11 +882,13 @@ static int ehci_hub_control (
                         * power switching; they're allowed to just limit the
                         * current.  khubd will turn the power back on.
                         */
diff --git a/target/linux/brcm63xx/patches-2.6.37/500-ssb-add-callback-for-sprom.patch b/target/linux/brcm63xx/patches-2.6.37/500-ssb-add-callback-for-sprom.patch
new file mode 100644 (file)
index 0000000..7e153a1
--- /dev/null
@@ -0,0 +1,157 @@
+From 62a518124cff3970d99f7ccdab457f4289e3b982 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sat, 30 Apr 2011 15:42:30 +0200
+Subject: [PATCH 1/4] ssb: add callback for sprom
+
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c |   16 ++++++++++++++--
+ drivers/ssb/pci.c                         |   13 ++++++++-----
+ drivers/ssb/sprom.c                       |   26 +++++++++++++++-----------
+ drivers/ssb/ssb_private.h                 |    2 +-
+ include/linux/ssb/ssb.h                   |    3 ++-
+ 5 files changed, 40 insertions(+), 20 deletions(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -1927,6 +1927,17 @@ static struct ssb_sprom bcm63xx_sprom =
+       .boardflags_lo          = 0x2848,
+       .boardflags_hi          = 0x0000,
+ };
++
++int bcm63xx_get_fallback_sprom(struct ssb_bus *bus)
++{
++      if (bus->bustype == SSB_BUSTYPE_PCI) {
++              memcpy(&bus->sprom, &bcm63xx_sprom, sizeof(struct ssb_sprom));
++              return 0;
++      } else {
++              printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
++              return -EINVAL;
++      }
++}
+ #endif
+ /*
+@@ -2111,8 +2122,9 @@ void __init board_prom_init(void)
+       if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
+               memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+               memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+-              if (ssb_arch_set_fallback_sprom(&bcm63xx_sprom) < 0)
+-                      printk(KERN_ERR "failed to register fallback SPROM\n");
++              if (ssb_arch_register_fallback_sprom(
++                              &bcm63xx_get_fallback_sprom) < 0)
++                      printk(KERN_ERR PFX "failed to register fallback SPROM\n");
+       }
+ #endif
+ }
+--- a/drivers/ssb/pci.c
++++ b/drivers/ssb/pci.c
+@@ -662,7 +662,6 @@ static int sprom_extract(struct ssb_bus
+ static int ssb_pci_sprom_get(struct ssb_bus *bus,
+                            struct ssb_sprom *sprom)
+ {
+-      const struct ssb_sprom *fallback;
+       int err;
+       u16 *buf;
+@@ -707,10 +706,14 @@ static int ssb_pci_sprom_get(struct ssb_
+               if (err) {
+                       /* All CRC attempts failed.
+                        * Maybe there is no SPROM on the device?
+-                       * If we have a fallback, use that. */
+-                      fallback = ssb_get_fallback_sprom();
+-                      if (fallback) {
+-                              memcpy(sprom, fallback, sizeof(*sprom));
++                       * Now we ask the arch code if there is some sprom
++                       * avaliable for this device in some other storage */
++                      err = ssb_fill_sprom_with_fallback(bus);
++                      if (err) {
++                              ssb_printk(KERN_WARNING PFX "WARNING: Using"
++                                         " fallback SPROM failed (err %d)\n",
++                                         err);
++                      } else {
+                               err = 0;
+                               goto out_free;
+                       }
+--- a/drivers/ssb/sprom.c
++++ b/drivers/ssb/sprom.c
+@@ -17,7 +17,7 @@
+ #include <linux/slab.h>
+-static const struct ssb_sprom *fallback_sprom;
++static int(*get_fallback_sprom)(struct ssb_bus *dev);
+ static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
+@@ -145,13 +145,14 @@ out:
+ }
+ /**
+- * ssb_arch_set_fallback_sprom - Set a fallback SPROM for use if no SPROM is found.
++ * ssb_arch_register_fallback_sprom - Registers a method providing a fallback
++ * SPROM if no SPROM is found.
+  *
+- * @sprom: The SPROM data structure to register.
++ * @sprom_callback: The callbcak function.
+  *
+- * With this function the architecture implementation may register a fallback
+- * SPROM data structure. The fallback is only used for PCI based SSB devices,
+- * where no valid SPROM can be found in the shadow registers.
++ * With this function the architecture implementation may register a callback
++ * handler which wills the SPROM data structure. The fallback is only used for
++ * PCI based SSB devices, where no valid SPROM can be found in the shadow registers.
+  *
+  * This function is useful for weird architectures that have a half-assed SSB device
+  * hardwired to their PCI bus.
+@@ -163,18 +164,21 @@ out:
+  *
+  * This function is available for architecture code, only. So it is not exported.
+  */
+-int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom)
++int ssb_arch_register_fallback_sprom(int (*sprom_callback)(struct ssb_bus *bus))
+ {
+-      if (fallback_sprom)
++      if (get_fallback_sprom)
+               return -EEXIST;
+-      fallback_sprom = sprom;
++      get_fallback_sprom = sprom_callback;
+       return 0;
+ }
+-const struct ssb_sprom *ssb_get_fallback_sprom(void)
++int ssb_fill_sprom_with_fallback(struct ssb_bus *bus)
+ {
+-      return fallback_sprom;
++      if (!get_fallback_sprom)
++              return -ENOENT;
++
++      return get_fallback_sprom(bus);
+ }
+ /* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */
+--- a/drivers/ssb/ssb_private.h
++++ b/drivers/ssb/ssb_private.h
+@@ -171,7 +171,7 @@ ssize_t ssb_attr_sprom_store(struct ssb_
+                            const char *buf, size_t count,
+                            int (*sprom_check_crc)(const u16 *sprom, size_t size),
+                            int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom));
+-extern const struct ssb_sprom *ssb_get_fallback_sprom(void);
++extern int ssb_fill_sprom_with_fallback(struct ssb_bus *bus);
+ /* core.c */
+--- a/include/linux/ssb/ssb.h
++++ b/include/linux/ssb/ssb.h
+@@ -404,7 +404,8 @@ extern bool ssb_is_sprom_available(struc
+ /* Set a fallback SPROM.
+  * See kdoc at the function definition for complete documentation. */
+-extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
++extern int ssb_arch_register_fallback_sprom(
++              int (*sprom_callback)(struct ssb_bus *bus));
+ /* Suspend a SSB bus.
+  * Call this from the parent bus suspend routine. */
index 2a22a3a38f215a2344a00847ec94a77ef9dc034f..3447c37a3cbe4db935a584e0326537581cd106b5 100644 (file)
@@ -1,20 +1,19 @@
---- a/drivers/ssb/sprom.c
-+++ b/drivers/ssb/sprom.c
-@@ -176,6 +176,7 @@ const struct ssb_sprom *ssb_get_fallback
- {
-       return fallback_sprom;
- }
-+EXPORT_SYMBOL(ssb_get_fallback_sprom);
- /* http://bcm-v4.sipsolutions.net/802.11/IsSpromAvailable */
- bool ssb_is_sprom_available(struct ssb_bus *bus)
---- a/include/linux/ssb/ssb.h
-+++ b/include/linux/ssb/ssb.h
-@@ -401,6 +401,7 @@ extern bool ssb_is_sprom_available(struc
- /* Set a fallback SPROM.
-  * See kdoc at the function definition for complete documentation. */
- extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom);
-+extern const struct ssb_sprom *ssb_get_fallback_sprom(void);
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -1907,7 +1907,7 @@ static void __init nb4_nvram_fixup(void)
+  * bcm4318 WLAN work
+  */
+ #ifdef CONFIG_SSB_PCIHOST
+-static struct ssb_sprom bcm63xx_sprom = {
++struct ssb_sprom bcm63xx_sprom = {
+       .revision               = 0x02,
+       .board_rev              = 0x17,
+       .country_code           = 0x0,
+@@ -1927,6 +1927,7 @@ static struct ssb_sprom bcm63xx_sprom =
+       .boardflags_lo          = 0x2848,
+       .boardflags_hi          = 0x0000,
+ };
++EXPORT_SYMBOL(bcm63xx_sprom);
  
- /* Suspend a SSB bus.
-  * Call this from the parent bus suspend routine. */
+ int bcm63xx_get_fallback_sprom(struct ssb_bus *bus)
+ {