Root/target/linux/brcm47xx/patches-3.2/195-bcma-add-support-for-sprom-not-found-on-the-device.patch

1From 332b8f6ca7da3197c631928b6bd1e7fdca87e109 Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sat, 18 Feb 2012 01:16:35 +0100
4Subject: [PATCH 195/202] bcma: add support for sprom not found on the device.
5
6On SoCs the sprom is stored in the nvram in a special partition on the
7flash chip. The nvram contains the sprom for the main bus, but
8sometimes also for a pci devices using bcma. This patch makes it
9possible for the arch code to register a function to fetch the needed
10sprom from the nvram and provide it to the bcma code.
11
12Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
13---
14 drivers/bcma/sprom.c | 80 ++++++++++++++++++++++++++++++++++++++++----
15 include/linux/bcma/bcma.h | 6 +++
16 2 files changed, 78 insertions(+), 8 deletions(-)
17
18--- a/drivers/bcma/sprom.c
19+++ b/drivers/bcma/sprom.c
20@@ -16,6 +16,49 @@
21 
22 #define SPOFF(offset) ((offset) / sizeof(u16))
23 
24+static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
25+
26+/**
27+ * ssb_arch_register_fallback_sprom - Registers a method providing a
28+ * fallback SPROM if no SPROM is found.
29+ *
30+ * @sprom_callback: The callback function.
31+ *
32+ * With this function the architecture implementation may register a
33+ * callback handler which fills the SPROM data structure. The fallback is
34+ * only used for PCI based SSB devices, where no valid SPROM can be found
35+ * in the shadow registers.
36+ *
37+ * This function is useful for weird architectures that have a half-assed
38+ * SSB device hardwired to their PCI bus.
39+ *
40+ * Note that it does only work with PCI attached SSB devices. PCMCIA
41+ * devices currently don't use this fallback.
42+ * Architectures must provide the SPROM for native SSB devices anyway, so
43+ * the fallback also isn't used for native devices.
44+ *
45+ * This function is available for architecture code, only. So it is not
46+ * exported.
47+ */
48+int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus,
49+ struct ssb_sprom *out))
50+{
51+ if (get_fallback_sprom)
52+ return -EEXIST;
53+ get_fallback_sprom = sprom_callback;
54+
55+ return 0;
56+}
57+
58+static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
59+ struct ssb_sprom *out)
60+{
61+ if (!get_fallback_sprom)
62+ return -ENOENT;
63+
64+ return get_fallback_sprom(bus, out);
65+}
66+
67 /**************************************************
68  * R/W ops.
69  **************************************************/
70@@ -205,23 +248,44 @@ static void bcma_sprom_extract_r8(struct
71         SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
72 }
73 
74+static bool bcma_is_sprom_available(struct bcma_bus *bus)
75+{
76+ u32 sromctrl;
77+
78+ if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
79+ return false;
80+
81+ if (bus->drv_cc.core->id.rev >= 32) {
82+ sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
83+ if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT))
84+ return false;
85+ }
86+ return true;
87+}
88+
89 int bcma_sprom_get(struct bcma_bus *bus)
90 {
91     u16 offset;
92     u16 *sprom;
93- u32 sromctrl;
94     int err = 0;
95 
96     if (!bus->drv_cc.core)
97         return -EOPNOTSUPP;
98 
99- if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
100- return -ENOENT;
101-
102- if (bus->drv_cc.core->id.rev >= 32) {
103- sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
104- if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT))
105- return -ENOENT;
106+ if (!bcma_is_sprom_available(bus)) {
107+ /*
108+ * Maybe there is no SPROM on the device?
109+ * Now we ask the arch code if there is some sprom
110+ * available for this device in some other storage
111+ */
112+ err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
113+ if (err) {
114+ pr_warn("Using fallback SPROM failed (err %d)\n", err);
115+ } else {
116+ pr_debug("Using SPROM revision %d provided by"
117+ " platform.\n", bus->sprom.revision);
118+ return 0;
119+ }
120     }
121 
122     sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
123--- a/include/linux/bcma/bcma.h
124+++ b/include/linux/bcma/bcma.h
125@@ -177,6 +177,12 @@ int __bcma_driver_register(struct bcma_d
126 
127 extern void bcma_driver_unregister(struct bcma_driver *drv);
128 
129+/* Set a fallback SPROM.
130+ * See kdoc at the function definition for complete documentation. */
131+extern int bcma_arch_register_fallback_sprom(
132+ int (*sprom_callback)(struct bcma_bus *bus,
133+ struct ssb_sprom *out));
134+
135 struct bcma_bus {
136     /* The MMIO area. */
137     void __iomem *mmio;
138

Archive Download this file



interactive