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