summaryrefslogtreecommitdiff
path: root/target/linux/brcm47xx/patches-3.2/196-bcma-add-support-for-sprom-not-found-on-the-device.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm47xx/patches-3.2/196-bcma-add-support-for-sprom-not-found-on-the-device.patch')
-rw-r--r--target/linux/brcm47xx/patches-3.2/196-bcma-add-support-for-sprom-not-found-on-the-device.patch125
1 files changed, 125 insertions, 0 deletions
diff --git a/target/linux/brcm47xx/patches-3.2/196-bcma-add-support-for-sprom-not-found-on-the-device.patch b/target/linux/brcm47xx/patches-3.2/196-bcma-add-support-for-sprom-not-found-on-the-device.patch
new file mode 100644
index 0000000000..296e10ae10
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.2/196-bcma-add-support-for-sprom-not-found-on-the-device.patch
@@ -0,0 +1,125 @@
+
+--- a/drivers/bcma/sprom.c
++++ b/drivers/bcma/sprom.c
+@@ -2,6 +2,8 @@
+ * Broadcom specific AMBA
+ * SPROM reading
+ *
++ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
++ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+@@ -16,6 +18,45 @@
+
+ #define SPOFF(offset) ((offset) / sizeof(u16))
+
++static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
++
++/**
++ * bcma_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
++ * used for PCI based BCMA devices, where no valid SPROM can be found
++ * in the shadow registers and to provide the SPROM for SoCs where BCMA is
++ * to controll the system bus.
++ *
++ * This function is useful for weird architectures that have a half-assed
++ * BCMA device hardwired to their PCI bus.
++ *
++ * 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 +246,43 @@ 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);
++ return sromctrl & BCMA_CC_SROM_CONTROL_PRESENT;
++ }
++ 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;