]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/ssb/pci.c
Merge remote-tracking branches 'spi/fix/ep93xx', 'spi/fix/rockchip', 'spi/fix/sunxi...
[karo-tx-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 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset,
330                                 u16 mask, u16 shift)
331 {
332         u16 v;
333         u8 gain;
334
335         v = in[SPOFF(offset)];
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_r23(struct ssb_sprom *out, const u16 *in)
351 {
352         SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
353         SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
354         SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
355         SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
356         SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
357         SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
358         SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
359         SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
360         SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
361         SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
362              SSB_SPROM2_MAXP_A_LO_SHIFT);
363 }
364
365 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
366 {
367         u16 loc[3];
368
369         if (out->revision == 3)                 /* rev 3 moved MAC */
370                 loc[0] = SSB_SPROM3_IL0MAC;
371         else {
372                 loc[0] = SSB_SPROM1_IL0MAC;
373                 loc[1] = SSB_SPROM1_ET0MAC;
374                 loc[2] = SSB_SPROM1_ET1MAC;
375         }
376         sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
377         if (out->revision < 3) {        /* only rev 1-2 have et0, et1 */
378                 sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
379                 sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
380         }
381         SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
382         SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
383              SSB_SPROM1_ETHPHY_ET1A_SHIFT);
384         SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
385         SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
386         SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
387         SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
388         if (out->revision == 1)
389                 SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
390                      SSB_SPROM1_BINF_CCODE_SHIFT);
391         SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
392              SSB_SPROM1_BINF_ANTA_SHIFT);
393         SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
394              SSB_SPROM1_BINF_ANTBG_SHIFT);
395         SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
396         SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
397         SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
398         SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
399         SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
400         SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
401         SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
402         SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
403              SSB_SPROM1_GPIOA_P1_SHIFT);
404         SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
405         SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
406              SSB_SPROM1_GPIOB_P3_SHIFT);
407         SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
408              SSB_SPROM1_MAXPWR_A_SHIFT);
409         SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
410         SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
411              SSB_SPROM1_ITSSI_A_SHIFT);
412         SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
413         SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
414
415         SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
416         SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
417
418         /* Extract the antenna gain values. */
419         out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
420                                                      SSB_SPROM1_AGAIN,
421                                                      SSB_SPROM1_AGAIN_BG,
422                                                      SSB_SPROM1_AGAIN_BG_SHIFT);
423         out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
424                                                      SSB_SPROM1_AGAIN,
425                                                      SSB_SPROM1_AGAIN_A,
426                                                      SSB_SPROM1_AGAIN_A_SHIFT);
427         if (out->revision >= 2)
428                 sprom_extract_r23(out, in);
429 }
430
431 /* Revs 4 5 and 8 have partially shared layout */
432 static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
433 {
434         SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
435              SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
436         SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
437              SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
438         SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
439              SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
440         SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
441              SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
442
443         SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
444              SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
445         SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
446              SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
447         SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
448              SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
449         SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
450              SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
451
452         SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
453              SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
454         SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
455              SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
456         SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
457              SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
458         SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
459              SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
460
461         SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
462              SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
463         SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
464              SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
465         SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
466              SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
467         SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
468              SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
469 }
470
471 static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
472 {
473         static const u16 pwr_info_offset[] = {
474                 SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1,
475                 SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3
476         };
477         u16 il0mac_offset;
478         int i;
479
480         BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
481                      ARRAY_SIZE(out->core_pwr_info));
482
483         if (out->revision == 4)
484                 il0mac_offset = SSB_SPROM4_IL0MAC;
485         else
486                 il0mac_offset = SSB_SPROM5_IL0MAC;
487
488         sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
489
490         SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
491         SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
492              SSB_SPROM4_ETHPHY_ET1A_SHIFT);
493         SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
494         SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
495         if (out->revision == 4) {
496                 SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
497                 SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
498                 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
499                 SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
500                 SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
501                 SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
502         } else {
503                 SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
504                 SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
505                 SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
506                 SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
507                 SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
508                 SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
509         }
510         SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
511              SSB_SPROM4_ANTAVAIL_A_SHIFT);
512         SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
513              SSB_SPROM4_ANTAVAIL_BG_SHIFT);
514         SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
515         SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
516              SSB_SPROM4_ITSSI_BG_SHIFT);
517         SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
518         SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
519              SSB_SPROM4_ITSSI_A_SHIFT);
520         if (out->revision == 4) {
521                 SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
522                 SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
523                      SSB_SPROM4_GPIOA_P1_SHIFT);
524                 SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
525                 SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
526                      SSB_SPROM4_GPIOB_P3_SHIFT);
527         } else {
528                 SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
529                 SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
530                      SSB_SPROM5_GPIOA_P1_SHIFT);
531                 SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
532                 SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
533                      SSB_SPROM5_GPIOB_P3_SHIFT);
534         }
535
536         /* Extract the antenna gain values. */
537         out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
538                                                      SSB_SPROM4_AGAIN01,
539                                                      SSB_SPROM4_AGAIN0,
540                                                      SSB_SPROM4_AGAIN0_SHIFT);
541         out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
542                                                      SSB_SPROM4_AGAIN01,
543                                                      SSB_SPROM4_AGAIN1,
544                                                      SSB_SPROM4_AGAIN1_SHIFT);
545         out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
546                                                      SSB_SPROM4_AGAIN23,
547                                                      SSB_SPROM4_AGAIN2,
548                                                      SSB_SPROM4_AGAIN2_SHIFT);
549         out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
550                                                      SSB_SPROM4_AGAIN23,
551                                                      SSB_SPROM4_AGAIN3,
552                                                      SSB_SPROM4_AGAIN3_SHIFT);
553
554         /* Extract cores power info info */
555         for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
556                 u16 o = pwr_info_offset[i];
557
558                 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
559                         SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT);
560                 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
561                         SSB_SPROM4_2G_MAXP, 0);
562
563                 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0);
564                 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0);
565                 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0);
566                 SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0);
567
568                 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
569                         SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT);
570                 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
571                         SSB_SPROM4_5G_MAXP, 0);
572                 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP,
573                         SSB_SPROM4_5GH_MAXP, 0);
574                 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP,
575                         SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT);
576
577                 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0);
578                 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0);
579                 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0);
580                 SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0);
581                 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0);
582                 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0);
583                 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0);
584                 SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0);
585                 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0);
586                 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0);
587                 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0);
588                 SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0);
589         }
590
591         sprom_extract_r458(out, in);
592
593         /* TODO - get remaining rev 4 stuff needed */
594 }
595
596 static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
597 {
598         int i;
599         u16 o;
600         u16 pwr_info_offset[] = {
601                 SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
602                 SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
603         };
604         BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
605                         ARRAY_SIZE(out->core_pwr_info));
606
607         /* extract the MAC address */
608         sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
609
610         SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
611         SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
612         SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
613         SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
614         SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
615         SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
616         SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
617         SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
618         SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
619              SSB_SPROM8_ANTAVAIL_A_SHIFT);
620         SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
621              SSB_SPROM8_ANTAVAIL_BG_SHIFT);
622         SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
623         SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
624              SSB_SPROM8_ITSSI_BG_SHIFT);
625         SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
626         SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
627              SSB_SPROM8_ITSSI_A_SHIFT);
628         SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
629         SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
630              SSB_SPROM8_MAXP_AL_SHIFT);
631         SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
632         SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
633              SSB_SPROM8_GPIOA_P1_SHIFT);
634         SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
635         SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
636              SSB_SPROM8_GPIOB_P3_SHIFT);
637         SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
638         SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
639              SSB_SPROM8_TRI5G_SHIFT);
640         SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
641         SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
642              SSB_SPROM8_TRI5GH_SHIFT);
643         SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
644         SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
645              SSB_SPROM8_RXPO5G_SHIFT);
646         SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
647         SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
648              SSB_SPROM8_RSSISMC2G_SHIFT);
649         SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
650              SSB_SPROM8_RSSISAV2G_SHIFT);
651         SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
652              SSB_SPROM8_BXA2G_SHIFT);
653         SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
654         SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
655              SSB_SPROM8_RSSISMC5G_SHIFT);
656         SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
657              SSB_SPROM8_RSSISAV5G_SHIFT);
658         SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
659              SSB_SPROM8_BXA5G_SHIFT);
660         SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
661         SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
662         SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
663         SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
664         SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
665         SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
666         SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
667         SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
668         SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
669         SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
670         SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
671         SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
672         SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
673         SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
674         SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
675         SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
676         SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
677
678         /* Extract the antenna gain values. */
679         out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
680                                                      SSB_SPROM8_AGAIN01,
681                                                      SSB_SPROM8_AGAIN0,
682                                                      SSB_SPROM8_AGAIN0_SHIFT);
683         out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
684                                                      SSB_SPROM8_AGAIN01,
685                                                      SSB_SPROM8_AGAIN1,
686                                                      SSB_SPROM8_AGAIN1_SHIFT);
687         out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
688                                                      SSB_SPROM8_AGAIN23,
689                                                      SSB_SPROM8_AGAIN2,
690                                                      SSB_SPROM8_AGAIN2_SHIFT);
691         out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
692                                                      SSB_SPROM8_AGAIN23,
693                                                      SSB_SPROM8_AGAIN3,
694                                                      SSB_SPROM8_AGAIN3_SHIFT);
695
696         /* Extract cores power info info */
697         for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
698                 o = pwr_info_offset[i];
699                 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
700                         SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
701                 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
702                         SSB_SPROM8_2G_MAXP, 0);
703
704                 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
705                 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
706                 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
707
708                 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
709                         SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
710                 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
711                         SSB_SPROM8_5G_MAXP, 0);
712                 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
713                         SSB_SPROM8_5GH_MAXP, 0);
714                 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
715                         SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
716
717                 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
718                 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
719                 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
720                 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
721                 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
722                 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
723                 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
724                 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
725                 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
726         }
727
728         /* Extract FEM info */
729         SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
730                 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
731         SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
732                 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
733         SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
734                 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
735         SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
736                 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
737         SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
738                 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
739
740         SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
741                 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
742         SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
743                 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
744         SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
745                 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
746         SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
747                 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
748         SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
749                 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
750
751         SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
752              SSB_SPROM8_LEDDC_ON_SHIFT);
753         SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
754              SSB_SPROM8_LEDDC_OFF_SHIFT);
755
756         SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
757              SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
758         SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
759              SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
760         SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
761              SSB_SPROM8_TXRXC_SWITCH_SHIFT);
762
763         SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
764
765         SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
766         SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
767         SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
768         SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
769
770         SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
771              SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
772         SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
773              SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
774         SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
775              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
776              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
777         SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
778              SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
779         SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
780              SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
781              SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
782         SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
783              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
784              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
785         SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
786              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
787              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
788         SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
789              SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
790
791         SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
792         SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
793         SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
794         SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
795
796         SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
797              SSB_SPROM8_THERMAL_TRESH_SHIFT);
798         SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
799              SSB_SPROM8_THERMAL_OFFSET_SHIFT);
800         SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
801              SSB_SPROM8_TEMPDELTA_PHYCAL,
802              SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
803         SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
804              SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
805         SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
806              SSB_SPROM8_TEMPDELTA_HYSTERESIS,
807              SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
808         sprom_extract_r458(out, in);
809
810         /* TODO - get remaining rev 8 stuff needed */
811 }
812
813 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
814                          const u16 *in, u16 size)
815 {
816         memset(out, 0, sizeof(*out));
817
818         out->revision = in[size - 1] & 0x00FF;
819         ssb_dbg("SPROM revision %d detected\n", out->revision);
820         memset(out->et0mac, 0xFF, 6);           /* preset et0 and et1 mac */
821         memset(out->et1mac, 0xFF, 6);
822
823         if ((bus->chip_id & 0xFF00) == 0x4400) {
824                 /* Workaround: The BCM44XX chip has a stupid revision
825                  * number stored in the SPROM.
826                  * Always extract r1. */
827                 out->revision = 1;
828                 ssb_dbg("SPROM treated as revision %d\n", out->revision);
829         }
830
831         switch (out->revision) {
832         case 1:
833         case 2:
834         case 3:
835                 sprom_extract_r123(out, in);
836                 break;
837         case 4:
838         case 5:
839                 sprom_extract_r45(out, in);
840                 break;
841         case 8:
842                 sprom_extract_r8(out, in);
843                 break;
844         default:
845                 ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
846                          out->revision);
847                 out->revision = 1;
848                 sprom_extract_r123(out, in);
849         }
850
851         if (out->boardflags_lo == 0xFFFF)
852                 out->boardflags_lo = 0;  /* per specs */
853         if (out->boardflags_hi == 0xFFFF)
854                 out->boardflags_hi = 0;  /* per specs */
855
856         return 0;
857 }
858
859 static int ssb_pci_sprom_get(struct ssb_bus *bus,
860                              struct ssb_sprom *sprom)
861 {
862         int err;
863         u16 *buf;
864
865         if (!ssb_is_sprom_available(bus)) {
866                 ssb_err("No SPROM available!\n");
867                 return -ENODEV;
868         }
869         if (bus->chipco.dev) {  /* can be unavailable! */
870                 /*
871                  * get SPROM offset: SSB_SPROM_BASE1 except for
872                  * chipcommon rev >= 31 or chip ID is 0x4312 and
873                  * chipcommon status & 3 == 2
874                  */
875                 if (bus->chipco.dev->id.revision >= 31)
876                         bus->sprom_offset = SSB_SPROM_BASE31;
877                 else if (bus->chip_id == 0x4312 &&
878                          (bus->chipco.status & 0x03) == 2)
879                         bus->sprom_offset = SSB_SPROM_BASE31;
880                 else
881                         bus->sprom_offset = SSB_SPROM_BASE1;
882         } else {
883                 bus->sprom_offset = SSB_SPROM_BASE1;
884         }
885         ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset);
886
887         buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
888         if (!buf)
889                 return -ENOMEM;
890         bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
891         sprom_do_read(bus, buf);
892         err = sprom_check_crc(buf, bus->sprom_size);
893         if (err) {
894                 /* try for a 440 byte SPROM - revision 4 and higher */
895                 kfree(buf);
896                 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
897                               GFP_KERNEL);
898                 if (!buf)
899                         return -ENOMEM;
900                 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
901                 sprom_do_read(bus, buf);
902                 err = sprom_check_crc(buf, bus->sprom_size);
903                 if (err) {
904                         /* All CRC attempts failed.
905                          * Maybe there is no SPROM on the device?
906                          * Now we ask the arch code if there is some sprom
907                          * available for this device in some other storage */
908                         err = ssb_fill_sprom_with_fallback(bus, sprom);
909                         if (err) {
910                                 ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n",
911                                          err);
912                         } else {
913                                 ssb_dbg("Using SPROM revision %d provided by platform\n",
914                                         sprom->revision);
915                                 err = 0;
916                                 goto out_free;
917                         }
918                         ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
919                 }
920         }
921         err = sprom_extract(bus, sprom, buf, bus->sprom_size);
922
923 out_free:
924         kfree(buf);
925         return err;
926 }
927
928 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
929                                   struct ssb_boardinfo *bi)
930 {
931         bi->vendor = bus->host_pci->subsystem_vendor;
932         bi->type = bus->host_pci->subsystem_device;
933 }
934
935 int ssb_pci_get_invariants(struct ssb_bus *bus,
936                            struct ssb_init_invariants *iv)
937 {
938         int err;
939
940         err = ssb_pci_sprom_get(bus, &iv->sprom);
941         if (err)
942                 goto out;
943         ssb_pci_get_boardinfo(bus, &iv->boardinfo);
944
945 out:
946         return err;
947 }
948
949 #ifdef CONFIG_SSB_DEBUG
950 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
951 {
952         if (likely(bus->powered_up))
953                 return 0;
954
955         printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
956                "while accessing PCI MMIO space\n");
957         if (bus->power_warn_count <= 10) {
958                 bus->power_warn_count++;
959                 dump_stack();
960         }
961
962         return -ENODEV;
963 }
964 #else /* DEBUG */
965 static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
966 {
967         return 0;
968 }
969 #endif /* DEBUG */
970
971 static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
972 {
973         struct ssb_bus *bus = dev->bus;
974
975         if (unlikely(ssb_pci_assert_buspower(bus)))
976                 return 0xFF;
977         if (unlikely(bus->mapped_device != dev)) {
978                 if (unlikely(ssb_pci_switch_core(bus, dev)))
979                         return 0xFF;
980         }
981         return ioread8(bus->mmio + offset);
982 }
983
984 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
985 {
986         struct ssb_bus *bus = dev->bus;
987
988         if (unlikely(ssb_pci_assert_buspower(bus)))
989                 return 0xFFFF;
990         if (unlikely(bus->mapped_device != dev)) {
991                 if (unlikely(ssb_pci_switch_core(bus, dev)))
992                         return 0xFFFF;
993         }
994         return ioread16(bus->mmio + offset);
995 }
996
997 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
998 {
999         struct ssb_bus *bus = dev->bus;
1000
1001         if (unlikely(ssb_pci_assert_buspower(bus)))
1002                 return 0xFFFFFFFF;
1003         if (unlikely(bus->mapped_device != dev)) {
1004                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1005                         return 0xFFFFFFFF;
1006         }
1007         return ioread32(bus->mmio + offset);
1008 }
1009
1010 #ifdef CONFIG_SSB_BLOCKIO
1011 static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
1012                                size_t count, u16 offset, u8 reg_width)
1013 {
1014         struct ssb_bus *bus = dev->bus;
1015         void __iomem *addr = bus->mmio + offset;
1016
1017         if (unlikely(ssb_pci_assert_buspower(bus)))
1018                 goto error;
1019         if (unlikely(bus->mapped_device != dev)) {
1020                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1021                         goto error;
1022         }
1023         switch (reg_width) {
1024         case sizeof(u8):
1025                 ioread8_rep(addr, buffer, count);
1026                 break;
1027         case sizeof(u16):
1028                 SSB_WARN_ON(count & 1);
1029                 ioread16_rep(addr, buffer, count >> 1);
1030                 break;
1031         case sizeof(u32):
1032                 SSB_WARN_ON(count & 3);
1033                 ioread32_rep(addr, buffer, count >> 2);
1034                 break;
1035         default:
1036                 SSB_WARN_ON(1);
1037         }
1038
1039         return;
1040 error:
1041         memset(buffer, 0xFF, count);
1042 }
1043 #endif /* CONFIG_SSB_BLOCKIO */
1044
1045 static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
1046 {
1047         struct ssb_bus *bus = dev->bus;
1048
1049         if (unlikely(ssb_pci_assert_buspower(bus)))
1050                 return;
1051         if (unlikely(bus->mapped_device != dev)) {
1052                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1053                         return;
1054         }
1055         iowrite8(value, bus->mmio + offset);
1056 }
1057
1058 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
1059 {
1060         struct ssb_bus *bus = dev->bus;
1061
1062         if (unlikely(ssb_pci_assert_buspower(bus)))
1063                 return;
1064         if (unlikely(bus->mapped_device != dev)) {
1065                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1066                         return;
1067         }
1068         iowrite16(value, bus->mmio + offset);
1069 }
1070
1071 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
1072 {
1073         struct ssb_bus *bus = dev->bus;
1074
1075         if (unlikely(ssb_pci_assert_buspower(bus)))
1076                 return;
1077         if (unlikely(bus->mapped_device != dev)) {
1078                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1079                         return;
1080         }
1081         iowrite32(value, bus->mmio + offset);
1082 }
1083
1084 #ifdef CONFIG_SSB_BLOCKIO
1085 static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1086                                 size_t count, u16 offset, u8 reg_width)
1087 {
1088         struct ssb_bus *bus = dev->bus;
1089         void __iomem *addr = bus->mmio + offset;
1090
1091         if (unlikely(ssb_pci_assert_buspower(bus)))
1092                 return;
1093         if (unlikely(bus->mapped_device != dev)) {
1094                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1095                         return;
1096         }
1097         switch (reg_width) {
1098         case sizeof(u8):
1099                 iowrite8_rep(addr, buffer, count);
1100                 break;
1101         case sizeof(u16):
1102                 SSB_WARN_ON(count & 1);
1103                 iowrite16_rep(addr, buffer, count >> 1);
1104                 break;
1105         case sizeof(u32):
1106                 SSB_WARN_ON(count & 3);
1107                 iowrite32_rep(addr, buffer, count >> 2);
1108                 break;
1109         default:
1110                 SSB_WARN_ON(1);
1111         }
1112 }
1113 #endif /* CONFIG_SSB_BLOCKIO */
1114
1115 /* Not "static", as it's used in main.c */
1116 const struct ssb_bus_ops ssb_pci_ops = {
1117         .read8          = ssb_pci_read8,
1118         .read16         = ssb_pci_read16,
1119         .read32         = ssb_pci_read32,
1120         .write8         = ssb_pci_write8,
1121         .write16        = ssb_pci_write16,
1122         .write32        = ssb_pci_write32,
1123 #ifdef CONFIG_SSB_BLOCKIO
1124         .block_read     = ssb_pci_block_read,
1125         .block_write    = ssb_pci_block_write,
1126 #endif
1127 };
1128
1129 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
1130                                        struct device_attribute *attr,
1131                                        char *buf)
1132 {
1133         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1134         struct ssb_bus *bus;
1135
1136         bus = ssb_pci_dev_to_bus(pdev);
1137         if (!bus)
1138                 return -ENODEV;
1139
1140         return ssb_attr_sprom_show(bus, buf, sprom_do_read);
1141 }
1142
1143 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
1144                                         struct device_attribute *attr,
1145                                         const char *buf, size_t count)
1146 {
1147         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1148         struct ssb_bus *bus;
1149
1150         bus = ssb_pci_dev_to_bus(pdev);
1151         if (!bus)
1152                 return -ENODEV;
1153
1154         return ssb_attr_sprom_store(bus, buf, count,
1155                                     sprom_check_crc, sprom_do_write);
1156 }
1157
1158 static DEVICE_ATTR(ssb_sprom, 0600,
1159                    ssb_pci_attr_sprom_show,
1160                    ssb_pci_attr_sprom_store);
1161
1162 void ssb_pci_exit(struct ssb_bus *bus)
1163 {
1164         struct pci_dev *pdev;
1165
1166         if (bus->bustype != SSB_BUSTYPE_PCI)
1167                 return;
1168
1169         pdev = bus->host_pci;
1170         device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1171 }
1172
1173 int ssb_pci_init(struct ssb_bus *bus)
1174 {
1175         struct pci_dev *pdev;
1176         int err;
1177
1178         if (bus->bustype != SSB_BUSTYPE_PCI)
1179                 return 0;
1180
1181         pdev = bus->host_pci;
1182         mutex_init(&bus->sprom_mutex);
1183         err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1184         if (err)
1185                 goto out;
1186
1187 out:
1188         return err;
1189 }