ssb: pci: Standardize a function to get mac address
[deliverable/linux.git] / drivers / ssb / pci.c
CommitLineData
61e115a5
MB
1/*
2 * Sonics Silicon Backplane PCI-Hostbus related functions.
3 *
eb032b98 4 * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
61e115a5
MB
5 * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
6 * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
7 * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
8 * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
9 *
10 * Derived from the Broadcom 4400 device driver.
11 * Copyright (C) 2002 David S. Miller (davem@redhat.com)
12 * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
13 * Copyright (C) 2006 Broadcom Corporation.
14 *
15 * Licensed under the GNU/GPL. See COPYING for details.
16 */
17
18#include <linux/ssb/ssb.h>
19#include <linux/ssb/ssb_regs.h>
5a0e3ad6 20#include <linux/slab.h>
61e115a5
MB
21#include <linux/pci.h>
22#include <linux/delay.h>
23
24#include "ssb_private.h"
25
26
27/* Define the following to 1 to enable a printk on each coreswitch. */
28#define SSB_VERBOSE_PCICORESWITCH_DEBUG 0
29
30
31/* Lowlevel coreswitching */
32int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
33{
34 int err;
35 int attempts = 0;
36 u32 cur_core;
37
38 while (1) {
39 err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
40 (coreidx * SSB_CORE_SIZE)
41 + SSB_ENUM_BASE);
42 if (err)
43 goto error;
44 err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
45 &cur_core);
46 if (err)
47 goto error;
48 cur_core = (cur_core - SSB_ENUM_BASE)
49 / SSB_CORE_SIZE;
50 if (cur_core == coreidx)
51 break;
52
53 if (attempts++ > SSB_BAR0_MAX_RETRIES)
54 goto error;
55 udelay(10);
56 }
57 return 0;
58error:
59 ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
60 return -ENODEV;
61}
62
63int ssb_pci_switch_core(struct ssb_bus *bus,
64 struct ssb_device *dev)
65{
66 int err;
67 unsigned long flags;
68
69#if SSB_VERBOSE_PCICORESWITCH_DEBUG
70 ssb_printk(KERN_INFO PFX
71 "Switching to %s core, index %d\n",
72 ssb_core_name(dev->id.coreid),
73 dev->core_index);
74#endif
75
76 spin_lock_irqsave(&bus->bar_lock, flags);
77 err = ssb_pci_switch_coreidx(bus, dev->core_index);
78 if (!err)
79 bus->mapped_device = dev;
80 spin_unlock_irqrestore(&bus->bar_lock, flags);
81
82 return err;
83}
84
85/* Enable/disable the on board crystal oscillator and/or PLL. */
86int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
87{
88 int err;
89 u32 in, out, outenable;
90 u16 pci_status;
91
92 if (bus->bustype != SSB_BUSTYPE_PCI)
93 return 0;
94
95 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
96 if (err)
97 goto err_pci;
98 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
99 if (err)
100 goto err_pci;
101 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
102 if (err)
103 goto err_pci;
104
105 outenable |= what;
106
107 if (turn_on) {
108 /* Avoid glitching the clock if GPRS is already using it.
109 * We can't actually read the state of the PLLPD so we infer it
110 * by the value of XTAL_PU which *is* readable via gpioin.
111 */
112 if (!(in & SSB_GPIO_XTAL)) {
113 if (what & SSB_GPIO_XTAL) {
114 /* Turn the crystal on */
115 out |= SSB_GPIO_XTAL;
116 if (what & SSB_GPIO_PLL)
117 out |= SSB_GPIO_PLL;
118 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
119 if (err)
120 goto err_pci;
121 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
122 outenable);
123 if (err)
124 goto err_pci;
125 msleep(1);
126 }
127 if (what & SSB_GPIO_PLL) {
128 /* Turn the PLL on */
129 out &= ~SSB_GPIO_PLL;
130 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
131 if (err)
132 goto err_pci;
133 msleep(5);
134 }
135 }
136
137 err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
138 if (err)
139 goto err_pci;
140 pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
141 err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
142 if (err)
143 goto err_pci;
144 } else {
145 if (what & SSB_GPIO_XTAL) {
146 /* Turn the crystal off */
147 out &= ~SSB_GPIO_XTAL;
148 }
149 if (what & SSB_GPIO_PLL) {
150 /* Turn the PLL off */
151 out |= SSB_GPIO_PLL;
152 }
153 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
154 if (err)
155 goto err_pci;
156 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
157 if (err)
158 goto err_pci;
159 }
160
161out:
162 return err;
163
164err_pci:
165 printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n");
166 err = -EBUSY;
167 goto out;
168}
169
170/* Get the word-offset for a SSB_SPROM_XXX define. */
0a182fd8 171#define SPOFF(offset) ((offset) / sizeof(u16))
61e115a5 172/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
f679056b 173#define SPEX16(_outvar, _offset, _mask, _shift) \
61e115a5 174 out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
f679056b
GS
175#define SPEX32(_outvar, _offset, _mask, _shift) \
176 out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
177 in[SPOFF(_offset)]) & (_mask)) >> (_shift))
178#define SPEX(_outvar, _offset, _mask, _shift) \
179 SPEX16(_outvar, _offset, _mask, _shift)
180
e2da4bd3
HM
181#define SPEX_ARRAY8(_field, _offset, _mask, _shift) \
182 do { \
183 SPEX(_field[0], _offset + 0, _mask, _shift); \
184 SPEX(_field[1], _offset + 2, _mask, _shift); \
185 SPEX(_field[2], _offset + 4, _mask, _shift); \
186 SPEX(_field[3], _offset + 6, _mask, _shift); \
187 SPEX(_field[4], _offset + 8, _mask, _shift); \
188 SPEX(_field[5], _offset + 10, _mask, _shift); \
189 SPEX(_field[6], _offset + 12, _mask, _shift); \
190 SPEX(_field[7], _offset + 14, _mask, _shift); \
191 } while (0)
192
61e115a5
MB
193
194static inline u8 ssb_crc8(u8 crc, u8 data)
195{
196 /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */
197 static const u8 t[] = {
198 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
199 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
200 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
201 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
202 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
203 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
204 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
205 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
206 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
207 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
208 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
209 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
210 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
211 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
212 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
213 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
214 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
215 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
216 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
217 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
218 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
219 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
220 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
221 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
222 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
223 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
224 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
225 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
226 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
227 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
228 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
229 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
230 };
231 return t[crc ^ data];
232}
233
e5652756
JP
234static void sprom_get_mac(char *mac, const u16 *in)
235{
236 int i;
237 for (i = 0; i < 3; i++) {
238 *mac++ = in[i];
239 *mac++ = in[i] >> 8;
240 }
241}
242
c272ef44 243static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
61e115a5
MB
244{
245 int word;
246 u8 crc = 0xFF;
247
c272ef44 248 for (word = 0; word < size - 1; word++) {
61e115a5
MB
249 crc = ssb_crc8(crc, sprom[word] & 0x00FF);
250 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
251 }
c272ef44 252 crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
61e115a5
MB
253 crc ^= 0xFF;
254
255 return crc;
256}
257
e7ec2e32 258static int sprom_check_crc(const u16 *sprom, size_t size)
61e115a5
MB
259{
260 u8 crc;
261 u8 expected_crc;
262 u16 tmp;
263
c272ef44
LF
264 crc = ssb_sprom_crc(sprom, size);
265 tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
61e115a5
MB
266 expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
267 if (crc != expected_crc)
268 return -EPROTO;
269
270 return 0;
271}
272
e7ec2e32 273static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
61e115a5
MB
274{
275 int i;
276
c272ef44 277 for (i = 0; i < bus->sprom_size; i++)
ea2db495 278 sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
e7ec2e32
MB
279
280 return 0;
61e115a5
MB
281}
282
283static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
284{
285 struct pci_dev *pdev = bus->host_pci;
286 int i, err;
287 u32 spromctl;
c272ef44 288 u16 size = bus->sprom_size;
61e115a5
MB
289
290 ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
291 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
292 if (err)
293 goto err_ctlreg;
294 spromctl |= SSB_SPROMCTL_WE;
295 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
296 if (err)
297 goto err_ctlreg;
298 ssb_printk(KERN_NOTICE PFX "[ 0%%");
299 msleep(500);
c272ef44
LF
300 for (i = 0; i < size; i++) {
301 if (i == size / 4)
61e115a5 302 ssb_printk("25%%");
c272ef44 303 else if (i == size / 2)
61e115a5 304 ssb_printk("50%%");
c272ef44 305 else if (i == (size * 3) / 4)
61e115a5
MB
306 ssb_printk("75%%");
307 else if (i % 2)
308 ssb_printk(".");
ea2db495 309 writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
61e115a5
MB
310 mmiowb();
311 msleep(20);
312 }
313 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
314 if (err)
315 goto err_ctlreg;
316 spromctl &= ~SSB_SPROMCTL_WE;
317 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
318 if (err)
319 goto err_ctlreg;
320 msleep(500);
321 ssb_printk("100%% ]\n");
322 ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
323
324 return 0;
325err_ctlreg:
326 ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
327 return err;
328}
329
e861b98d
MB
330static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
331 u16 mask, u16 shift)
332{
333 u16 v;
334 u8 gain;
335
336 v = in[SPOFF(SSB_SPROM1_AGAIN)];
337 gain = (v & mask) >> shift;
338 if (gain == 0xFF)
339 gain = 2; /* If unset use 2dBm */
340 if (sprom_revision == 1) {
341 /* Convert to Q5.2 */
342 gain <<= 2;
343 } else {
344 /* Q5.2 Fractional part is stored in 0xC0 */
345 gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
346 }
347
348 return (s8)gain;
349}
350
c272ef44 351static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
61e115a5 352{
c272ef44 353 u16 loc[3];
61e115a5 354
31ce12fb 355 if (out->revision == 3) /* rev 3 moved MAC */
c272ef44 356 loc[0] = SSB_SPROM3_IL0MAC;
31ce12fb 357 else {
c272ef44
LF
358 loc[0] = SSB_SPROM1_IL0MAC;
359 loc[1] = SSB_SPROM1_ET0MAC;
360 loc[2] = SSB_SPROM1_ET1MAC;
361 }
e5652756 362 sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
31ce12fb 363 if (out->revision < 3) { /* only rev 1-2 have et0, et1 */
e5652756
JP
364 sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
365 sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
61e115a5 366 }
c272ef44
LF
367 SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
368 SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
369 SSB_SPROM1_ETHPHY_ET1A_SHIFT);
e861b98d
MB
370 SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
371 SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
372 SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
bf7d420b
HM
373 if (out->revision == 1)
374 SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
375 SSB_SPROM1_BINF_CCODE_SHIFT);
e861b98d
MB
376 SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
377 SSB_SPROM1_BINF_ANTA_SHIFT);
378 SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
379 SSB_SPROM1_BINF_ANTBG_SHIFT);
c272ef44
LF
380 SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
381 SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
382 SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
383 SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
384 SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
385 SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
386 SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
387 SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
388 SSB_SPROM1_GPIOA_P1_SHIFT);
389 SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
390 SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
391 SSB_SPROM1_GPIOB_P3_SHIFT);
392 SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
393 SSB_SPROM1_MAXPWR_A_SHIFT);
394 SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
395 SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
396 SSB_SPROM1_ITSSI_A_SHIFT);
397 SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
398 SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
af4b7450
MB
399 if (out->revision >= 2)
400 SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
bf7d420b
HM
401 SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
402 SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
e861b98d
MB
403
404 /* Extract the antenna gain values. */
f8f8a660
HM
405 out->antenna_gain.a0 = r123_extract_antgain(out->revision, in,
406 SSB_SPROM1_AGAIN_BG,
407 SSB_SPROM1_AGAIN_BG_SHIFT);
408 out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
409 SSB_SPROM1_AGAIN_A,
410 SSB_SPROM1_AGAIN_A_SHIFT);
61e115a5
MB
411}
412
172c69a4
RM
413/* Revs 4 5 and 8 have partially shared layout */
414static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
415{
416 SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
417 SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
418 SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
419 SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
420 SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
421 SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
422 SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
423 SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
424
425 SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
426 SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
427 SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
428 SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
429 SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
430 SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
431 SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
432 SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
433
434 SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
435 SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
436 SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
437 SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
438 SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
439 SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
440 SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
441 SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
442
443 SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
444 SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
445 SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
446 SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
447 SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
448 SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
449 SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
450 SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
451}
452
095f695c 453static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
61e115a5 454{
095f695c 455 u16 il0mac_offset;
c272ef44 456
095f695c
LF
457 if (out->revision == 4)
458 il0mac_offset = SSB_SPROM4_IL0MAC;
459 else
460 il0mac_offset = SSB_SPROM5_IL0MAC;
e5652756
JP
461
462 sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
463
c272ef44
LF
464 SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
465 SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
466 SSB_SPROM4_ETHPHY_ET1A_SHIFT);
673335c8 467 SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
095f695c 468 if (out->revision == 4) {
bf7d420b
HM
469 SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
470 SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
095f695c
LF
471 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
472 SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
6d1d4ea4
RM
473 SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
474 SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
095f695c 475 } else {
bf7d420b
HM
476 SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
477 SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
095f695c
LF
478 SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
479 SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
6d1d4ea4
RM
480 SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
481 SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
095f695c 482 }
e861b98d
MB
483 SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
484 SSB_SPROM4_ANTAVAIL_A_SHIFT);
485 SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
486 SSB_SPROM4_ANTAVAIL_BG_SHIFT);
d3c319f9
LF
487 SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
488 SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
489 SSB_SPROM4_ITSSI_BG_SHIFT);
490 SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
491 SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
492 SSB_SPROM4_ITSSI_A_SHIFT);
095f695c
LF
493 if (out->revision == 4) {
494 SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
495 SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
496 SSB_SPROM4_GPIOA_P1_SHIFT);
497 SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
498 SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
499 SSB_SPROM4_GPIOB_P3_SHIFT);
500 } else {
501 SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
502 SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
503 SSB_SPROM5_GPIOA_P1_SHIFT);
504 SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
505 SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
506 SSB_SPROM5_GPIOB_P3_SHIFT);
507 }
e861b98d
MB
508
509 /* Extract the antenna gain values. */
f8f8a660 510 SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
e861b98d 511 SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
f8f8a660 512 SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
e861b98d 513 SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
f8f8a660 514 SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
e861b98d 515 SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
f8f8a660 516 SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
e861b98d 517 SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
e861b98d 518
172c69a4
RM
519 sprom_extract_r458(out, in);
520
c272ef44 521 /* TODO - get remaining rev 4 stuff needed */
61e115a5
MB
522}
523
6b1c7c67
MB
524static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
525{
526 int i;
e5652756 527 u16 o;
b0f70292
RM
528 u16 pwr_info_offset[] = {
529 SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
530 SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
531 };
532 BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
533 ARRAY_SIZE(out->core_pwr_info));
6b1c7c67
MB
534
535 /* extract the MAC address */
e5652756
JP
536 sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
537
673335c8 538 SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
bf7d420b
HM
539 SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
540 SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
6b1c7c67
MB
541 SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
542 SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
f679056b
GS
543 SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
544 SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
6b1c7c67
MB
545 SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
546 SSB_SPROM8_ANTAVAIL_A_SHIFT);
547 SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
548 SSB_SPROM8_ANTAVAIL_BG_SHIFT);
549 SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
550 SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
551 SSB_SPROM8_ITSSI_BG_SHIFT);
552 SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
553 SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
554 SSB_SPROM8_ITSSI_A_SHIFT);
f679056b
GS
555 SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
556 SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
557 SSB_SPROM8_MAXP_AL_SHIFT);
6b1c7c67
MB
558 SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
559 SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
560 SSB_SPROM8_GPIOA_P1_SHIFT);
561 SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
562 SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
563 SSB_SPROM8_GPIOB_P3_SHIFT);
f679056b
GS
564 SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
565 SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
566 SSB_SPROM8_TRI5G_SHIFT);
567 SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
568 SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
569 SSB_SPROM8_TRI5GH_SHIFT);
570 SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
571 SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
572 SSB_SPROM8_RXPO5G_SHIFT);
573 SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
574 SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
575 SSB_SPROM8_RSSISMC2G_SHIFT);
576 SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
577 SSB_SPROM8_RSSISAV2G_SHIFT);
578 SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
579 SSB_SPROM8_BXA2G_SHIFT);
580 SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
581 SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
582 SSB_SPROM8_RSSISMC5G_SHIFT);
583 SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
584 SSB_SPROM8_RSSISAV5G_SHIFT);
585 SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
586 SSB_SPROM8_BXA5G_SHIFT);
587 SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
588 SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
589 SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
590 SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
591 SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
592 SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
593 SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
594 SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
595 SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
596 SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
597 SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
598 SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
599 SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
600 SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
601 SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
602 SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
603 SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
6b1c7c67
MB
604
605 /* Extract the antenna gain values. */
f8f8a660 606 SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
6b1c7c67 607 SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
f8f8a660 608 SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
6b1c7c67 609 SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
f8f8a660 610 SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
6b1c7c67 611 SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
f8f8a660 612 SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
6b1c7c67 613 SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
6b1c7c67 614
b0f70292
RM
615 /* Extract cores power info info */
616 for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
617 o = pwr_info_offset[i];
618 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
619 SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
620 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
621 SSB_SPROM8_2G_MAXP, 0);
622
623 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
624 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
625 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
626
627 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
628 SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
629 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
630 SSB_SPROM8_5G_MAXP, 0);
631 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
632 SSB_SPROM8_5GH_MAXP, 0);
633 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
634 SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
635
636 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
637 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
638 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
639 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
640 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
641 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
642 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
643 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
644 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
645 }
646
8a5ac6ec
RM
647 /* Extract FEM info */
648 SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
649 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
650 SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
651 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
652 SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
653 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
654 SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
655 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
656 SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
657 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
658
659 SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
660 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
661 SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
662 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
663 SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
664 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
665 SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
666 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
667 SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
668 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
669
e2da4bd3
HM
670 SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
671 SSB_SPROM8_LEDDC_ON_SHIFT);
672 SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
673 SSB_SPROM8_LEDDC_OFF_SHIFT);
674
675 SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
676 SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
677 SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
678 SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
679 SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
680 SSB_SPROM8_TXRXC_SWITCH_SHIFT);
681
682 SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
683
684 SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
685 SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
686 SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
687 SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
688
689 SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
690 SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
691 SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
692 SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
693 SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
694 SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
695 SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
696 SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
697 SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
698 SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
699 SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
700 SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
701 SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
702 SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
703 SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
704 SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
705 SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
706 SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
707 SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
708 SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
709
710 SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
711 SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
712 SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
713 SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
714
715 SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
716 SSB_SPROM8_THERMAL_TRESH_SHIFT);
717 SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
718 SSB_SPROM8_THERMAL_OFFSET_SHIFT);
719 SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
720 SSB_SPROM8_TEMPDELTA_PHYCAL,
721 SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
722 SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
723 SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
724 SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
725 SSB_SPROM8_TEMPDELTA_HYSTERESIS,
726 SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
172c69a4
RM
727 sprom_extract_r458(out, in);
728
6b1c7c67
MB
729 /* TODO - get remaining rev 8 stuff needed */
730}
731
c272ef44
LF
732static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
733 const u16 *in, u16 size)
61e115a5
MB
734{
735 memset(out, 0, sizeof(*out));
736
c272ef44 737 out->revision = in[size - 1] & 0x00FF;
e861b98d 738 ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
31ce12fb
LF
739 memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
740 memset(out->et1mac, 0xFF, 6);
54435f9e 741
61e115a5
MB
742 if ((bus->chip_id & 0xFF00) == 0x4400) {
743 /* Workaround: The BCM44XX chip has a stupid revision
744 * number stored in the SPROM.
745 * Always extract r1. */
c272ef44 746 out->revision = 1;
54435f9e 747 ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
54435f9e
RM
748 }
749
750 switch (out->revision) {
751 case 1:
752 case 2:
753 case 3:
754 sprom_extract_r123(out, in);
755 break;
756 case 4:
757 case 5:
095f695c 758 sprom_extract_r45(out, in);
54435f9e
RM
759 break;
760 case 8:
761 sprom_extract_r8(out, in);
762 break;
763 default:
764 ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
98605c2e 765 " revision %d detected. Will extract"
54435f9e
RM
766 " v1\n", out->revision);
767 out->revision = 1;
768 sprom_extract_r123(out, in);
61e115a5
MB
769 }
770
4503183a
LF
771 if (out->boardflags_lo == 0xFFFF)
772 out->boardflags_lo = 0; /* per specs */
773 if (out->boardflags_hi == 0xFFFF)
774 out->boardflags_hi = 0; /* per specs */
775
61e115a5 776 return 0;
61e115a5
MB
777}
778
779static int ssb_pci_sprom_get(struct ssb_bus *bus,
780 struct ssb_sprom *sprom)
781{
ca4a0831 782 int err;
61e115a5
MB
783 u16 *buf;
784
d53cdbb9
JL
785 if (!ssb_is_sprom_available(bus)) {
786 ssb_printk(KERN_ERR PFX "No SPROM available!\n");
787 return -ENODEV;
788 }
25985edc 789 if (bus->chipco.dev) { /* can be unavailable! */
9d1ac34e
LF
790 /*
791 * get SPROM offset: SSB_SPROM_BASE1 except for
792 * chipcommon rev >= 31 or chip ID is 0x4312 and
793 * chipcommon status & 3 == 2
794 */
795 if (bus->chipco.dev->id.revision >= 31)
796 bus->sprom_offset = SSB_SPROM_BASE31;
797 else if (bus->chip_id == 0x4312 &&
798 (bus->chipco.status & 0x03) == 2)
799 bus->sprom_offset = SSB_SPROM_BASE31;
800 else
801 bus->sprom_offset = SSB_SPROM_BASE1;
da1fdb02
CF
802 } else {
803 bus->sprom_offset = SSB_SPROM_BASE1;
804 }
9d1ac34e 805 ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
ea2db495 806
c272ef44 807 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
61e115a5 808 if (!buf)
ca4a0831 809 return -ENOMEM;
c272ef44 810 bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
61e115a5 811 sprom_do_read(bus, buf);
c272ef44 812 err = sprom_check_crc(buf, bus->sprom_size);
61e115a5 813 if (err) {
2afc4901
LF
814 /* try for a 440 byte SPROM - revision 4 and higher */
815 kfree(buf);
816 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
817 GFP_KERNEL);
818 if (!buf)
ca4a0831 819 return -ENOMEM;
2afc4901
LF
820 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
821 sprom_do_read(bus, buf);
822 err = sprom_check_crc(buf, bus->sprom_size);
e79c1ba8
MB
823 if (err) {
824 /* All CRC attempts failed.
825 * Maybe there is no SPROM on the device?
b3ae52b6
HM
826 * Now we ask the arch code if there is some sprom
827 * available for this device in some other storage */
828 err = ssb_fill_sprom_with_fallback(bus, sprom);
829 if (err) {
830 ssb_printk(KERN_WARNING PFX "WARNING: Using"
831 " fallback SPROM failed (err %d)\n",
832 err);
833 } else {
834 ssb_dprintk(KERN_DEBUG PFX "Using SPROM"
835 " revision %d provided by"
836 " platform.\n", sprom->revision);
e79c1ba8
MB
837 err = 0;
838 goto out_free;
839 }
c272ef44
LF
840 ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
841 " SPROM CRC (corrupt SPROM)\n");
e79c1ba8 842 }
61e115a5 843 }
c272ef44 844 err = sprom_extract(bus, sprom, buf, bus->sprom_size);
61e115a5 845
e79c1ba8 846out_free:
61e115a5 847 kfree(buf);
61e115a5
MB
848 return err;
849}
850
851static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
852 struct ssb_boardinfo *bi)
853{
115f9450
SS
854 bi->vendor = bus->host_pci->subsystem_vendor;
855 bi->type = bus->host_pci->subsystem_device;
61e115a5
MB
856}
857
858int ssb_pci_get_invariants(struct ssb_bus *bus,
859 struct ssb_init_invariants *iv)
860{
861 int err;
862
863 err = ssb_pci_sprom_get(bus, &iv->sprom);
864 if (err)
865 goto out;
866 ssb_pci_get_boardinfo(bus, &iv->boardinfo);
867
868out:
869 return err;
870}
871
872#ifdef CONFIG_SSB_DEBUG
873static int ssb_pci_assert_buspower(struct ssb_bus *bus)
874{
875 if (likely(bus->powered_up))
876 return 0;
877
878 printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
879 "while accessing PCI MMIO space\n");
880 if (bus->power_warn_count <= 10) {
881 bus->power_warn_count++;
882 dump_stack();
883 }
884
885 return -ENODEV;
886}
887#else /* DEBUG */
888static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
889{
890 return 0;
891}
892#endif /* DEBUG */
893
ffc7689d
MB
894static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
895{
896 struct ssb_bus *bus = dev->bus;
897
898 if (unlikely(ssb_pci_assert_buspower(bus)))
899 return 0xFF;
900 if (unlikely(bus->mapped_device != dev)) {
901 if (unlikely(ssb_pci_switch_core(bus, dev)))
902 return 0xFF;
903 }
904 return ioread8(bus->mmio + offset);
905}
906
61e115a5
MB
907static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
908{
909 struct ssb_bus *bus = dev->bus;
910
911 if (unlikely(ssb_pci_assert_buspower(bus)))
912 return 0xFFFF;
913 if (unlikely(bus->mapped_device != dev)) {
914 if (unlikely(ssb_pci_switch_core(bus, dev)))
915 return 0xFFFF;
916 }
4b402c65 917 return ioread16(bus->mmio + offset);
61e115a5
MB
918}
919
920static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
921{
922 struct ssb_bus *bus = dev->bus;
923
924 if (unlikely(ssb_pci_assert_buspower(bus)))
925 return 0xFFFFFFFF;
926 if (unlikely(bus->mapped_device != dev)) {
927 if (unlikely(ssb_pci_switch_core(bus, dev)))
928 return 0xFFFFFFFF;
929 }
4b402c65 930 return ioread32(bus->mmio + offset);
61e115a5
MB
931}
932
d625a29b
MB
933#ifdef CONFIG_SSB_BLOCKIO
934static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
935 size_t count, u16 offset, u8 reg_width)
936{
937 struct ssb_bus *bus = dev->bus;
938 void __iomem *addr = bus->mmio + offset;
939
940 if (unlikely(ssb_pci_assert_buspower(bus)))
941 goto error;
942 if (unlikely(bus->mapped_device != dev)) {
943 if (unlikely(ssb_pci_switch_core(bus, dev)))
944 goto error;
945 }
946 switch (reg_width) {
947 case sizeof(u8):
948 ioread8_rep(addr, buffer, count);
949 break;
950 case sizeof(u16):
951 SSB_WARN_ON(count & 1);
952 ioread16_rep(addr, buffer, count >> 1);
953 break;
954 case sizeof(u32):
955 SSB_WARN_ON(count & 3);
956 ioread32_rep(addr, buffer, count >> 2);
957 break;
958 default:
959 SSB_WARN_ON(1);
960 }
961
962 return;
963error:
964 memset(buffer, 0xFF, count);
965}
966#endif /* CONFIG_SSB_BLOCKIO */
967
ffc7689d
MB
968static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
969{
970 struct ssb_bus *bus = dev->bus;
971
972 if (unlikely(ssb_pci_assert_buspower(bus)))
973 return;
974 if (unlikely(bus->mapped_device != dev)) {
975 if (unlikely(ssb_pci_switch_core(bus, dev)))
976 return;
977 }
978 iowrite8(value, bus->mmio + offset);
979}
980
61e115a5
MB
981static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
982{
983 struct ssb_bus *bus = dev->bus;
984
985 if (unlikely(ssb_pci_assert_buspower(bus)))
986 return;
987 if (unlikely(bus->mapped_device != dev)) {
988 if (unlikely(ssb_pci_switch_core(bus, dev)))
989 return;
990 }
4b402c65 991 iowrite16(value, bus->mmio + offset);
61e115a5
MB
992}
993
994static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
995{
996 struct ssb_bus *bus = dev->bus;
997
998 if (unlikely(ssb_pci_assert_buspower(bus)))
999 return;
1000 if (unlikely(bus->mapped_device != dev)) {
1001 if (unlikely(ssb_pci_switch_core(bus, dev)))
1002 return;
1003 }
4b402c65 1004 iowrite32(value, bus->mmio + offset);
61e115a5
MB
1005}
1006
d625a29b
MB
1007#ifdef CONFIG_SSB_BLOCKIO
1008static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1009 size_t count, u16 offset, u8 reg_width)
1010{
1011 struct ssb_bus *bus = dev->bus;
1012 void __iomem *addr = bus->mmio + offset;
1013
1014 if (unlikely(ssb_pci_assert_buspower(bus)))
1015 return;
1016 if (unlikely(bus->mapped_device != dev)) {
1017 if (unlikely(ssb_pci_switch_core(bus, dev)))
1018 return;
1019 }
1020 switch (reg_width) {
1021 case sizeof(u8):
1022 iowrite8_rep(addr, buffer, count);
1023 break;
1024 case sizeof(u16):
1025 SSB_WARN_ON(count & 1);
1026 iowrite16_rep(addr, buffer, count >> 1);
1027 break;
1028 case sizeof(u32):
1029 SSB_WARN_ON(count & 3);
1030 iowrite32_rep(addr, buffer, count >> 2);
1031 break;
1032 default:
1033 SSB_WARN_ON(1);
1034 }
1035}
1036#endif /* CONFIG_SSB_BLOCKIO */
1037
61e115a5
MB
1038/* Not "static", as it's used in main.c */
1039const struct ssb_bus_ops ssb_pci_ops = {
ffc7689d 1040 .read8 = ssb_pci_read8,
61e115a5
MB
1041 .read16 = ssb_pci_read16,
1042 .read32 = ssb_pci_read32,
ffc7689d 1043 .write8 = ssb_pci_write8,
61e115a5
MB
1044 .write16 = ssb_pci_write16,
1045 .write32 = ssb_pci_write32,
d625a29b
MB
1046#ifdef CONFIG_SSB_BLOCKIO
1047 .block_read = ssb_pci_block_read,
1048 .block_write = ssb_pci_block_write,
1049#endif
61e115a5
MB
1050};
1051
61e115a5
MB
1052static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
1053 struct device_attribute *attr,
1054 char *buf)
1055{
1056 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1057 struct ssb_bus *bus;
61e115a5
MB
1058
1059 bus = ssb_pci_dev_to_bus(pdev);
1060 if (!bus)
e7ec2e32 1061 return -ENODEV;
61e115a5 1062
e7ec2e32 1063 return ssb_attr_sprom_show(bus, buf, sprom_do_read);
61e115a5
MB
1064}
1065
1066static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
1067 struct device_attribute *attr,
1068 const char *buf, size_t count)
1069{
1070 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1071 struct ssb_bus *bus;
61e115a5
MB
1072
1073 bus = ssb_pci_dev_to_bus(pdev);
1074 if (!bus)
e7ec2e32 1075 return -ENODEV;
61e115a5 1076
e7ec2e32
MB
1077 return ssb_attr_sprom_store(bus, buf, count,
1078 sprom_check_crc, sprom_do_write);
61e115a5
MB
1079}
1080
1081static DEVICE_ATTR(ssb_sprom, 0600,
1082 ssb_pci_attr_sprom_show,
1083 ssb_pci_attr_sprom_store);
1084
1085void ssb_pci_exit(struct ssb_bus *bus)
1086{
1087 struct pci_dev *pdev;
1088
1089 if (bus->bustype != SSB_BUSTYPE_PCI)
1090 return;
1091
1092 pdev = bus->host_pci;
1093 device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1094}
1095
1096int ssb_pci_init(struct ssb_bus *bus)
1097{
1098 struct pci_dev *pdev;
1099 int err;
1100
1101 if (bus->bustype != SSB_BUSTYPE_PCI)
1102 return 0;
1103
1104 pdev = bus->host_pci;
e7ec2e32 1105 mutex_init(&bus->sprom_mutex);
61e115a5
MB
1106 err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1107 if (err)
1108 goto out;
1109
1110out:
1111 return err;
1112}
This page took 0.600533 seconds and 5 git commands to generate.