Merge tag 'iommu-fixes-v3.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[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 {
77         int i;
78         for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++)
79                 sprom[i] = bcma_read16(bus->drv_cc.core,
80                                        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)
128 {
129         int word;
130         u8 crc = 0xFF;
131
132         for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 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[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF);
137         crc ^= 0xFF;
138
139         return crc;
140 }
141
142 static int bcma_sprom_check_crc(const u16 *sprom)
143 {
144         u8 crc;
145         u8 expected_crc;
146         u16 tmp;
147
148         crc = bcma_sprom_crc(sprom);
149         tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 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(const u16 *sprom)
158 {
159         u16 revision;
160         int err;
161
162         err = bcma_sprom_check_crc(sprom);
163         if (err)
164                 return err;
165
166         revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV;
167         if (revision != 8 && revision != 9) {
168                 pr_err("Unsupported SPROM revision: %d\n", revision);
169                 return -ENOENT;
170         }
171
172         return 0;
173 }
174
175 /**************************************************
176  * SPROM extraction.
177  **************************************************/
178
179 #define SPOFF(offset)   ((offset) / sizeof(u16))
180
181 #define SPEX(_field, _offset, _mask, _shift)    \
182         bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift))
183
184 #define SPEX32(_field, _offset, _mask, _shift)  \
185         bus->sprom._field = ((((u32)sprom[SPOFF((_offset)+2)] << 16 | \
186                                 sprom[SPOFF(_offset)]) & (_mask)) >> (_shift))
187
188 #define SPEX_ARRAY8(_field, _offset, _mask, _shift)     \
189         do {    \
190                 SPEX(_field[0], _offset +  0, _mask, _shift);   \
191                 SPEX(_field[1], _offset +  2, _mask, _shift);   \
192                 SPEX(_field[2], _offset +  4, _mask, _shift);   \
193                 SPEX(_field[3], _offset +  6, _mask, _shift);   \
194                 SPEX(_field[4], _offset +  8, _mask, _shift);   \
195                 SPEX(_field[5], _offset + 10, _mask, _shift);   \
196                 SPEX(_field[6], _offset + 12, _mask, _shift);   \
197                 SPEX(_field[7], _offset + 14, _mask, _shift);   \
198         } while (0)
199
200 static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
201 {
202         u16 v, o;
203         int i;
204         u16 pwr_info_offset[] = {
205                 SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
206                 SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
207         };
208         BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
209                         ARRAY_SIZE(bus->sprom.core_pwr_info));
210
211         bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] &
212                 SSB_SPROM_REVISION_REV;
213
214         for (i = 0; i < 3; i++) {
215                 v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
216                 *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
217         }
218
219         SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0);
220
221         SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
222              SSB_SPROM4_TXPID2G0_SHIFT);
223         SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G1,
224              SSB_SPROM4_TXPID2G1_SHIFT);
225         SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G2,
226              SSB_SPROM4_TXPID2G2_SHIFT);
227         SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G3,
228              SSB_SPROM4_TXPID2G3_SHIFT);
229
230         SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL0,
231              SSB_SPROM4_TXPID5GL0_SHIFT);
232         SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL1,
233              SSB_SPROM4_TXPID5GL1_SHIFT);
234         SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL2,
235              SSB_SPROM4_TXPID5GL2_SHIFT);
236         SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL3,
237              SSB_SPROM4_TXPID5GL3_SHIFT);
238
239         SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G0,
240              SSB_SPROM4_TXPID5G0_SHIFT);
241         SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G1,
242              SSB_SPROM4_TXPID5G1_SHIFT);
243         SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G2,
244              SSB_SPROM4_TXPID5G2_SHIFT);
245         SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G3,
246              SSB_SPROM4_TXPID5G3_SHIFT);
247
248         SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH0,
249              SSB_SPROM4_TXPID5GH0_SHIFT);
250         SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH1,
251              SSB_SPROM4_TXPID5GH1_SHIFT);
252         SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH2,
253              SSB_SPROM4_TXPID5GH2_SHIFT);
254         SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH3,
255              SSB_SPROM4_TXPID5GH3_SHIFT);
256
257         SPEX(boardflags_lo, SSB_SPROM8_BFLLO, ~0, 0);
258         SPEX(boardflags_hi, SSB_SPROM8_BFLHI, ~0, 0);
259         SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0);
260         SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0);
261
262         SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
263         SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
264
265         /* Extract cores power info info */
266         for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
267                 o = pwr_info_offset[i];
268                 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
269                         SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
270                 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
271                         SSB_SPROM8_2G_MAXP, 0);
272
273                 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
274                 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
275                 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
276
277                 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
278                         SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
279                 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
280                         SSB_SPROM8_5G_MAXP, 0);
281                 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
282                         SSB_SPROM8_5GH_MAXP, 0);
283                 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
284                         SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
285
286                 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
287                 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
288                 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
289                 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
290                 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
291                 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
292                 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
293                 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
294                 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
295         }
296
297         SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS,
298              SSB_SROM8_FEM_TSSIPOS_SHIFT);
299         SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN,
300              SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
301         SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_PDET_RANGE,
302              SSB_SROM8_FEM_PDET_RANGE_SHIFT);
303         SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TR_ISO,
304              SSB_SROM8_FEM_TR_ISO_SHIFT);
305         SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_ANTSWLUT,
306              SSB_SROM8_FEM_ANTSWLUT_SHIFT);
307
308         SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TSSIPOS,
309              SSB_SROM8_FEM_TSSIPOS_SHIFT);
310         SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_EXTPA_GAIN,
311              SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
312         SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_PDET_RANGE,
313              SSB_SROM8_FEM_PDET_RANGE_SHIFT);
314         SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TR_ISO,
315              SSB_SROM8_FEM_TR_ISO_SHIFT);
316         SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
317              SSB_SROM8_FEM_ANTSWLUT_SHIFT);
318
319         SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
320              SSB_SPROM8_ANTAVAIL_A_SHIFT);
321         SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
322              SSB_SPROM8_ANTAVAIL_BG_SHIFT);
323         SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
324         SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
325              SSB_SPROM8_ITSSI_BG_SHIFT);
326         SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
327         SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
328              SSB_SPROM8_ITSSI_A_SHIFT);
329         SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
330         SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
331              SSB_SPROM8_MAXP_AL_SHIFT);
332         SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
333         SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
334              SSB_SPROM8_GPIOA_P1_SHIFT);
335         SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
336         SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
337              SSB_SPROM8_GPIOB_P3_SHIFT);
338         SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
339         SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
340              SSB_SPROM8_TRI5G_SHIFT);
341         SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
342         SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
343              SSB_SPROM8_TRI5GH_SHIFT);
344         SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G,
345              SSB_SPROM8_RXPO2G_SHIFT);
346         SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
347              SSB_SPROM8_RXPO5G_SHIFT);
348         SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
349         SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
350              SSB_SPROM8_RSSISMC2G_SHIFT);
351         SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
352              SSB_SPROM8_RSSISAV2G_SHIFT);
353         SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
354              SSB_SPROM8_BXA2G_SHIFT);
355         SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
356         SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
357              SSB_SPROM8_RSSISMC5G_SHIFT);
358         SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
359              SSB_SPROM8_RSSISAV5G_SHIFT);
360         SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
361              SSB_SPROM8_BXA5G_SHIFT);
362
363         SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0);
364         SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0);
365         SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0);
366         SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0);
367         SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0);
368         SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0);
369         SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0);
370         SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0);
371         SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0);
372         SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0);
373         SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0);
374         SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0);
375         SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0);
376         SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0);
377         SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0);
378         SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0);
379         SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
380
381         /* Extract the antenna gain values. */
382         SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
383              SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
384         SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
385              SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
386         SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
387              SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
388         SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
389              SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
390
391         SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
392              SSB_SPROM8_LEDDC_ON_SHIFT);
393         SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
394              SSB_SPROM8_LEDDC_OFF_SHIFT);
395
396         SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
397              SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
398         SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
399              SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
400         SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
401              SSB_SPROM8_TXRXC_SWITCH_SHIFT);
402
403         SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
404
405         SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
406         SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
407         SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
408         SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
409
410         SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
411              SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
412         SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
413              SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
414         SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
415              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
416              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
417         SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
418              SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
419         SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
420              SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
421              SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
422         SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
423              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
424              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
425         SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
426              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
427              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
428         SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
429              SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
430
431         SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
432         SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
433         SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
434         SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
435
436         SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
437              SSB_SPROM8_THERMAL_TRESH_SHIFT);
438         SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
439              SSB_SPROM8_THERMAL_OFFSET_SHIFT);
440         SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
441              SSB_SPROM8_TEMPDELTA_PHYCAL,
442              SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
443         SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
444              SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
445         SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
446              SSB_SPROM8_TEMPDELTA_HYSTERESIS,
447              SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
448 }
449
450 /*
451  * Indicates the presence of external SPROM.
452  */
453 static bool bcma_sprom_ext_available(struct bcma_bus *bus)
454 {
455         u32 chip_status;
456         u32 srom_control;
457         u32 present_mask;
458
459         if (bus->drv_cc.core->id.rev >= 31) {
460                 if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
461                         return false;
462
463                 srom_control = bcma_read32(bus->drv_cc.core,
464                                            BCMA_CC_SROM_CONTROL);
465                 return srom_control & BCMA_CC_SROM_CONTROL_PRESENT;
466         }
467
468         /* older chipcommon revisions use chip status register */
469         chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
470         switch (bus->chipinfo.id) {
471         case BCMA_CHIP_ID_BCM4313:
472                 present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
473                 break;
474
475         case BCMA_CHIP_ID_BCM4331:
476                 present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
477                 break;
478
479         default:
480                 return true;
481         }
482
483         return chip_status & present_mask;
484 }
485
486 /*
487  * Indicates that on-chip OTP memory is present and enabled.
488  */
489 static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
490 {
491         u32 chip_status;
492         u32 otpsize = 0;
493         bool present;
494
495         chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
496         switch (bus->chipinfo.id) {
497         case BCMA_CHIP_ID_BCM4313:
498                 present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
499                 break;
500
501         case BCMA_CHIP_ID_BCM4331:
502                 present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
503                 break;
504
505         case BCMA_CHIP_ID_BCM43224:
506         case BCMA_CHIP_ID_BCM43225:
507                 /* for these chips OTP is always available */
508                 present = true;
509                 break;
510         case BCMA_CHIP_ID_BCM43228:
511                 present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT;
512                 break;
513         default:
514                 present = false;
515                 break;
516         }
517
518         if (present) {
519                 otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS;
520                 otpsize >>= BCMA_CC_CAP_OTPS_SHIFT;
521         }
522
523         return otpsize != 0;
524 }
525
526 /*
527  * Verify OTP is filled and determine the byte
528  * offset where SPROM data is located.
529  *
530  * On error, returns 0; byte offset otherwise.
531  */
532 static int bcma_sprom_onchip_offset(struct bcma_bus *bus)
533 {
534         struct bcma_device *cc = bus->drv_cc.core;
535         u32 offset;
536
537         /* verify OTP status */
538         if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0)
539                 return 0;
540
541         /* obtain bit offset from otplayout register */
542         offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET);
543         return BCMA_CC_SPROM + (offset >> 3);
544 }
545
546 int bcma_sprom_get(struct bcma_bus *bus)
547 {
548         u16 offset = BCMA_CC_SPROM;
549         u16 *sprom;
550         int err = 0;
551
552         if (!bus->drv_cc.core)
553                 return -EOPNOTSUPP;
554
555         if (!bcma_sprom_ext_available(bus)) {
556                 bool sprom_onchip;
557
558                 /*
559                  * External SPROM takes precedence so check
560                  * on-chip OTP only when no external SPROM
561                  * is present.
562                  */
563                 sprom_onchip = bcma_sprom_onchip_available(bus);
564                 if (sprom_onchip) {
565                         /* determine offset */
566                         offset = bcma_sprom_onchip_offset(bus);
567                 }
568                 if (!offset || !sprom_onchip) {
569                         /*
570                          * Maybe there is no SPROM on the device?
571                          * Now we ask the arch code if there is some sprom
572                          * available for this device in some other storage.
573                          */
574                         err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
575                         return err;
576                 }
577         }
578
579         sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
580                         GFP_KERNEL);
581         if (!sprom)
582                 return -ENOMEM;
583
584         if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
585             bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
586                 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
587
588         bcma_debug(bus, "SPROM offset 0x%x\n", offset);
589         bcma_sprom_read(bus, offset, sprom);
590
591         if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
592             bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
593                 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
594
595         err = bcma_sprom_valid(sprom);
596         if (err)
597                 goto out;
598
599         bcma_sprom_extract_r8(bus, sprom);
600
601 out:
602         kfree(sprom);
603         return err;
604 }