brcm43xx: update SSB driver * files/ now contains the wireless-dev tree version ...
[librecmc/librecmc.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, 0);
334         SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG,
335              SSB_SPROM1_MAXPWR_BG_SHIFT);
336         SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A, 0);
337         SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG,
338              SSB_SPROM1_ITSSI_BG_SHIFT);
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_sprom *out, const u16 *in)
411 {
412         memset(out, 0, sizeof(*out));
413
414         SPEX(revision, SSB_SPROM_REVISION, SSB_SPROM_REVISION_REV, 0);
415         SPEX(crc, SSB_SPROM_REVISION, SSB_SPROM_REVISION_CRC,
416              SSB_SPROM_REVISION_CRC_SHIFT);
417
418         if (out->revision == 0)
419                 goto unsupported;
420         if (out->revision >= 1 && out->revision <= 3)
421                 sprom_extract_r1(&out->r1, in);
422         if (out->revision >= 2 && out->revision <= 3)
423                 sprom_extract_r2(&out->r2, in);
424         if (out->revision == 3)
425                 sprom_extract_r3(&out->r3, in);
426         if (out->revision >= 4)
427                 goto unsupported;
428
429         return 0;
430 unsupported:
431         ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
432                    "detected. Will extract v1\n", out->revision);
433         sprom_extract_r1(&out->r1, in);
434         return 0;
435 }
436
437 int ssb_pci_sprom_get(struct ssb_bus *bus)
438 {
439         int err = -ENOMEM;
440         u16 *buf;
441
442         assert(bus->bustype == SSB_BUSTYPE_PCI);
443
444         buf = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
445         if (!buf)
446                 goto out;
447         sprom_do_read(bus, buf);
448         err = sprom_check_crc(buf);
449         if (err) {
450                 ssb_printk(KERN_WARNING PFX
451                            "WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
452         }
453         err = sprom_extract(&bus->sprom, buf);
454
455         kfree(buf);
456 out:
457         return err;
458 }
459
460 void ssb_pci_get_boardtype(struct ssb_bus *bus)
461 {
462         pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
463                              &bus->board_vendor);
464         pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
465                              &bus->board_type);
466         pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
467                              &bus->board_rev);
468 }
469
470 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
471 {
472         struct ssb_bus *bus = dev->bus;
473
474         if (unlikely(bus->mapped_device != dev)) {
475                 if (unlikely(ssb_pci_switch_core(bus, dev)))
476                         return 0xFFFF;
477         }
478         return readw(bus->mmio + offset);
479 }
480
481 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
482 {
483         struct ssb_bus *bus = dev->bus;
484
485         if (unlikely(bus->mapped_device != dev)) {
486                 if (unlikely(ssb_pci_switch_core(bus, dev)))
487                         return 0xFFFFFFFF;
488         }
489         return readl(bus->mmio + offset);
490 }
491
492 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
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;
499         }
500         writew(value, bus->mmio + offset);
501 }
502
503 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
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;
510         }
511         writel(value, bus->mmio + offset);
512 }
513
514 const struct ssb_bus_ops ssb_pci_ops = {
515         .read16         = ssb_pci_read16,
516         .read32         = ssb_pci_read32,
517         .write16        = ssb_pci_write16,
518         .write32        = ssb_pci_write32,
519 };
520
521 static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
522 {
523         int i, pos = 0;
524
525         for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
526                 pos += snprintf(buf + pos, buf_len - pos - 1,
527                                 "%04X", swab16(sprom[i]) & 0xFFFF);
528         }
529         pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
530
531         return pos + 1;
532 }
533
534 static int hex2sprom(u16 *sprom, const char *dump, size_t len)
535 {
536         char tmp[5] = { 0 };
537         int cnt = 0;
538         unsigned long parsed;
539
540         if (len < SSB_SPROMSIZE_BYTES * 2)
541                 return -EINVAL;
542
543         while (cnt < SSB_SPROMSIZE_WORDS) {
544                 memcpy(tmp, dump, 4);
545                 dump += 4;
546                 parsed = simple_strtoul(tmp, NULL, 16);
547                 sprom[cnt++] = swab16((u16)parsed);
548         }
549
550         return 0;
551 }
552
553 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
554                                        struct device_attribute *attr,
555                                        char *buf)
556 {
557         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
558         struct ssb_bus *bus;
559         u16 *sprom;
560         int err = -ENODEV;
561         ssize_t count = 0;
562
563         bus = ssb_pci_dev_to_bus(pdev);
564         if (!bus)
565                 goto out;
566         err = -ENOMEM;
567         sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
568         if (!sprom)
569                 goto out;
570
571         err = -ERESTARTSYS;
572         if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
573                 goto out_kfree;
574         sprom_do_read(bus, sprom);
575         mutex_unlock(&bus->pci_sprom_mutex);
576
577         count = sprom2hex(sprom, buf, PAGE_SIZE);
578         err = 0;
579
580 out_kfree:
581         kfree(sprom);
582 out:
583         return err ? err : count;
584 }
585
586 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
587                                         struct device_attribute *attr,
588                                         const char *buf, size_t count)
589 {
590         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
591         struct ssb_bus *bus;
592         u16 *sprom;
593         int res = 0, err = -ENODEV;
594
595         bus = ssb_pci_dev_to_bus(pdev);
596         if (!bus)
597                 goto out;
598         err = -ENOMEM;
599         sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
600         if (!sprom)
601                 goto out;
602         err = hex2sprom(sprom, buf, count);
603         if (err) {
604                 err = -EINVAL;
605                 goto out_kfree;
606         }
607         err = sprom_check_crc(sprom);
608         if (err) {
609                 err = -EINVAL;
610                 goto out_kfree;
611         }
612
613         err = -ERESTARTSYS;
614         if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
615                 goto out_kfree;
616         err = ssb_devices_freeze(bus);
617         if (err) {
618                 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
619                 goto out_unlock;
620         }
621         res = sprom_do_write(bus, sprom);
622         err = ssb_devices_thaw(bus);
623         if (err)
624                 ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
625 out_unlock:
626         mutex_unlock(&bus->pci_sprom_mutex);
627 out_kfree:
628         kfree(sprom);
629 out:
630         if (res)
631                 return res;
632         return err ? err : count;
633 }
634
635 static DEVICE_ATTR(ssb_sprom, 0600,
636                    ssb_pci_attr_sprom_show,
637                    ssb_pci_attr_sprom_store);
638
639 void ssb_pci_exit(struct ssb_bus *bus)
640 {
641         struct pci_dev *pdev;
642
643         if (bus->bustype != SSB_BUSTYPE_PCI)
644                 return;
645
646         pdev = bus->host_pci;
647         device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
648 }
649
650 int ssb_pci_init(struct ssb_bus *bus)
651 {
652         struct pci_dev *pdev;
653         int err;
654
655         if (bus->bustype != SSB_BUSTYPE_PCI)
656                 return 0;
657
658         pdev = bus->host_pci;
659         mutex_init(&bus->pci_sprom_mutex);
660         err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
661         if (err)
662                 goto out;
663         err = ssb_pci_sprom_get(bus);
664         if (err)
665                 goto err_remove_sprom_file;
666
667 out:
668         return err;
669 err_remove_sprom_file:
670         device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
671         return err;
672 }