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