]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/ssb/pci.c
TTY: mn10300-serial, fix build breakage
[karo-tx-linux.git] / drivers / ssb / pci.c
1 /*
2  * Sonics Silicon Backplane PCI-Hostbus related functions.
3  *
4  * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
5  * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
6  * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
7  * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
8  * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
9  *
10  * Derived from the Broadcom 4400 device driver.
11  * Copyright (C) 2002 David S. Miller (davem@redhat.com)
12  * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
13  * Copyright (C) 2006 Broadcom Corporation.
14  *
15  * Licensed under the GNU/GPL. See COPYING for details.
16  */
17
18 #include <linux/ssb/ssb.h>
19 #include <linux/ssb/ssb_regs.h>
20 #include <linux/slab.h>
21 #include <linux/pci.h>
22 #include <linux/delay.h>
23
24 #include "ssb_private.h"
25
26
27 /* Define the following to 1 to enable a printk on each coreswitch. */
28 #define SSB_VERBOSE_PCICORESWITCH_DEBUG         0
29
30
31 /* Lowlevel coreswitching */
32 int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
33 {
34         int err;
35         int attempts = 0;
36         u32 cur_core;
37
38         while (1) {
39                 err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
40                                              (coreidx * SSB_CORE_SIZE)
41                                              + SSB_ENUM_BASE);
42                 if (err)
43                         goto error;
44                 err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
45                                             &cur_core);
46                 if (err)
47                         goto error;
48                 cur_core = (cur_core - SSB_ENUM_BASE)
49                            / SSB_CORE_SIZE;
50                 if (cur_core == coreidx)
51                         break;
52
53                 if (attempts++ > SSB_BAR0_MAX_RETRIES)
54                         goto error;
55                 udelay(10);
56         }
57         return 0;
58 error:
59         ssb_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 u8 ssb_sprom_crc(const u16 *sprom, u16 size)
235 {
236         int word;
237         u8 crc = 0xFF;
238
239         for (word = 0; word < size - 1; word++) {
240                 crc = ssb_crc8(crc, sprom[word] & 0x00FF);
241                 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
242         }
243         crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
244         crc ^= 0xFF;
245
246         return crc;
247 }
248
249 static int sprom_check_crc(const u16 *sprom, size_t size)
250 {
251         u8 crc;
252         u8 expected_crc;
253         u16 tmp;
254
255         crc = ssb_sprom_crc(sprom, size);
256         tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
257         expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
258         if (crc != expected_crc)
259                 return -EPROTO;
260
261         return 0;
262 }
263
264 static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
265 {
266         int i;
267
268         for (i = 0; i < bus->sprom_size; i++)
269                 sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
270
271         return 0;
272 }
273
274 static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
275 {
276         struct pci_dev *pdev = bus->host_pci;
277         int i, err;
278         u32 spromctl;
279         u16 size = bus->sprom_size;
280
281         ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
282         err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
283         if (err)
284                 goto err_ctlreg;
285         spromctl |= SSB_SPROMCTL_WE;
286         err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
287         if (err)
288                 goto err_ctlreg;
289         ssb_printk(KERN_NOTICE PFX "[ 0%%");
290         msleep(500);
291         for (i = 0; i < size; i++) {
292                 if (i == size / 4)
293                         ssb_printk("25%%");
294                 else if (i == size / 2)
295                         ssb_printk("50%%");
296                 else if (i == (size * 3) / 4)
297                         ssb_printk("75%%");
298                 else if (i % 2)
299                         ssb_printk(".");
300                 writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
301                 mmiowb();
302                 msleep(20);
303         }
304         err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
305         if (err)
306                 goto err_ctlreg;
307         spromctl &= ~SSB_SPROMCTL_WE;
308         err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
309         if (err)
310                 goto err_ctlreg;
311         msleep(500);
312         ssb_printk("100%% ]\n");
313         ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
314
315         return 0;
316 err_ctlreg:
317         ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
318         return err;
319 }
320
321 static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
322                                u16 mask, u16 shift)
323 {
324         u16 v;
325         u8 gain;
326
327         v = in[SPOFF(SSB_SPROM1_AGAIN)];
328         gain = (v & mask) >> shift;
329         if (gain == 0xFF)
330                 gain = 2; /* If unset use 2dBm */
331         if (sprom_revision == 1) {
332                 /* Convert to Q5.2 */
333                 gain <<= 2;
334         } else {
335                 /* Q5.2 Fractional part is stored in 0xC0 */
336                 gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
337         }
338
339         return (s8)gain;
340 }
341
342 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
343 {
344         int i;
345         u16 v;
346         u16 loc[3];
347
348         if (out->revision == 3)                 /* rev 3 moved MAC */
349                 loc[0] = SSB_SPROM3_IL0MAC;
350         else {
351                 loc[0] = SSB_SPROM1_IL0MAC;
352                 loc[1] = SSB_SPROM1_ET0MAC;
353                 loc[2] = SSB_SPROM1_ET1MAC;
354         }
355         for (i = 0; i < 3; i++) {
356                 v = in[SPOFF(loc[0]) + i];
357                 *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
358         }
359         if (out->revision < 3) {        /* only rev 1-2 have et0, et1 */
360                 for (i = 0; i < 3; i++) {
361                         v = in[SPOFF(loc[1]) + i];
362                         *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
363                 }
364                 for (i = 0; i < 3; i++) {
365                         v = in[SPOFF(loc[2]) + i];
366                         *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
367                 }
368         }
369         SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
370         SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
371              SSB_SPROM1_ETHPHY_ET1A_SHIFT);
372         SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
373         SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
374         SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
375         if (out->revision == 1)
376                 SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
377                      SSB_SPROM1_BINF_CCODE_SHIFT);
378         SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
379              SSB_SPROM1_BINF_ANTA_SHIFT);
380         SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
381              SSB_SPROM1_BINF_ANTBG_SHIFT);
382         SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
383         SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
384         SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
385         SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
386         SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
387         SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
388         SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
389         SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
390              SSB_SPROM1_GPIOA_P1_SHIFT);
391         SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
392         SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
393              SSB_SPROM1_GPIOB_P3_SHIFT);
394         SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
395              SSB_SPROM1_MAXPWR_A_SHIFT);
396         SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
397         SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
398              SSB_SPROM1_ITSSI_A_SHIFT);
399         SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
400         SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
401         if (out->revision >= 2)
402                 SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
403         SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
404         SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
405
406         /* Extract the antenna gain values. */
407         out->antenna_gain.a0 = r123_extract_antgain(out->revision, in,
408                                                     SSB_SPROM1_AGAIN_BG,
409                                                     SSB_SPROM1_AGAIN_BG_SHIFT);
410         out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
411                                                     SSB_SPROM1_AGAIN_A,
412                                                     SSB_SPROM1_AGAIN_A_SHIFT);
413 }
414
415 /* Revs 4 5 and 8 have partially shared layout */
416 static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
417 {
418         SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
419              SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
420         SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
421              SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
422         SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
423              SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
424         SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
425              SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
426
427         SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
428              SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
429         SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
430              SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
431         SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
432              SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
433         SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
434              SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
435
436         SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
437              SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
438         SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
439              SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
440         SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
441              SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
442         SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
443              SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
444
445         SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
446              SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
447         SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
448              SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
449         SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
450              SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
451         SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
452              SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
453 }
454
455 static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
456 {
457         int i;
458         u16 v;
459         u16 il0mac_offset;
460
461         if (out->revision == 4)
462                 il0mac_offset = SSB_SPROM4_IL0MAC;
463         else
464                 il0mac_offset = SSB_SPROM5_IL0MAC;
465         /* extract the MAC address */
466         for (i = 0; i < 3; i++) {
467                 v = in[SPOFF(il0mac_offset) + i];
468                 *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
469         }
470         SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
471         SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
472              SSB_SPROM4_ETHPHY_ET1A_SHIFT);
473         SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
474         if (out->revision == 4) {
475                 SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
476                 SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
477                 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
478                 SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
479                 SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
480                 SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
481         } else {
482                 SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
483                 SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
484                 SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
485                 SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
486                 SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
487                 SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
488         }
489         SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
490              SSB_SPROM4_ANTAVAIL_A_SHIFT);
491         SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
492              SSB_SPROM4_ANTAVAIL_BG_SHIFT);
493         SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
494         SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
495              SSB_SPROM4_ITSSI_BG_SHIFT);
496         SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
497         SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
498              SSB_SPROM4_ITSSI_A_SHIFT);
499         if (out->revision == 4) {
500                 SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
501                 SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
502                      SSB_SPROM4_GPIOA_P1_SHIFT);
503                 SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
504                 SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
505                      SSB_SPROM4_GPIOB_P3_SHIFT);
506         } else {
507                 SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
508                 SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
509                      SSB_SPROM5_GPIOA_P1_SHIFT);
510                 SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
511                 SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
512                      SSB_SPROM5_GPIOB_P3_SHIFT);
513         }
514
515         /* Extract the antenna gain values. */
516         SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
517              SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
518         SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
519              SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
520         SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
521              SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
522         SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
523              SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
524
525         sprom_extract_r458(out, in);
526
527         /* TODO - get remaining rev 4 stuff needed */
528 }
529
530 static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
531 {
532         int i;
533         u16 v, o;
534         u16 pwr_info_offset[] = {
535                 SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
536                 SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
537         };
538         BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
539                         ARRAY_SIZE(out->core_pwr_info));
540
541         /* extract the MAC address */
542         for (i = 0; i < 3; i++) {
543                 v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
544                 *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
545         }
546         SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
547         SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
548         SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
549         SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
550         SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
551         SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
552         SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
553         SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
554              SSB_SPROM8_ANTAVAIL_A_SHIFT);
555         SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
556              SSB_SPROM8_ANTAVAIL_BG_SHIFT);
557         SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
558         SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
559              SSB_SPROM8_ITSSI_BG_SHIFT);
560         SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
561         SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
562              SSB_SPROM8_ITSSI_A_SHIFT);
563         SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
564         SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
565              SSB_SPROM8_MAXP_AL_SHIFT);
566         SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
567         SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
568              SSB_SPROM8_GPIOA_P1_SHIFT);
569         SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
570         SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
571              SSB_SPROM8_GPIOB_P3_SHIFT);
572         SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
573         SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
574              SSB_SPROM8_TRI5G_SHIFT);
575         SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
576         SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
577              SSB_SPROM8_TRI5GH_SHIFT);
578         SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
579         SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
580              SSB_SPROM8_RXPO5G_SHIFT);
581         SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
582         SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
583              SSB_SPROM8_RSSISMC2G_SHIFT);
584         SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
585              SSB_SPROM8_RSSISAV2G_SHIFT);
586         SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
587              SSB_SPROM8_BXA2G_SHIFT);
588         SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
589         SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
590              SSB_SPROM8_RSSISMC5G_SHIFT);
591         SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
592              SSB_SPROM8_RSSISAV5G_SHIFT);
593         SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
594              SSB_SPROM8_BXA5G_SHIFT);
595         SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
596         SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
597         SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
598         SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
599         SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
600         SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
601         SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
602         SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
603         SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
604         SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
605         SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
606         SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
607         SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
608         SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
609         SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
610         SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
611         SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
612
613         /* Extract the antenna gain values. */
614         SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
615              SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
616         SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
617              SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
618         SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
619              SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
620         SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
621              SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
622
623         /* Extract cores power info info */
624         for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
625                 o = pwr_info_offset[i];
626                 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
627                         SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
628                 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
629                         SSB_SPROM8_2G_MAXP, 0);
630
631                 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
632                 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
633                 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
634
635                 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
636                         SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
637                 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
638                         SSB_SPROM8_5G_MAXP, 0);
639                 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
640                         SSB_SPROM8_5GH_MAXP, 0);
641                 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
642                         SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
643
644                 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
645                 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
646                 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
647                 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
648                 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
649                 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
650                 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
651                 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
652                 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
653         }
654
655         /* Extract FEM info */
656         SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
657                 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
658         SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
659                 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
660         SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
661                 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
662         SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
663                 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
664         SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
665                 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
666
667         SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
668                 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
669         SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
670                 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
671         SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
672                 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
673         SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
674                 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
675         SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
676                 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
677
678         SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
679              SSB_SPROM8_LEDDC_ON_SHIFT);
680         SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
681              SSB_SPROM8_LEDDC_OFF_SHIFT);
682
683         SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
684              SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
685         SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
686              SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
687         SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
688              SSB_SPROM8_TXRXC_SWITCH_SHIFT);
689
690         SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
691
692         SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
693         SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
694         SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
695         SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
696
697         SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
698              SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
699         SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
700              SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
701         SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
702              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
703              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
704         SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
705              SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
706         SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
707              SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
708              SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
709         SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
710              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
711              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
712         SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
713              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
714              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
715         SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
716              SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
717
718         SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
719         SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
720         SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
721         SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
722
723         SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
724              SSB_SPROM8_THERMAL_TRESH_SHIFT);
725         SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
726              SSB_SPROM8_THERMAL_OFFSET_SHIFT);
727         SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
728              SSB_SPROM8_TEMPDELTA_PHYCAL,
729              SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
730         SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
731              SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
732         SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
733              SSB_SPROM8_TEMPDELTA_HYSTERESIS,
734              SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
735         sprom_extract_r458(out, in);
736
737         /* TODO - get remaining rev 8 stuff needed */
738 }
739
740 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
741                          const u16 *in, u16 size)
742 {
743         memset(out, 0, sizeof(*out));
744
745         out->revision = in[size - 1] & 0x00FF;
746         ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
747         memset(out->et0mac, 0xFF, 6);           /* preset et0 and et1 mac */
748         memset(out->et1mac, 0xFF, 6);
749
750         if ((bus->chip_id & 0xFF00) == 0x4400) {
751                 /* Workaround: The BCM44XX chip has a stupid revision
752                  * number stored in the SPROM.
753                  * Always extract r1. */
754                 out->revision = 1;
755                 ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
756         }
757
758         switch (out->revision) {
759         case 1:
760         case 2:
761         case 3:
762                 sprom_extract_r123(out, in);
763                 break;
764         case 4:
765         case 5:
766                 sprom_extract_r45(out, in);
767                 break;
768         case 8:
769                 sprom_extract_r8(out, in);
770                 break;
771         default:
772                 ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
773                            " revision %d detected. Will extract"
774                            " v1\n", out->revision);
775                 out->revision = 1;
776                 sprom_extract_r123(out, in);
777         }
778
779         if (out->boardflags_lo == 0xFFFF)
780                 out->boardflags_lo = 0;  /* per specs */
781         if (out->boardflags_hi == 0xFFFF)
782                 out->boardflags_hi = 0;  /* per specs */
783
784         return 0;
785 }
786
787 static int ssb_pci_sprom_get(struct ssb_bus *bus,
788                              struct ssb_sprom *sprom)
789 {
790         int err;
791         u16 *buf;
792
793         if (!ssb_is_sprom_available(bus)) {
794                 ssb_printk(KERN_ERR PFX "No SPROM available!\n");
795                 return -ENODEV;
796         }
797         if (bus->chipco.dev) {  /* can be unavailable! */
798                 /*
799                  * get SPROM offset: SSB_SPROM_BASE1 except for
800                  * chipcommon rev >= 31 or chip ID is 0x4312 and
801                  * chipcommon status & 3 == 2
802                  */
803                 if (bus->chipco.dev->id.revision >= 31)
804                         bus->sprom_offset = SSB_SPROM_BASE31;
805                 else if (bus->chip_id == 0x4312 &&
806                          (bus->chipco.status & 0x03) == 2)
807                         bus->sprom_offset = SSB_SPROM_BASE31;
808                 else
809                         bus->sprom_offset = SSB_SPROM_BASE1;
810         } else {
811                 bus->sprom_offset = SSB_SPROM_BASE1;
812         }
813         ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
814
815         buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
816         if (!buf)
817                 return -ENOMEM;
818         bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
819         sprom_do_read(bus, buf);
820         err = sprom_check_crc(buf, bus->sprom_size);
821         if (err) {
822                 /* try for a 440 byte SPROM - revision 4 and higher */
823                 kfree(buf);
824                 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
825                               GFP_KERNEL);
826                 if (!buf)
827                         return -ENOMEM;
828                 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
829                 sprom_do_read(bus, buf);
830                 err = sprom_check_crc(buf, bus->sprom_size);
831                 if (err) {
832                         /* All CRC attempts failed.
833                          * Maybe there is no SPROM on the device?
834                          * Now we ask the arch code if there is some sprom
835                          * available for this device in some other storage */
836                         err = ssb_fill_sprom_with_fallback(bus, sprom);
837                         if (err) {
838                                 ssb_printk(KERN_WARNING PFX "WARNING: Using"
839                                            " fallback SPROM failed (err %d)\n",
840                                            err);
841                         } else {
842                                 ssb_dprintk(KERN_DEBUG PFX "Using SPROM"
843                                             " revision %d provided by"
844                                             " platform.\n", sprom->revision);
845                                 err = 0;
846                                 goto out_free;
847                         }
848                         ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
849                                    " SPROM CRC (corrupt SPROM)\n");
850                 }
851         }
852         err = sprom_extract(bus, sprom, buf, bus->sprom_size);
853
854 out_free:
855         kfree(buf);
856         return err;
857 }
858
859 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
860                                   struct ssb_boardinfo *bi)
861 {
862         bi->vendor = bus->host_pci->subsystem_vendor;
863         bi->type = bus->host_pci->subsystem_device;
864 }
865
866 int ssb_pci_get_invariants(struct ssb_bus *bus,
867                            struct ssb_init_invariants *iv)
868 {
869         int err;
870
871         err = ssb_pci_sprom_get(bus, &iv->sprom);
872         if (err)
873                 goto out;
874         ssb_pci_get_boardinfo(bus, &iv->boardinfo);
875
876 out:
877         return err;
878 }
879
880 #ifdef CONFIG_SSB_DEBUG
881 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
882 {
883         if (likely(bus->powered_up))
884                 return 0;
885
886         printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
887                "while accessing PCI MMIO space\n");
888         if (bus->power_warn_count <= 10) {
889                 bus->power_warn_count++;
890                 dump_stack();
891         }
892
893         return -ENODEV;
894 }
895 #else /* DEBUG */
896 static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
897 {
898         return 0;
899 }
900 #endif /* DEBUG */
901
902 static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
903 {
904         struct ssb_bus *bus = dev->bus;
905
906         if (unlikely(ssb_pci_assert_buspower(bus)))
907                 return 0xFF;
908         if (unlikely(bus->mapped_device != dev)) {
909                 if (unlikely(ssb_pci_switch_core(bus, dev)))
910                         return 0xFF;
911         }
912         return ioread8(bus->mmio + offset);
913 }
914
915 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
916 {
917         struct ssb_bus *bus = dev->bus;
918
919         if (unlikely(ssb_pci_assert_buspower(bus)))
920                 return 0xFFFF;
921         if (unlikely(bus->mapped_device != dev)) {
922                 if (unlikely(ssb_pci_switch_core(bus, dev)))
923                         return 0xFFFF;
924         }
925         return ioread16(bus->mmio + offset);
926 }
927
928 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
929 {
930         struct ssb_bus *bus = dev->bus;
931
932         if (unlikely(ssb_pci_assert_buspower(bus)))
933                 return 0xFFFFFFFF;
934         if (unlikely(bus->mapped_device != dev)) {
935                 if (unlikely(ssb_pci_switch_core(bus, dev)))
936                         return 0xFFFFFFFF;
937         }
938         return ioread32(bus->mmio + offset);
939 }
940
941 #ifdef CONFIG_SSB_BLOCKIO
942 static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
943                                size_t count, u16 offset, u8 reg_width)
944 {
945         struct ssb_bus *bus = dev->bus;
946         void __iomem *addr = bus->mmio + offset;
947
948         if (unlikely(ssb_pci_assert_buspower(bus)))
949                 goto error;
950         if (unlikely(bus->mapped_device != dev)) {
951                 if (unlikely(ssb_pci_switch_core(bus, dev)))
952                         goto error;
953         }
954         switch (reg_width) {
955         case sizeof(u8):
956                 ioread8_rep(addr, buffer, count);
957                 break;
958         case sizeof(u16):
959                 SSB_WARN_ON(count & 1);
960                 ioread16_rep(addr, buffer, count >> 1);
961                 break;
962         case sizeof(u32):
963                 SSB_WARN_ON(count & 3);
964                 ioread32_rep(addr, buffer, count >> 2);
965                 break;
966         default:
967                 SSB_WARN_ON(1);
968         }
969
970         return;
971 error:
972         memset(buffer, 0xFF, count);
973 }
974 #endif /* CONFIG_SSB_BLOCKIO */
975
976 static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
977 {
978         struct ssb_bus *bus = dev->bus;
979
980         if (unlikely(ssb_pci_assert_buspower(bus)))
981                 return;
982         if (unlikely(bus->mapped_device != dev)) {
983                 if (unlikely(ssb_pci_switch_core(bus, dev)))
984                         return;
985         }
986         iowrite8(value, bus->mmio + offset);
987 }
988
989 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
990 {
991         struct ssb_bus *bus = dev->bus;
992
993         if (unlikely(ssb_pci_assert_buspower(bus)))
994                 return;
995         if (unlikely(bus->mapped_device != dev)) {
996                 if (unlikely(ssb_pci_switch_core(bus, dev)))
997                         return;
998         }
999         iowrite16(value, bus->mmio + offset);
1000 }
1001
1002 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
1003 {
1004         struct ssb_bus *bus = dev->bus;
1005
1006         if (unlikely(ssb_pci_assert_buspower(bus)))
1007                 return;
1008         if (unlikely(bus->mapped_device != dev)) {
1009                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1010                         return;
1011         }
1012         iowrite32(value, bus->mmio + offset);
1013 }
1014
1015 #ifdef CONFIG_SSB_BLOCKIO
1016 static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1017                                 size_t count, u16 offset, u8 reg_width)
1018 {
1019         struct ssb_bus *bus = dev->bus;
1020         void __iomem *addr = bus->mmio + offset;
1021
1022         if (unlikely(ssb_pci_assert_buspower(bus)))
1023                 return;
1024         if (unlikely(bus->mapped_device != dev)) {
1025                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1026                         return;
1027         }
1028         switch (reg_width) {
1029         case sizeof(u8):
1030                 iowrite8_rep(addr, buffer, count);
1031                 break;
1032         case sizeof(u16):
1033                 SSB_WARN_ON(count & 1);
1034                 iowrite16_rep(addr, buffer, count >> 1);
1035                 break;
1036         case sizeof(u32):
1037                 SSB_WARN_ON(count & 3);
1038                 iowrite32_rep(addr, buffer, count >> 2);
1039                 break;
1040         default:
1041                 SSB_WARN_ON(1);
1042         }
1043 }
1044 #endif /* CONFIG_SSB_BLOCKIO */
1045
1046 /* Not "static", as it's used in main.c */
1047 const struct ssb_bus_ops ssb_pci_ops = {
1048         .read8          = ssb_pci_read8,
1049         .read16         = ssb_pci_read16,
1050         .read32         = ssb_pci_read32,
1051         .write8         = ssb_pci_write8,
1052         .write16        = ssb_pci_write16,
1053         .write32        = ssb_pci_write32,
1054 #ifdef CONFIG_SSB_BLOCKIO
1055         .block_read     = ssb_pci_block_read,
1056         .block_write    = ssb_pci_block_write,
1057 #endif
1058 };
1059
1060 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
1061                                        struct device_attribute *attr,
1062                                        char *buf)
1063 {
1064         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1065         struct ssb_bus *bus;
1066
1067         bus = ssb_pci_dev_to_bus(pdev);
1068         if (!bus)
1069                 return -ENODEV;
1070
1071         return ssb_attr_sprom_show(bus, buf, sprom_do_read);
1072 }
1073
1074 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
1075                                         struct device_attribute *attr,
1076                                         const char *buf, size_t count)
1077 {
1078         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1079         struct ssb_bus *bus;
1080
1081         bus = ssb_pci_dev_to_bus(pdev);
1082         if (!bus)
1083                 return -ENODEV;
1084
1085         return ssb_attr_sprom_store(bus, buf, count,
1086                                     sprom_check_crc, sprom_do_write);
1087 }
1088
1089 static DEVICE_ATTR(ssb_sprom, 0600,
1090                    ssb_pci_attr_sprom_show,
1091                    ssb_pci_attr_sprom_store);
1092
1093 void ssb_pci_exit(struct ssb_bus *bus)
1094 {
1095         struct pci_dev *pdev;
1096
1097         if (bus->bustype != SSB_BUSTYPE_PCI)
1098                 return;
1099
1100         pdev = bus->host_pci;
1101         device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1102 }
1103
1104 int ssb_pci_init(struct ssb_bus *bus)
1105 {
1106         struct pci_dev *pdev;
1107         int err;
1108
1109         if (bus->bustype != SSB_BUSTYPE_PCI)
1110                 return 0;
1111
1112         pdev = bus->host_pci;
1113         mutex_init(&bus->sprom_mutex);
1114         err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1115         if (err)
1116                 goto out;
1117
1118 out:
1119         return err;
1120 }