brcm47xx: sprom for nvram parsing
[openwrt.git] / target / linux / brcm47xx / patches-3.2 / 195-bcma-add-support-for-sprom-not-found-on-the-device.patch
diff --git a/target/linux/brcm47xx/patches-3.2/195-bcma-add-support-for-sprom-not-found-on-the-device.patch b/target/linux/brcm47xx/patches-3.2/195-bcma-add-support-for-sprom-not-found-on-the-device.patch
new file mode 100644 (file)
index 0000000..6991576
--- /dev/null
@@ -0,0 +1,137 @@
+From 332b8f6ca7da3197c631928b6bd1e7fdca87e109 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sat, 18 Feb 2012 01:16:35 +0100
+Subject: [PATCH 195/202] bcma: add support for sprom not found on the device.
+
+On SoCs the sprom is stored in the nvram in a special partition on the
+flash chip. The nvram contains the sprom for the main bus, but
+sometimes also for a pci devices using bcma. This patch makes it
+possible for the arch code to register a function to fetch the needed
+sprom from the nvram and provide it to the bcma code.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/bcma/sprom.c      |   80 ++++++++++++++++++++++++++++++++++++++++----
+ include/linux/bcma/bcma.h |    6 +++
+ 2 files changed, 78 insertions(+), 8 deletions(-)
+
+--- a/drivers/bcma/sprom.c
++++ b/drivers/bcma/sprom.c
+@@ -16,6 +16,49 @@
+ #define SPOFF(offset) ((offset) / sizeof(u16))
++static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
++
++/**
++ * ssb_arch_register_fallback_sprom - Registers a method providing a
++ * fallback SPROM if no SPROM is found.
++ *
++ * @sprom_callback: The callback function.
++ *
++ * With this function the architecture implementation may register a
++ * callback handler which fills 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.
++ *
++ * Note that it does only work with PCI attached SSB devices. PCMCIA
++ * devices currently don't use this fallback.
++ * Architectures must provide the SPROM for native SSB devices anyway, so
++ * the fallback also isn't used for native devices.
++ *
++ * This function is available for architecture code, only. So it is not
++ * exported.
++ */
++int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus,
++                                   struct ssb_sprom *out))
++{
++      if (get_fallback_sprom)
++              return -EEXIST;
++      get_fallback_sprom = sprom_callback;
++
++      return 0;
++}
++
++static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
++                                       struct ssb_sprom *out)
++{
++      if (!get_fallback_sprom)
++              return -ENOENT;
++
++      return get_fallback_sprom(bus, out);
++}
++
+ /**************************************************
+  * R/W ops.
+  **************************************************/
+@@ -205,23 +248,44 @@ static void bcma_sprom_extract_r8(struct
+               SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
+ }
++static bool bcma_is_sprom_available(struct bcma_bus *bus)
++{
++      u32 sromctrl;
++
++      if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
++              return false;
++
++      if (bus->drv_cc.core->id.rev >= 32) {
++              sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
++              if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT))
++                      return false;
++      }
++      return true;
++}
++
+ int bcma_sprom_get(struct bcma_bus *bus)
+ {
+       u16 offset;
+       u16 *sprom;
+-      u32 sromctrl;
+       int err = 0;
+       if (!bus->drv_cc.core)
+               return -EOPNOTSUPP;
+-      if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
+-              return -ENOENT;
+-
+-      if (bus->drv_cc.core->id.rev >= 32) {
+-              sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
+-              if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT))
+-                      return -ENOENT;
++      if (!bcma_is_sprom_available(bus)) {
++              /*
++               * Maybe there is no SPROM on the device?
++               * Now we ask the arch code if there is some sprom
++               * available for this device in some other storage
++               */
++              err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
++              if (err) {
++                      pr_warn("Using fallback SPROM failed (err %d)\n", err);
++              } else {
++                      pr_debug("Using SPROM revision %d provided by"
++                               " platform.\n", bus->sprom.revision);
++                      return 0;
++              }
+       }
+       sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
+--- a/include/linux/bcma/bcma.h
++++ b/include/linux/bcma/bcma.h
+@@ -177,6 +177,12 @@ int __bcma_driver_register(struct bcma_d
+ extern void bcma_driver_unregister(struct bcma_driver *drv);
++/* Set a fallback SPROM.
++ * See kdoc at the function definition for complete documentation. */
++extern int bcma_arch_register_fallback_sprom(
++              int (*sprom_callback)(struct bcma_bus *bus,
++              struct ssb_sprom *out));
++
+ struct bcma_bus {
+       /* The MMIO area. */
+       void __iomem *mmio;
This page took 0.031841 seconds and 4 git commands to generate.