2 --- a/drivers/bcma/sprom.c
3 +++ b/drivers/bcma/sprom.c
5 * Broadcom specific AMBA
8 + * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
10 * Licensed under the GNU/GPL. See COPYING for details.
15 #define SPOFF(offset) ((offset) / sizeof(u16))
17 +static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
20 + * bcma_arch_register_fallback_sprom - Registers a method providing a
21 + * fallback SPROM if no SPROM is found.
23 + * @sprom_callback: The callback function.
25 + * With this function the architecture implementation may register a
26 + * callback handler which fills the SPROM data structure. The fallback is
27 + * used for PCI based BCMA devices, where no valid SPROM can be found
28 + * in the shadow registers and to provide the SPROM for SoCs where BCMA is
29 + * to controll the system bus.
31 + * This function is useful for weird architectures that have a half-assed
32 + * BCMA device hardwired to their PCI bus.
34 + * This function is available for architecture code, only. So it is not
37 +int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus,
38 + struct ssb_sprom *out))
40 + if (get_fallback_sprom)
42 + get_fallback_sprom = sprom_callback;
47 +static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
48 + struct ssb_sprom *out)
50 + if (!get_fallback_sprom)
53 + return get_fallback_sprom(bus, out);
56 /**************************************************
58 **************************************************/
59 @@ -205,23 +246,43 @@ static void bcma_sprom_extract_r8(struct
60 SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
63 +static bool bcma_is_sprom_available(struct bcma_bus *bus)
67 + if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
70 + if (bus->drv_cc.core->id.rev >= 32) {
71 + sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
72 + return sromctrl & BCMA_CC_SROM_CONTROL_PRESENT;
77 int bcma_sprom_get(struct bcma_bus *bus)
84 if (!bus->drv_cc.core)
87 - if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
90 - if (bus->drv_cc.core->id.rev >= 32) {
91 - sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
92 - if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT))
94 + if (!bcma_is_sprom_available(bus)) {
96 + * Maybe there is no SPROM on the device?
97 + * Now we ask the arch code if there is some sprom
98 + * available for this device in some other storage.
100 + err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
102 + pr_warn("Using fallback SPROM failed (err %d)\n", err);
104 + pr_debug("Using SPROM revision %d provided by"
105 + " platform.\n", bus->sprom.revision);
110 sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
111 --- a/include/linux/bcma/bcma.h
112 +++ b/include/linux/bcma/bcma.h
113 @@ -177,6 +177,12 @@ int __bcma_driver_register(struct bcma_d
115 extern void bcma_driver_unregister(struct bcma_driver *drv);
117 +/* Set a fallback SPROM.
118 + * See kdoc at the function definition for complete documentation. */
119 +extern int bcma_arch_register_fallback_sprom(
120 + int (*sprom_callback)(struct bcma_bus *bus,
121 + struct ssb_sprom *out));