Merge tag 'for-linville-20140717' of git://github.com/kvalo/ath
[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 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         u16 il0mac_offset;
474
475         if (out->revision == 4)
476                 il0mac_offset = SSB_SPROM4_IL0MAC;
477         else
478                 il0mac_offset = SSB_SPROM5_IL0MAC;
479
480         sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
481
482         SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
483         SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
484              SSB_SPROM4_ETHPHY_ET1A_SHIFT);
485         SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
486         SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
487         if (out->revision == 4) {
488                 SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
489                 SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
490                 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
491                 SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
492                 SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
493                 SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
494         } else {
495                 SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
496                 SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
497                 SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
498                 SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
499                 SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
500                 SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
501         }
502         SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
503              SSB_SPROM4_ANTAVAIL_A_SHIFT);
504         SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
505              SSB_SPROM4_ANTAVAIL_BG_SHIFT);
506         SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
507         SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
508              SSB_SPROM4_ITSSI_BG_SHIFT);
509         SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
510         SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
511              SSB_SPROM4_ITSSI_A_SHIFT);
512         if (out->revision == 4) {
513                 SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
514                 SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
515                      SSB_SPROM4_GPIOA_P1_SHIFT);
516                 SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
517                 SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
518                      SSB_SPROM4_GPIOB_P3_SHIFT);
519         } else {
520                 SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
521                 SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
522                      SSB_SPROM5_GPIOA_P1_SHIFT);
523                 SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
524                 SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
525                      SSB_SPROM5_GPIOB_P3_SHIFT);
526         }
527
528         /* Extract the antenna gain values. */
529         out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
530                                                      SSB_SPROM4_AGAIN01,
531                                                      SSB_SPROM4_AGAIN0,
532                                                      SSB_SPROM4_AGAIN0_SHIFT);
533         out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
534                                                      SSB_SPROM4_AGAIN01,
535                                                      SSB_SPROM4_AGAIN1,
536                                                      SSB_SPROM4_AGAIN1_SHIFT);
537         out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
538                                                      SSB_SPROM4_AGAIN23,
539                                                      SSB_SPROM4_AGAIN2,
540                                                      SSB_SPROM4_AGAIN2_SHIFT);
541         out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
542                                                      SSB_SPROM4_AGAIN23,
543                                                      SSB_SPROM4_AGAIN3,
544                                                      SSB_SPROM4_AGAIN3_SHIFT);
545
546         sprom_extract_r458(out, in);
547
548         /* TODO - get remaining rev 4 stuff needed */
549 }
550
551 static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
552 {
553         int i;
554         u16 o;
555         u16 pwr_info_offset[] = {
556                 SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
557                 SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
558         };
559         BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
560                         ARRAY_SIZE(out->core_pwr_info));
561
562         /* extract the MAC address */
563         sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
564
565         SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
566         SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
567         SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
568         SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
569         SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
570         SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
571         SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
572         SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
573         SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
574              SSB_SPROM8_ANTAVAIL_A_SHIFT);
575         SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
576              SSB_SPROM8_ANTAVAIL_BG_SHIFT);
577         SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
578         SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
579              SSB_SPROM8_ITSSI_BG_SHIFT);
580         SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
581         SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
582              SSB_SPROM8_ITSSI_A_SHIFT);
583         SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
584         SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
585              SSB_SPROM8_MAXP_AL_SHIFT);
586         SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
587         SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
588              SSB_SPROM8_GPIOA_P1_SHIFT);
589         SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
590         SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
591              SSB_SPROM8_GPIOB_P3_SHIFT);
592         SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
593         SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
594              SSB_SPROM8_TRI5G_SHIFT);
595         SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
596         SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
597              SSB_SPROM8_TRI5GH_SHIFT);
598         SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
599         SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
600              SSB_SPROM8_RXPO5G_SHIFT);
601         SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
602         SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
603              SSB_SPROM8_RSSISMC2G_SHIFT);
604         SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
605              SSB_SPROM8_RSSISAV2G_SHIFT);
606         SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
607              SSB_SPROM8_BXA2G_SHIFT);
608         SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
609         SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
610              SSB_SPROM8_RSSISMC5G_SHIFT);
611         SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
612              SSB_SPROM8_RSSISAV5G_SHIFT);
613         SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
614              SSB_SPROM8_BXA5G_SHIFT);
615         SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
616         SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
617         SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
618         SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
619         SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
620         SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
621         SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
622         SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
623         SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
624         SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
625         SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
626         SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
627         SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
628         SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
629         SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
630         SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
631         SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
632
633         /* Extract the antenna gain values. */
634         out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
635                                                      SSB_SPROM8_AGAIN01,
636                                                      SSB_SPROM8_AGAIN0,
637                                                      SSB_SPROM8_AGAIN0_SHIFT);
638         out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
639                                                      SSB_SPROM8_AGAIN01,
640                                                      SSB_SPROM8_AGAIN1,
641                                                      SSB_SPROM8_AGAIN1_SHIFT);
642         out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
643                                                      SSB_SPROM8_AGAIN23,
644                                                      SSB_SPROM8_AGAIN2,
645                                                      SSB_SPROM8_AGAIN2_SHIFT);
646         out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
647                                                      SSB_SPROM8_AGAIN23,
648                                                      SSB_SPROM8_AGAIN3,
649                                                      SSB_SPROM8_AGAIN3_SHIFT);
650
651         /* Extract cores power info info */
652         for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
653                 o = pwr_info_offset[i];
654                 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
655                         SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
656                 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
657                         SSB_SPROM8_2G_MAXP, 0);
658
659                 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
660                 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
661                 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
662
663                 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
664                         SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
665                 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
666                         SSB_SPROM8_5G_MAXP, 0);
667                 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
668                         SSB_SPROM8_5GH_MAXP, 0);
669                 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
670                         SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
671
672                 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
673                 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
674                 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
675                 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
676                 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
677                 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
678                 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
679                 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
680                 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
681         }
682
683         /* Extract FEM info */
684         SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
685                 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
686         SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
687                 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
688         SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
689                 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
690         SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
691                 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
692         SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
693                 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
694
695         SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
696                 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
697         SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
698                 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
699         SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
700                 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
701         SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
702                 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
703         SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
704                 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
705
706         SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
707              SSB_SPROM8_LEDDC_ON_SHIFT);
708         SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
709              SSB_SPROM8_LEDDC_OFF_SHIFT);
710
711         SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
712              SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
713         SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
714              SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
715         SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
716              SSB_SPROM8_TXRXC_SWITCH_SHIFT);
717
718         SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
719
720         SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
721         SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
722         SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
723         SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
724
725         SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
726              SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
727         SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
728              SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
729         SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
730              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
731              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
732         SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
733              SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
734         SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
735              SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
736              SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
737         SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
738              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
739              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
740         SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
741              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
742              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
743         SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
744              SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
745
746         SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
747         SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
748         SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
749         SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
750
751         SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
752              SSB_SPROM8_THERMAL_TRESH_SHIFT);
753         SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
754              SSB_SPROM8_THERMAL_OFFSET_SHIFT);
755         SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
756              SSB_SPROM8_TEMPDELTA_PHYCAL,
757              SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
758         SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
759              SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
760         SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
761              SSB_SPROM8_TEMPDELTA_HYSTERESIS,
762              SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
763         sprom_extract_r458(out, in);
764
765         /* TODO - get remaining rev 8 stuff needed */
766 }
767
768 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
769                          const u16 *in, u16 size)
770 {
771         memset(out, 0, sizeof(*out));
772
773         out->revision = in[size - 1] & 0x00FF;
774         ssb_dbg("SPROM revision %d detected\n", out->revision);
775         memset(out->et0mac, 0xFF, 6);           /* preset et0 and et1 mac */
776         memset(out->et1mac, 0xFF, 6);
777
778         if ((bus->chip_id & 0xFF00) == 0x4400) {
779                 /* Workaround: The BCM44XX chip has a stupid revision
780                  * number stored in the SPROM.
781                  * Always extract r1. */
782                 out->revision = 1;
783                 ssb_dbg("SPROM treated as revision %d\n", out->revision);
784         }
785
786         switch (out->revision) {
787         case 1:
788         case 2:
789         case 3:
790                 sprom_extract_r123(out, in);
791                 break;
792         case 4:
793         case 5:
794                 sprom_extract_r45(out, in);
795                 break;
796         case 8:
797                 sprom_extract_r8(out, in);
798                 break;
799         default:
800                 ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
801                          out->revision);
802                 out->revision = 1;
803                 sprom_extract_r123(out, in);
804         }
805
806         if (out->boardflags_lo == 0xFFFF)
807                 out->boardflags_lo = 0;  /* per specs */
808         if (out->boardflags_hi == 0xFFFF)
809                 out->boardflags_hi = 0;  /* per specs */
810
811         return 0;
812 }
813
814 static int ssb_pci_sprom_get(struct ssb_bus *bus,
815                              struct ssb_sprom *sprom)
816 {
817         int err;
818         u16 *buf;
819
820         if (!ssb_is_sprom_available(bus)) {
821                 ssb_err("No SPROM available!\n");
822                 return -ENODEV;
823         }
824         if (bus->chipco.dev) {  /* can be unavailable! */
825                 /*
826                  * get SPROM offset: SSB_SPROM_BASE1 except for
827                  * chipcommon rev >= 31 or chip ID is 0x4312 and
828                  * chipcommon status & 3 == 2
829                  */
830                 if (bus->chipco.dev->id.revision >= 31)
831                         bus->sprom_offset = SSB_SPROM_BASE31;
832                 else if (bus->chip_id == 0x4312 &&
833                          (bus->chipco.status & 0x03) == 2)
834                         bus->sprom_offset = SSB_SPROM_BASE31;
835                 else
836                         bus->sprom_offset = SSB_SPROM_BASE1;
837         } else {
838                 bus->sprom_offset = SSB_SPROM_BASE1;
839         }
840         ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset);
841
842         buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
843         if (!buf)
844                 return -ENOMEM;
845         bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
846         sprom_do_read(bus, buf);
847         err = sprom_check_crc(buf, bus->sprom_size);
848         if (err) {
849                 /* try for a 440 byte SPROM - revision 4 and higher */
850                 kfree(buf);
851                 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
852                               GFP_KERNEL);
853                 if (!buf)
854                         return -ENOMEM;
855                 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
856                 sprom_do_read(bus, buf);
857                 err = sprom_check_crc(buf, bus->sprom_size);
858                 if (err) {
859                         /* All CRC attempts failed.
860                          * Maybe there is no SPROM on the device?
861                          * Now we ask the arch code if there is some sprom
862                          * available for this device in some other storage */
863                         err = ssb_fill_sprom_with_fallback(bus, sprom);
864                         if (err) {
865                                 ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n",
866                                          err);
867                         } else {
868                                 ssb_dbg("Using SPROM revision %d provided by platform\n",
869                                         sprom->revision);
870                                 err = 0;
871                                 goto out_free;
872                         }
873                         ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
874                 }
875         }
876         err = sprom_extract(bus, sprom, buf, bus->sprom_size);
877
878 out_free:
879         kfree(buf);
880         return err;
881 }
882
883 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
884                                   struct ssb_boardinfo *bi)
885 {
886         bi->vendor = bus->host_pci->subsystem_vendor;
887         bi->type = bus->host_pci->subsystem_device;
888 }
889
890 int ssb_pci_get_invariants(struct ssb_bus *bus,
891                            struct ssb_init_invariants *iv)
892 {
893         int err;
894
895         err = ssb_pci_sprom_get(bus, &iv->sprom);
896         if (err)
897                 goto out;
898         ssb_pci_get_boardinfo(bus, &iv->boardinfo);
899
900 out:
901         return err;
902 }
903
904 #ifdef CONFIG_SSB_DEBUG
905 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
906 {
907         if (likely(bus->powered_up))
908                 return 0;
909
910         printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
911                "while accessing PCI MMIO space\n");
912         if (bus->power_warn_count <= 10) {
913                 bus->power_warn_count++;
914                 dump_stack();
915         }
916
917         return -ENODEV;
918 }
919 #else /* DEBUG */
920 static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
921 {
922         return 0;
923 }
924 #endif /* DEBUG */
925
926 static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
927 {
928         struct ssb_bus *bus = dev->bus;
929
930         if (unlikely(ssb_pci_assert_buspower(bus)))
931                 return 0xFF;
932         if (unlikely(bus->mapped_device != dev)) {
933                 if (unlikely(ssb_pci_switch_core(bus, dev)))
934                         return 0xFF;
935         }
936         return ioread8(bus->mmio + offset);
937 }
938
939 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
940 {
941         struct ssb_bus *bus = dev->bus;
942
943         if (unlikely(ssb_pci_assert_buspower(bus)))
944                 return 0xFFFF;
945         if (unlikely(bus->mapped_device != dev)) {
946                 if (unlikely(ssb_pci_switch_core(bus, dev)))
947                         return 0xFFFF;
948         }
949         return ioread16(bus->mmio + offset);
950 }
951
952 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
953 {
954         struct ssb_bus *bus = dev->bus;
955
956         if (unlikely(ssb_pci_assert_buspower(bus)))
957                 return 0xFFFFFFFF;
958         if (unlikely(bus->mapped_device != dev)) {
959                 if (unlikely(ssb_pci_switch_core(bus, dev)))
960                         return 0xFFFFFFFF;
961         }
962         return ioread32(bus->mmio + offset);
963 }
964
965 #ifdef CONFIG_SSB_BLOCKIO
966 static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
967                                size_t count, u16 offset, u8 reg_width)
968 {
969         struct ssb_bus *bus = dev->bus;
970         void __iomem *addr = bus->mmio + offset;
971
972         if (unlikely(ssb_pci_assert_buspower(bus)))
973                 goto error;
974         if (unlikely(bus->mapped_device != dev)) {
975                 if (unlikely(ssb_pci_switch_core(bus, dev)))
976                         goto error;
977         }
978         switch (reg_width) {
979         case sizeof(u8):
980                 ioread8_rep(addr, buffer, count);
981                 break;
982         case sizeof(u16):
983                 SSB_WARN_ON(count & 1);
984                 ioread16_rep(addr, buffer, count >> 1);
985                 break;
986         case sizeof(u32):
987                 SSB_WARN_ON(count & 3);
988                 ioread32_rep(addr, buffer, count >> 2);
989                 break;
990         default:
991                 SSB_WARN_ON(1);
992         }
993
994         return;
995 error:
996         memset(buffer, 0xFF, count);
997 }
998 #endif /* CONFIG_SSB_BLOCKIO */
999
1000 static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
1001 {
1002         struct ssb_bus *bus = dev->bus;
1003
1004         if (unlikely(ssb_pci_assert_buspower(bus)))
1005                 return;
1006         if (unlikely(bus->mapped_device != dev)) {
1007                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1008                         return;
1009         }
1010         iowrite8(value, bus->mmio + offset);
1011 }
1012
1013 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
1014 {
1015         struct ssb_bus *bus = dev->bus;
1016
1017         if (unlikely(ssb_pci_assert_buspower(bus)))
1018                 return;
1019         if (unlikely(bus->mapped_device != dev)) {
1020                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1021                         return;
1022         }
1023         iowrite16(value, bus->mmio + offset);
1024 }
1025
1026 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
1027 {
1028         struct ssb_bus *bus = dev->bus;
1029
1030         if (unlikely(ssb_pci_assert_buspower(bus)))
1031                 return;
1032         if (unlikely(bus->mapped_device != dev)) {
1033                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1034                         return;
1035         }
1036         iowrite32(value, bus->mmio + offset);
1037 }
1038
1039 #ifdef CONFIG_SSB_BLOCKIO
1040 static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1041                                 size_t count, u16 offset, u8 reg_width)
1042 {
1043         struct ssb_bus *bus = dev->bus;
1044         void __iomem *addr = bus->mmio + offset;
1045
1046         if (unlikely(ssb_pci_assert_buspower(bus)))
1047                 return;
1048         if (unlikely(bus->mapped_device != dev)) {
1049                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1050                         return;
1051         }
1052         switch (reg_width) {
1053         case sizeof(u8):
1054                 iowrite8_rep(addr, buffer, count);
1055                 break;
1056         case sizeof(u16):
1057                 SSB_WARN_ON(count & 1);
1058                 iowrite16_rep(addr, buffer, count >> 1);
1059                 break;
1060         case sizeof(u32):
1061                 SSB_WARN_ON(count & 3);
1062                 iowrite32_rep(addr, buffer, count >> 2);
1063                 break;
1064         default:
1065                 SSB_WARN_ON(1);
1066         }
1067 }
1068 #endif /* CONFIG_SSB_BLOCKIO */
1069
1070 /* Not "static", as it's used in main.c */
1071 const struct ssb_bus_ops ssb_pci_ops = {
1072         .read8          = ssb_pci_read8,
1073         .read16         = ssb_pci_read16,
1074         .read32         = ssb_pci_read32,
1075         .write8         = ssb_pci_write8,
1076         .write16        = ssb_pci_write16,
1077         .write32        = ssb_pci_write32,
1078 #ifdef CONFIG_SSB_BLOCKIO
1079         .block_read     = ssb_pci_block_read,
1080         .block_write    = ssb_pci_block_write,
1081 #endif
1082 };
1083
1084 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
1085                                        struct device_attribute *attr,
1086                                        char *buf)
1087 {
1088         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1089         struct ssb_bus *bus;
1090
1091         bus = ssb_pci_dev_to_bus(pdev);
1092         if (!bus)
1093                 return -ENODEV;
1094
1095         return ssb_attr_sprom_show(bus, buf, sprom_do_read);
1096 }
1097
1098 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
1099                                         struct device_attribute *attr,
1100                                         const char *buf, size_t count)
1101 {
1102         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1103         struct ssb_bus *bus;
1104
1105         bus = ssb_pci_dev_to_bus(pdev);
1106         if (!bus)
1107                 return -ENODEV;
1108
1109         return ssb_attr_sprom_store(bus, buf, count,
1110                                     sprom_check_crc, sprom_do_write);
1111 }
1112
1113 static DEVICE_ATTR(ssb_sprom, 0600,
1114                    ssb_pci_attr_sprom_show,
1115                    ssb_pci_attr_sprom_store);
1116
1117 void ssb_pci_exit(struct ssb_bus *bus)
1118 {
1119         struct pci_dev *pdev;
1120
1121         if (bus->bustype != SSB_BUSTYPE_PCI)
1122                 return;
1123
1124         pdev = bus->host_pci;
1125         device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1126 }
1127
1128 int ssb_pci_init(struct ssb_bus *bus)
1129 {
1130         struct pci_dev *pdev;
1131         int err;
1132
1133         if (bus->bustype != SSB_BUSTYPE_PCI)
1134                 return 0;
1135
1136         pdev = bus->host_pci;
1137         mutex_init(&bus->sprom_mutex);
1138         err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1139         if (err)
1140                 goto out;
1141
1142 out:
1143         return err;
1144 }