aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/bcma/sprom.c77
-rw-r--r--include/linux/bcma/bcma.h6
2 files changed, 75 insertions, 8 deletions
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index ca7752510d5b..916ae255ff64 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -2,6 +2,8 @@
2 * Broadcom specific AMBA 2 * Broadcom specific AMBA
3 * SPROM reading 3 * SPROM reading
4 * 4 *
5 * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
6 *
5 * Licensed under the GNU/GPL. See COPYING for details. 7 * Licensed under the GNU/GPL. See COPYING for details.
6 */ 8 */
7 9
@@ -14,6 +16,45 @@
14#include <linux/dma-mapping.h> 16#include <linux/dma-mapping.h>
15#include <linux/slab.h> 17#include <linux/slab.h>
16 18
19static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
20
21/**
22 * bcma_arch_register_fallback_sprom - Registers a method providing a
23 * fallback SPROM if no SPROM is found.
24 *
25 * @sprom_callback: The callback function.
26 *
27 * With this function the architecture implementation may register a
28 * callback handler which fills the SPROM data structure. The fallback is
29 * used for PCI based BCMA devices, where no valid SPROM can be found
30 * in the shadow registers and to provide the SPROM for SoCs where BCMA is
31 * to controll the system bus.
32 *
33 * This function is useful for weird architectures that have a half-assed
34 * BCMA device hardwired to their PCI bus.
35 *
36 * This function is available for architecture code, only. So it is not
37 * exported.
38 */
39int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus,
40 struct ssb_sprom *out))
41{
42 if (get_fallback_sprom)
43 return -EEXIST;
44 get_fallback_sprom = sprom_callback;
45
46 return 0;
47}
48
49static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
50 struct ssb_sprom *out)
51{
52 if (!get_fallback_sprom)
53 return -ENOENT;
54
55 return get_fallback_sprom(bus, out);
56}
57
17/************************************************** 58/**************************************************
18 * R/W ops. 59 * R/W ops.
19 **************************************************/ 60 **************************************************/
@@ -246,23 +287,43 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
246 SSB_SROM8_FEM_ANTSWLUT_SHIFT); 287 SSB_SROM8_FEM_ANTSWLUT_SHIFT);
247} 288}
248 289
290static bool bcma_is_sprom_available(struct bcma_bus *bus)
291{
292 u32 sromctrl;
293
294 if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
295 return false;
296
297 if (bus->drv_cc.core->id.rev >= 32) {
298 sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
299 return sromctrl & BCMA_CC_SROM_CONTROL_PRESENT;
300 }
301 return true;
302}
303
249int bcma_sprom_get(struct bcma_bus *bus) 304int bcma_sprom_get(struct bcma_bus *bus)
250{ 305{
251 u16 offset; 306 u16 offset;
252 u16 *sprom; 307 u16 *sprom;
253 u32 sromctrl;
254 int err = 0; 308 int err = 0;
255 309
256 if (!bus->drv_cc.core) 310 if (!bus->drv_cc.core)
257 return -EOPNOTSUPP; 311 return -EOPNOTSUPP;
258 312
259 if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) 313 if (!bcma_is_sprom_available(bus)) {
260 return -ENOENT; 314 /*
261 315 * Maybe there is no SPROM on the device?
262 if (bus->drv_cc.core->id.rev >= 32) { 316 * Now we ask the arch code if there is some sprom
263 sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL); 317 * available for this device in some other storage.
264 if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT)) 318 */
265 return -ENOENT; 319 err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
320 if (err) {
321 pr_warn("Using fallback SPROM failed (err %d)\n", err);
322 } else {
323 pr_debug("Using SPROM revision %d provided by"
324 " platform.\n", bus->sprom.revision);
325 return 0;
326 }
266 } 327 }
267 328
268 sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), 329 sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 46bbd088c4ad..5af9a075498f 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -176,6 +176,12 @@ int __bcma_driver_register(struct bcma_driver *drv, struct module *owner);
176 176
177extern void bcma_driver_unregister(struct bcma_driver *drv); 177extern void bcma_driver_unregister(struct bcma_driver *drv);
178 178
179/* Set a fallback SPROM.
180 * See kdoc at the function definition for complete documentation. */
181extern int bcma_arch_register_fallback_sprom(
182 int (*sprom_callback)(struct bcma_bus *bus,
183 struct ssb_sprom *out));
184
179struct bcma_bus { 185struct bcma_bus {
180 /* The MMIO area. */ 186 /* The MMIO area. */
181 void __iomem *mmio; 187 void __iomem *mmio;