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