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