Merge branch 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / bcma / sprom.c
1 /*
2  * Broadcom specific AMBA
3  * SPROM reading
4  *
5  * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
6  *
7  * Licensed under the GNU/GPL. See COPYING for details.
8  */
9
10 #include "bcma_private.h"
11
12 #include <linux/bcma/bcma.h>
13 #include <linux/bcma/bcma_regs.h>
14 #include <linux/pci.h>
15 #include <linux/io.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/slab.h>
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         int err;
53
54         if (!get_fallback_sprom) {
55                 err = -ENOENT;
56                 goto fail;
57         }
58
59         err = get_fallback_sprom(bus, out);
60         if (err)
61                 goto fail;
62
63         bcma_debug(bus, "Using SPROM revision %d provided by platform.\n",
64                    bus->sprom.revision);
65         return 0;
66 fail:
67         bcma_warn(bus, "Using fallback SPROM failed (err %d)\n", err);
68         return err;
69 }
70
71 /**************************************************
72  * R/W ops.
73  **************************************************/
74
75 static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom,
76                             size_t words)
77 {
78         int i;
79         for (i = 0; i < words; i++)
80                 sprom[i] = bcma_read16(bus->drv_cc.core, offset + (i * 2));
81 }
82
83 /**************************************************
84  * Validation.
85  **************************************************/
86
87 static inline u8 bcma_crc8(u8 crc, u8 data)
88 {
89         /* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
90         static const u8 t[] = {
91                 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
92                 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
93                 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
94                 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
95                 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
96                 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
97                 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
98                 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
99                 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
100                 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
101                 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
102                 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
103                 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
104                 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
105                 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
106                 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
107                 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
108                 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
109                 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
110                 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
111                 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
112                 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
113                 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
114                 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
115                 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
116                 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
117                 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
118                 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
119                 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
120                 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
121                 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
122                 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
123         };
124         return t[crc ^ data];
125 }
126
127 static u8 bcma_sprom_crc(const u16 *sprom, size_t words)
128 {
129         int word;
130         u8 crc = 0xFF;
131
132         for (word = 0; word < words - 1; word++) {
133                 crc = bcma_crc8(crc, sprom[word] & 0x00FF);
134                 crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8);
135         }
136         crc = bcma_crc8(crc, sprom[words - 1] & 0x00FF);
137         crc ^= 0xFF;
138
139         return crc;
140 }
141
142 static int bcma_sprom_check_crc(const u16 *sprom, size_t words)
143 {
144         u8 crc;
145         u8 expected_crc;
146         u16 tmp;
147
148         crc = bcma_sprom_crc(sprom, words);
149         tmp = sprom[words - 1] & SSB_SPROM_REVISION_CRC;
150         expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
151         if (crc != expected_crc)
152                 return -EPROTO;
153
154         return 0;
155 }
156
157 static int bcma_sprom_valid(struct bcma_bus *bus, const u16 *sprom,
158                             size_t words)
159 {
160         u16 revision;
161         int err;
162
163         err = bcma_sprom_check_crc(sprom, words);
164         if (err)
165                 return err;
166
167         revision = sprom[words - 1] & SSB_SPROM_REVISION_REV;
168         if (revision != 8 && revision != 9 && revision != 10) {
169                 pr_err("Unsupported SPROM revision: %d\n", revision);
170                 return -ENOENT;
171         }
172
173         bus->sprom.revision = revision;
174         bcma_debug(bus, "Found SPROM revision %d\n", revision);
175
176         return 0;
177 }
178
179 /**************************************************
180  * SPROM extraction.
181  **************************************************/
182
183 #define SPOFF(offset)   ((offset) / sizeof(u16))
184
185 #define SPEX(_field, _offset, _mask, _shift)    \
186         bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift))
187
188 #define SPEX32(_field, _offset, _mask, _shift)  \
189         bus->sprom._field = ((((u32)sprom[SPOFF((_offset)+2)] << 16 | \
190                                 sprom[SPOFF(_offset)]) & (_mask)) >> (_shift))
191
192 #define SPEX_ARRAY8(_field, _offset, _mask, _shift)     \
193         do {    \
194                 SPEX(_field[0], _offset +  0, _mask, _shift);   \
195                 SPEX(_field[1], _offset +  2, _mask, _shift);   \
196                 SPEX(_field[2], _offset +  4, _mask, _shift);   \
197                 SPEX(_field[3], _offset +  6, _mask, _shift);   \
198                 SPEX(_field[4], _offset +  8, _mask, _shift);   \
199                 SPEX(_field[5], _offset + 10, _mask, _shift);   \
200                 SPEX(_field[6], _offset + 12, _mask, _shift);   \
201                 SPEX(_field[7], _offset + 14, _mask, _shift);   \
202         } while (0)
203
204 static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
205 {
206         u16 v, o;
207         int i;
208         u16 pwr_info_offset[] = {
209                 SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
210                 SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
211         };
212         BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
213                         ARRAY_SIZE(bus->sprom.core_pwr_info));
214
215         for (i = 0; i < 3; i++) {
216                 v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
217                 *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
218         }
219
220         SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0);
221         SPEX(board_type, SSB_SPROM1_SPID, ~0, 0);
222
223         SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
224              SSB_SPROM4_TXPID2G0_SHIFT);
225         SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G1,
226              SSB_SPROM4_TXPID2G1_SHIFT);
227         SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G2,
228              SSB_SPROM4_TXPID2G2_SHIFT);
229         SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G3,
230              SSB_SPROM4_TXPID2G3_SHIFT);
231
232         SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL0,
233              SSB_SPROM4_TXPID5GL0_SHIFT);
234         SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL1,
235              SSB_SPROM4_TXPID5GL1_SHIFT);
236         SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL2,
237              SSB_SPROM4_TXPID5GL2_SHIFT);
238         SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL3,
239              SSB_SPROM4_TXPID5GL3_SHIFT);
240
241         SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G0,
242              SSB_SPROM4_TXPID5G0_SHIFT);
243         SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G1,
244              SSB_SPROM4_TXPID5G1_SHIFT);
245         SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G2,
246              SSB_SPROM4_TXPID5G2_SHIFT);
247         SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G3,
248              SSB_SPROM4_TXPID5G3_SHIFT);
249
250         SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH0,
251              SSB_SPROM4_TXPID5GH0_SHIFT);
252         SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH1,
253              SSB_SPROM4_TXPID5GH1_SHIFT);
254         SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH2,
255              SSB_SPROM4_TXPID5GH2_SHIFT);
256         SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH3,
257              SSB_SPROM4_TXPID5GH3_SHIFT);
258
259         SPEX(boardflags_lo, SSB_SPROM8_BFLLO, ~0, 0);
260         SPEX(boardflags_hi, SSB_SPROM8_BFLHI, ~0, 0);
261         SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0);
262         SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0);
263
264         SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
265         SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
266
267         /* Extract cores power info info */
268         for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
269                 o = pwr_info_offset[i];
270                 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
271                         SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
272                 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
273                         SSB_SPROM8_2G_MAXP, 0);
274
275                 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
276                 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
277                 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
278
279                 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
280                         SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
281                 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
282                         SSB_SPROM8_5G_MAXP, 0);
283                 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
284                         SSB_SPROM8_5GH_MAXP, 0);
285                 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
286                         SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
287
288                 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
289                 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
290                 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
291                 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
292                 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
293                 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
294                 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
295                 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
296                 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
297         }
298
299         SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS,
300              SSB_SROM8_FEM_TSSIPOS_SHIFT);
301         SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN,
302              SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
303         SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_PDET_RANGE,
304              SSB_SROM8_FEM_PDET_RANGE_SHIFT);
305         SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TR_ISO,
306              SSB_SROM8_FEM_TR_ISO_SHIFT);
307         SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_ANTSWLUT,
308              SSB_SROM8_FEM_ANTSWLUT_SHIFT);
309
310         SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TSSIPOS,
311              SSB_SROM8_FEM_TSSIPOS_SHIFT);
312         SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_EXTPA_GAIN,
313              SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
314         SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_PDET_RANGE,
315              SSB_SROM8_FEM_PDET_RANGE_SHIFT);
316         SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TR_ISO,
317              SSB_SROM8_FEM_TR_ISO_SHIFT);
318         SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
319              SSB_SROM8_FEM_ANTSWLUT_SHIFT);
320
321         SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
322              SSB_SPROM8_ANTAVAIL_A_SHIFT);
323         SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
324              SSB_SPROM8_ANTAVAIL_BG_SHIFT);
325         SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
326         SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
327              SSB_SPROM8_ITSSI_BG_SHIFT);
328         SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
329         SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
330              SSB_SPROM8_ITSSI_A_SHIFT);
331         SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
332         SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
333              SSB_SPROM8_MAXP_AL_SHIFT);
334         SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
335         SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
336              SSB_SPROM8_GPIOA_P1_SHIFT);
337         SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
338         SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
339              SSB_SPROM8_GPIOB_P3_SHIFT);
340         SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
341         SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
342              SSB_SPROM8_TRI5G_SHIFT);
343         SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
344         SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
345              SSB_SPROM8_TRI5GH_SHIFT);
346         SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G,
347              SSB_SPROM8_RXPO2G_SHIFT);
348         SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
349              SSB_SPROM8_RXPO5G_SHIFT);
350         SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
351         SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
352              SSB_SPROM8_RSSISMC2G_SHIFT);
353         SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
354              SSB_SPROM8_RSSISAV2G_SHIFT);
355         SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
356              SSB_SPROM8_BXA2G_SHIFT);
357         SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
358         SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
359              SSB_SPROM8_RSSISMC5G_SHIFT);
360         SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
361              SSB_SPROM8_RSSISAV5G_SHIFT);
362         SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
363              SSB_SPROM8_BXA5G_SHIFT);
364
365         SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0);
366         SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0);
367         SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0);
368         SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0);
369         SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0);
370         SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0);
371         SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0);
372         SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0);
373         SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0);
374         SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0);
375         SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0);
376         SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0);
377         SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0);
378         SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0);
379         SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0);
380         SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0);
381         SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
382
383         /* Extract the antenna gain values. */
384         SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
385              SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
386         SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
387              SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
388         SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
389              SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
390         SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
391              SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
392
393         SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
394              SSB_SPROM8_LEDDC_ON_SHIFT);
395         SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
396              SSB_SPROM8_LEDDC_OFF_SHIFT);
397
398         SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
399              SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
400         SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
401              SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
402         SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
403              SSB_SPROM8_TXRXC_SWITCH_SHIFT);
404
405         SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
406
407         SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
408         SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
409         SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
410         SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
411
412         SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
413              SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
414         SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
415              SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
416         SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
417              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
418              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
419         SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
420              SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
421         SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
422              SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
423              SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
424         SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
425              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
426              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
427         SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
428              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
429              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
430         SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
431              SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
432
433         SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
434         SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
435         SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
436         SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
437
438         SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
439              SSB_SPROM8_THERMAL_TRESH_SHIFT);
440         SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
441              SSB_SPROM8_THERMAL_OFFSET_SHIFT);
442         SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
443              SSB_SPROM8_TEMPDELTA_PHYCAL,
444              SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
445         SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
446              SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
447         SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
448              SSB_SPROM8_TEMPDELTA_HYSTERESIS,
449              SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
450 }
451
452 /*
453  * Indicates the presence of external SPROM.
454  */
455 static bool bcma_sprom_ext_available(struct bcma_bus *bus)
456 {
457         u32 chip_status;
458         u32 srom_control;
459         u32 present_mask;
460
461         if (bus->drv_cc.core->id.rev >= 31) {
462                 if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
463                         return false;
464
465                 srom_control = bcma_read32(bus->drv_cc.core,
466                                            BCMA_CC_SROM_CONTROL);
467                 return srom_control & BCMA_CC_SROM_CONTROL_PRESENT;
468         }
469
470         /* older chipcommon revisions use chip status register */
471         chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
472         switch (bus->chipinfo.id) {
473         case BCMA_CHIP_ID_BCM4313:
474                 present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
475                 break;
476
477         case BCMA_CHIP_ID_BCM4331:
478                 present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
479                 break;
480
481         default:
482                 return true;
483         }
484
485         return chip_status & present_mask;
486 }
487
488 /*
489  * Indicates that on-chip OTP memory is present and enabled.
490  */
491 static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
492 {
493         u32 chip_status;
494         u32 otpsize = 0;
495         bool present;
496
497         chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
498         switch (bus->chipinfo.id) {
499         case BCMA_CHIP_ID_BCM4313:
500                 present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
501                 break;
502
503         case BCMA_CHIP_ID_BCM4331:
504                 present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
505                 break;
506         case BCMA_CHIP_ID_BCM43142:
507         case BCMA_CHIP_ID_BCM43224:
508         case BCMA_CHIP_ID_BCM43225:
509                 /* for these chips OTP is always available */
510                 present = true;
511                 break;
512         case BCMA_CHIP_ID_BCM43227:
513         case BCMA_CHIP_ID_BCM43228:
514         case BCMA_CHIP_ID_BCM43428:
515                 present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT;
516                 break;
517         default:
518                 present = false;
519                 break;
520         }
521
522         if (present) {
523                 otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS;
524                 otpsize >>= BCMA_CC_CAP_OTPS_SHIFT;
525         }
526
527         return otpsize != 0;
528 }
529
530 /*
531  * Verify OTP is filled and determine the byte
532  * offset where SPROM data is located.
533  *
534  * On error, returns 0; byte offset otherwise.
535  */
536 static int bcma_sprom_onchip_offset(struct bcma_bus *bus)
537 {
538         struct bcma_device *cc = bus->drv_cc.core;
539         u32 offset;
540
541         /* verify OTP status */
542         if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0)
543                 return 0;
544
545         /* obtain bit offset from otplayout register */
546         offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET);
547         return BCMA_CC_SPROM + (offset >> 3);
548 }
549
550 int bcma_sprom_get(struct bcma_bus *bus)
551 {
552         u16 offset = BCMA_CC_SPROM;
553         u16 *sprom;
554         size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4,
555                                  SSB_SPROMSIZE_WORDS_R10, };
556         int i, err = 0;
557
558         if (!bus->drv_cc.core)
559                 return -EOPNOTSUPP;
560
561         if (!bcma_sprom_ext_available(bus)) {
562                 bool sprom_onchip;
563
564                 /*
565                  * External SPROM takes precedence so check
566                  * on-chip OTP only when no external SPROM
567                  * is present.
568                  */
569                 sprom_onchip = bcma_sprom_onchip_available(bus);
570                 if (sprom_onchip) {
571                         /* determine offset */
572                         offset = bcma_sprom_onchip_offset(bus);
573                 }
574                 if (!offset || !sprom_onchip) {
575                         /*
576                          * Maybe there is no SPROM on the device?
577                          * Now we ask the arch code if there is some sprom
578                          * available for this device in some other storage.
579                          */
580                         err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
581                         return err;
582                 }
583         }
584
585         if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
586             bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
587                 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
588
589         bcma_debug(bus, "SPROM offset 0x%x\n", offset);
590         for (i = 0; i < ARRAY_SIZE(sprom_sizes); i++) {
591                 size_t words = sprom_sizes[i];
592
593                 sprom = kcalloc(words, sizeof(u16), GFP_KERNEL);
594                 if (!sprom)
595                         return -ENOMEM;
596
597                 bcma_sprom_read(bus, offset, sprom, words);
598                 err = bcma_sprom_valid(bus, sprom, words);
599                 if (!err)
600                         break;
601
602                 kfree(sprom);
603         }
604
605         if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
606             bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
607                 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
608
609         if (err) {
610                 bcma_warn(bus, "Invalid SPROM read from the PCIe card, trying to use fallback SPROM\n");
611                 err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
612         } else {
613                 bcma_sprom_extract_r8(bus, sprom);
614                 kfree(sprom);
615         }
616
617         return err;
618 }