aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bcma
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2012-02-27 18:56:10 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-03-05 15:20:50 -0500
commita027237a56f7d519eee5749cfb720e568d0bb0b6 (patch)
tree0d408171f47086b66330a844701747d8aa0e37fc /drivers/bcma
parent1c9351cf2180924c91bb85e5ba607f24a3d875b1 (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.c77
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
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),