brcm47xx: sprom for nvram parsing
[openwrt/svn-archive/archive.git] / target / linux / brcm47xx / patches-3.2 / 195-bcma-add-support-for-sprom-not-found-on-the-device.patch
1 From 332b8f6ca7da3197c631928b6bd1e7fdca87e109 Mon Sep 17 00:00:00 2001
2 From: Hauke Mehrtens <hauke@hauke-m.de>
3 Date: Sat, 18 Feb 2012 01:16:35 +0100
4 Subject: [PATCH 195/202] bcma: add support for sprom not found on the device.
5
6 On SoCs the sprom is stored in the nvram in a special partition on the
7 flash chip. The nvram contains the sprom for the main bus, but
8 sometimes also for a pci devices using bcma. This patch makes it
9 possible for the arch code to register a function to fetch the needed
10 sprom from the nvram and provide it to the bcma code.
11
12 Signed-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;