add gateway 7001 support patch from #1918
[openwrt.git] / target / linux / brcm47xx-2.6 / files / drivers / ssb / pci.c
1 /*
2  * Sonics Silicon Backplane PCI-Hostbus related functions.
3  *
4  * Copyright (C) 2005-2006 Michael Buesch <mb@bu3sch.de>
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/pci.h>
21 #include <linux/delay.h>
22
23 #include "ssb_private.h"
24
25
26 int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
27 {
28         int err;
29         int attempts = 0;
30         u32 cur_core;
31
32         while (1) {
33                 err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
34                                              (coreidx * SSB_CORE_SIZE)
35                                              + SSB_ENUM_BASE);
36                 if (err)
37                         goto error;
38                 err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
39                                             &cur_core);
40                 if (err)
41                         goto error;
42                 cur_core = (cur_core - SSB_ENUM_BASE)
43                            / SSB_CORE_SIZE;
44                 if (cur_core == coreidx)
45                         break;
46
47                 if (attempts++ > SSB_BAR0_MAX_RETRIES)
48                         goto error;
49                 udelay(10);
50         }
51         return 0;
52 error:
53         ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
54         return -ENODEV;
55 }
56
57 int ssb_pci_switch_core(struct ssb_bus *bus,
58                         struct ssb_device *dev)
59 {
60         int err;
61         unsigned long flags;
62
63         ssb_dprintk(KERN_INFO PFX
64                     "Switching to %s core, index %d\n",
65                     ssb_core_name(dev->id.coreid),
66                     dev->core_index);
67
68         spin_lock_irqsave(&bus->bar_lock, flags);
69         err = ssb_pci_switch_coreidx(bus, dev->core_index);
70         if (!err)
71                 bus->mapped_device = dev;
72         spin_unlock_irqrestore(&bus->bar_lock, flags);
73
74         return err;
75 }
76
77 int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
78 {
79         int err;
80         u32 in, out, outenable;
81         u16 pci_status;
82
83         if (bus->bustype != SSB_BUSTYPE_PCI)
84                 return 0;
85
86         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
87         if (err)
88                 goto err_pci;
89         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
90         if (err)
91                 goto err_pci;
92         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
93         if (err)
94                 goto err_pci;
95
96         outenable |= what;
97
98         if (turn_on) {
99                 /* Avoid glitching the clock if GPRS is already using it.
100                  * We can't actually read the state of the PLLPD so we infer it
101                  * by the value of XTAL_PU which *is* readable via gpioin.
102                  */
103                 if (!(in & SSB_GPIO_XTAL)) {
104                         if (what & SSB_GPIO_XTAL) {
105                                 /* Turn the crystal on */
106                                 out |= SSB_GPIO_XTAL;
107                                 if (what & SSB_GPIO_PLL)
108                                         out |= SSB_GPIO_PLL;
109                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
110                                 if (err)
111                                         goto err_pci;
112                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
113                                                              outenable);
114                                 if (err)
115                                         goto err_pci;
116                                 msleep(1);
117                         }
118                         if (what & SSB_GPIO_PLL) {
119                                 /* Turn the PLL on */
120                                 out &= ~SSB_GPIO_PLL;
121                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
122                                 if (err)
123                                         goto err_pci;
124                                 msleep(5);
125                         }
126                 }
127
128                 err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
129                 if (err)
130                         goto err_pci;
131                 pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
132                 err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
133                 if (err)
134                         goto err_pci;
135         } else {
136                 if (what & SSB_GPIO_XTAL) {
137                         /* Turn the crystal off */
138                         out &= ~SSB_GPIO_XTAL;
139                 }
140                 if (what & SSB_GPIO_PLL) {
141                         /* Turn the PLL off */
142                         out |= SSB_GPIO_PLL;
143                 }
144                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
145                 if (err)
146                         goto err_pci;
147                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
148                 if (err)
149                         goto err_pci;
150         }
151
152 out:
153         return err;
154
155 err_pci:
156         printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n");
157         err = -EBUSY;
158         goto out;
159 }
160
161 #define SPOFF(offset)   (((offset) - SSB_SPROM_BASE) / sizeof(u16))
162 #define SPEX(_outvar, _offset, _mask, _shift)   \
163         out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
164
165 static inline u8 ssb_crc8(u8 crc, u8 data)
166 {
167         /* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
168         static const u8 t[] = {
169                 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
170                 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
171                 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
172                 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
173                 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
174                 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
175                 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
176                 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
177                 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
178                 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
179                 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
180                 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
181                 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
182                 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
183                 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
184                 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
185                 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
186                 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
187                 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
188                 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
189                 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
190                 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
191                 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
192                 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
193                 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
194                 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
195                 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
196                 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
197                 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
198                 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
199                 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
200                 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
201         };
202         return t[crc ^ data];
203 }
204
205 static u8 ssb_sprom_crc(const u16 *sprom)
206 {
207         int word;
208         u8 crc = 0xFF;
209
210         for (word = 0; word < SSB_SPROMSIZE_WORDS - 1; word++) {
211                 crc = ssb_crc8(crc, sprom[word] & 0x00FF);
212                 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
213         }
214         crc = ssb_crc8(crc, sprom[SPOFF(SSB_SPROM_REVISION)] & 0x00FF);
215         crc ^= 0xFF;
216
217         return crc;
218 }
219
220 static int sprom_check_crc(const u16 *sprom)
221 {
222         u8 crc;
223         u8 expected_crc;
224         u16 tmp;
225
226         crc = ssb_sprom_crc(sprom);
227         tmp = sprom[SPOFF(SSB_SPROM_REVISION)] & SSB_SPROM_REVISION_CRC;
228         expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
229         if (crc != expected_crc)
230                 return -EPROTO;
231
232         return 0;
233 }
234
235 static void sprom_do_read(struct ssb_bus *bus, u16 *sprom)
236 {
237         int i;
238
239         for (i = 0; i < SSB_SPROMSIZE_WORDS; i++)
240                 sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2));
241 }
242
243 static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
244 {
245         struct pci_dev *pdev = bus->host_pci;
246         int i, err;
247         u32 spromctl;
248
249         ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
250         err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
251         if (err)
252                 goto err_ctlreg;
253         spromctl |= SSB_SPROMCTL_WE;
254         err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
255         if (err)
256                 goto err_ctlreg;
257         ssb_printk(KERN_NOTICE PFX "[ 0%%");
258         msleep(500);
259         for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
260                 if (i == SSB_SPROMSIZE_WORDS / 4)
261                         ssb_printk("25%%");
262                 else if (i == SSB_SPROMSIZE_WORDS / 2)
263                         ssb_printk("50%%");
264                 else if (i == (SSB_SPROMSIZE_WORDS / 4) * 3)
265                         ssb_printk("75%%");
266                 else if (i % 2)
267                         ssb_printk(".");
268                 writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2));
269                 mmiowb();
270                 msleep(20);
271         }
272         err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
273         if (err)
274                 goto err_ctlreg;
275         spromctl &= ~SSB_SPROMCTL_WE;
276         err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
277         if (err)
278                 goto err_ctlreg;
279         msleep(500);
280         ssb_printk("100%% ]\n");
281         ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
282
283         return 0;
284 err_ctlreg:
285         ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
286         return err;
287 }
288
289 static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in)
290 {
291         int i;
292         u16 v;
293
294         SPEX(pci_spid, SSB_SPROM1_SPID, 0xFFFF, 0);
295         SPEX(pci_svid, SSB_SPROM1_SVID, 0xFFFF, 0);
296         SPEX(pci_pid, SSB_SPROM1_PID, 0xFFFF, 0);
297         for (i = 0; i < 3; i++) {
298                 v = in[SPOFF(SSB_SPROM1_IL0MAC) + i];
299                 *(((u16 *)out->il0mac) + i) = cpu_to_be16(v);
300         }
301         for (i = 0; i < 3; i++) {
302                 v = in[SPOFF(SSB_SPROM1_ET0MAC) + i];
303                 *(((u16 *)out->et0mac) + i) = cpu_to_be16(v);
304         }
305         for (i = 0; i < 3; i++) {
306                 v = in[SPOFF(SSB_SPROM1_ET1MAC) + i];
307                 *(((u16 *)out->et1mac) + i) = cpu_to_be16(v);
308         }
309         SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
310         SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
311              SSB_SPROM1_ETHPHY_ET1A_SHIFT);
312         SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
313         SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
314         SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
315         SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
316              SSB_SPROM1_BINF_CCODE_SHIFT);
317         SPEX(antenna_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
318              SSB_SPROM1_BINF_ANTA_SHIFT);
319         SPEX(antenna_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
320              SSB_SPROM1_BINF_ANTBG_SHIFT);
321         SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
322         SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
323         SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
324         SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
325         SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
326         SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
327         SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
328         SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
329              SSB_SPROM1_GPIOA_P1_SHIFT);
330         SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
331         SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
332              SSB_SPROM1_GPIOB_P3_SHIFT);
333         SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
334              SSB_SPROM1_MAXPWR_A_SHIFT);
335         SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
336         SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
337              SSB_SPROM1_ITSSI_A_SHIFT);
338         SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
339         SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
340         SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0);
341         SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG,
342              SSB_SPROM1_AGAIN_BG_SHIFT);
343         for (i = 0; i < 4; i++) {
344                 v = in[SPOFF(SSB_SPROM1_OEM) + i];
345                 *(((u16 *)out->oem) + i) = cpu_to_le16(v);
346         }
347 }
348
349 static void sprom_extract_r2(struct ssb_sprom_r2 *out, const u16 *in)
350 {
351         int i;
352         u16 v;
353
354         SPEX(boardflags_hi, SSB_SPROM2_BFLHI,  0xFFFF, 0);
355         SPEX(maxpwr_a_hi, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
356         SPEX(maxpwr_a_lo, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
357              SSB_SPROM2_MAXP_A_LO_SHIFT);
358         SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
359         SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
360         SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
361         SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
362         SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
363         SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
364         SPEX(ofdm_pwr_off, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
365         for (i = 0; i < 4; i++) {
366                 v = in[SPOFF(SSB_SPROM2_CCODE) + i];
367                 *(((u16 *)out->country_str) + i) = cpu_to_le16(v);
368         }
369 }
370
371 static void sprom_extract_r3(struct ssb_sprom_r3 *out, const u16 *in)
372 {
373         out->ofdmapo  = (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0xFF00) >> 8;
374         out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0x00FF) << 8;
375         out->ofdmapo <<= 16;
376         out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0xFF00) >> 8;
377         out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0x00FF) << 8;
378
379         out->ofdmalpo  = (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0xFF00) >> 8;
380         out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0x00FF) << 8;
381         out->ofdmalpo <<= 16;
382         out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0xFF00) >> 8;
383         out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0x00FF) << 8;
384
385         out->ofdmahpo  = (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0xFF00) >> 8;
386         out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0x00FF) << 8;
387         out->ofdmahpo <<= 16;
388         out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0xFF00) >> 8;
389         out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0x00FF) << 8;
390
391         SPEX(gpioldc_on_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_ON,
392              SSB_SPROM3_GPIOLDC_ON_SHIFT);
393         SPEX(gpioldc_off_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_OFF,
394              SSB_SPROM3_GPIOLDC_OFF_SHIFT);
395         SPEX(cckpo_1M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_1M, 0);
396         SPEX(cckpo_2M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_2M,
397              SSB_SPROM3_CCKPO_2M_SHIFT);
398         SPEX(cckpo_55M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_55M,
399              SSB_SPROM3_CCKPO_55M_SHIFT);
400         SPEX(cckpo_11M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_11M,
401              SSB_SPROM3_CCKPO_11M_SHIFT);
402
403         out->ofdmgpo  = (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0xFF00) >> 8;
404         out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0x00FF) << 8;
405         out->ofdmgpo <<= 16;
406         out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0xFF00) >> 8;
407         out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0x00FF) << 8;
408 }
409
410 static int sprom_extract(struct ssb_bus *bus,
411                          struct ssb_sprom *out, const u16 *in)
412 {
413         memset(out, 0, sizeof(*out));
414
415         SPEX(revision, SSB_SPROM_REVISION, SSB_SPROM_REVISION_REV, 0);
416         SPEX(crc, SSB_SPROM_REVISION, SSB_SPROM_REVISION_CRC,
417              SSB_SPROM_REVISION_CRC_SHIFT);
418
419         if ((bus->chip_id & 0xFF00) == 0x4400) {
420                 /* Workaround: The BCM44XX chip has a stupid revision
421                  * number stored in the SPROM.
422                  * Always extract r1. */
423                 sprom_extract_r1(&out->r1, in);
424         } else {
425                 if (out->revision == 0)
426                         goto unsupported;
427                 if (out->revision >= 1 && out->revision <= 3)
428                         sprom_extract_r1(&out->r1, in);
429                 if (out->revision >= 2 && out->revision <= 3)
430                         sprom_extract_r2(&out->r2, in);
431                 if (out->revision == 3)
432                         sprom_extract_r3(&out->r3, in);
433                 if (out->revision >= 4)
434                         goto unsupported;
435         }
436
437         return 0;
438 unsupported:
439         ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
440                    "detected. Will extract v1\n", out->revision);
441         sprom_extract_r1(&out->r1, in);
442         return 0;
443 }
444
445 static int ssb_pci_sprom_get(struct ssb_bus *bus,
446                              struct ssb_sprom *sprom)
447 {
448         int err = -ENOMEM;
449         u16 *buf;
450
451         buf = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
452         if (!buf)
453                 goto out;
454         sprom_do_read(bus, buf);
455         err = sprom_check_crc(buf);
456         if (err) {
457                 ssb_printk(KERN_WARNING PFX
458                            "WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
459         }
460         err = sprom_extract(bus, sprom, buf);
461
462         kfree(buf);
463 out:
464         return err;
465 }
466
467 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
468                                   struct ssb_boardinfo *bi)
469 {
470         pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
471                              &bi->vendor);
472         pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
473                              &bi->type);
474         pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
475                              &bi->rev);
476 }
477
478 int ssb_pci_get_invariants(struct ssb_bus *bus,
479                            struct ssb_init_invariants *iv)
480 {
481         int err;
482
483         err = ssb_pci_sprom_get(bus, &iv->sprom);
484         if (err)
485                 goto out;
486         ssb_pci_get_boardinfo(bus, &iv->boardinfo);
487
488 out:
489         return err;
490 }
491
492 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
493 {
494         struct ssb_bus *bus = dev->bus;
495
496         if (unlikely(bus->mapped_device != dev)) {
497                 if (unlikely(ssb_pci_switch_core(bus, dev)))
498                         return 0xFFFF;
499         }
500         return readw(bus->mmio + offset);
501 }
502
503 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
504 {
505         struct ssb_bus *bus = dev->bus;
506
507         if (unlikely(bus->mapped_device != dev)) {
508                 if (unlikely(ssb_pci_switch_core(bus, dev)))
509                         return 0xFFFFFFFF;
510         }
511         return readl(bus->mmio + offset);
512 }
513
514 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
515 {
516         struct ssb_bus *bus = dev->bus;
517
518         if (unlikely(bus->mapped_device != dev)) {
519                 if (unlikely(ssb_pci_switch_core(bus, dev)))
520                         return;
521         }
522         writew(value, bus->mmio + offset);
523 }
524
525 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
526 {
527         struct ssb_bus *bus = dev->bus;
528
529         if (unlikely(bus->mapped_device != dev)) {
530                 if (unlikely(ssb_pci_switch_core(bus, dev)))
531                         return;
532         }
533         writel(value, bus->mmio + offset);
534 }
535
536 const struct ssb_bus_ops ssb_pci_ops = {
537         .read16         = ssb_pci_read16,
538         .read32         = ssb_pci_read32,
539         .write16        = ssb_pci_write16,
540         .write32        = ssb_pci_write32,
541 };
542
543 static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
544 {
545         int i, pos = 0;
546
547         for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
548                 pos += snprintf(buf + pos, buf_len - pos - 1,
549                                 "%04X", swab16(sprom[i]) & 0xFFFF);
550         }
551         pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
552
553         return pos + 1;
554 }
555
556 static int hex2sprom(u16 *sprom, const char *dump, size_t len)
557 {
558         char tmp[5] = { 0 };
559         int cnt = 0;
560         unsigned long parsed;
561
562         if (len < SSB_SPROMSIZE_BYTES * 2)
563                 return -EINVAL;
564
565         while (cnt < SSB_SPROMSIZE_WORDS) {
566                 memcpy(tmp, dump, 4);
567                 dump += 4;
568                 parsed = simple_strtoul(tmp, NULL, 16);
569                 sprom[cnt++] = swab16((u16)parsed);
570         }
571
572         return 0;
573 }
574
575 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
576                                        struct device_attribute *attr,
577                                        char *buf)
578 {
579         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
580         struct ssb_bus *bus;
581         u16 *sprom;
582         int err = -ENODEV;
583         ssize_t count = 0;
584
585         bus = ssb_pci_dev_to_bus(pdev);
586         if (!bus)
587                 goto out;
588         err = -ENOMEM;
589         sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
590         if (!sprom)
591                 goto out;
592
593         err = -ERESTARTSYS;
594         if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
595                 goto out_kfree;
596         sprom_do_read(bus, sprom);
597         mutex_unlock(&bus->pci_sprom_mutex);
598
599         count = sprom2hex(sprom, buf, PAGE_SIZE);
600         err = 0;
601
602 out_kfree:
603         kfree(sprom);
604 out:
605         return err ? err : count;
606 }
607
608 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
609                                         struct device_attribute *attr,
610                                         const char *buf, size_t count)
611 {
612         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
613         struct ssb_bus *bus;
614         u16 *sprom;
615         int res = 0, err = -ENODEV;
616
617         bus = ssb_pci_dev_to_bus(pdev);
618         if (!bus)
619                 goto out;
620         err = -ENOMEM;
621         sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
622         if (!sprom)
623                 goto out;
624         err = hex2sprom(sprom, buf, count);
625         if (err) {
626                 err = -EINVAL;
627                 goto out_kfree;
628         }
629         err = sprom_check_crc(sprom);
630         if (err) {
631                 err = -EINVAL;
632                 goto out_kfree;
633         }
634
635         err = -ERESTARTSYS;
636         if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
637                 goto out_kfree;
638         err = ssb_devices_freeze(bus);
639         if (err) {
640                 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
641                 goto out_unlock;
642         }
643         res = sprom_do_write(bus, sprom);
644         err = ssb_devices_thaw(bus);
645         if (err)
646                 ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
647 out_unlock:
648         mutex_unlock(&bus->pci_sprom_mutex);
649 out_kfree:
650         kfree(sprom);
651 out:
652         if (res)
653                 return res;
654         return err ? err : count;
655 }
656
657 static DEVICE_ATTR(ssb_sprom, 0600,
658                    ssb_pci_attr_sprom_show,
659                    ssb_pci_attr_sprom_store);
660
661 void ssb_pci_exit(struct ssb_bus *bus)
662 {
663         struct pci_dev *pdev;
664
665         if (bus->bustype != SSB_BUSTYPE_PCI)
666                 return;
667
668         pdev = bus->host_pci;
669         device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
670 }
671
672 int ssb_pci_init(struct ssb_bus *bus)
673 {
674         struct pci_dev *pdev;
675         int err;
676
677         if (bus->bustype != SSB_BUSTYPE_PCI)
678                 return 0;
679
680         pdev = bus->host_pci;
681         mutex_init(&bus->pci_sprom_mutex);
682         err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
683         if (err)
684                 goto out;
685
686 out:
687         return err;
688 }