diff options
author | Hauke Mehrtens <hauke@hauke-m.de> | 2012-02-27 18:56:10 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-03-05 15:20:50 -0500 |
commit | a027237a56f7d519eee5749cfb720e568d0bb0b6 (patch) | |
tree | 0d408171f47086b66330a844701747d8aa0e37fc /drivers/bcma | |
parent | 1c9351cf2180924c91bb85e5ba607f24a3d875b1 (diff) |
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>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/bcma')
-rw-r--r-- | drivers/bcma/sprom.c | 77 |
1 files changed, 69 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 | ||
19 | static 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 | */ | ||
39 | int 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 | |||
49 | static 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 | ||
290 | static 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 | |||
249 | int bcma_sprom_get(struct bcma_bus *bus) | 304 | int 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), |