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