ssb: Fix extraction of values from SPROM
[safe/jmp/linux-2.6] / 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 /* Define the following to 1 to enable a printk on each coreswitch. */
27 #define SSB_VERBOSE_PCICORESWITCH_DEBUG         0
28
29
30 /* Lowlevel coreswitching */
31 int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
32 {
33         int err;
34         int attempts = 0;
35         u32 cur_core;
36
37         while (1) {
38                 err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
39                                              (coreidx * SSB_CORE_SIZE)
40                                              + SSB_ENUM_BASE);
41                 if (err)
42                         goto error;
43                 err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
44                                             &cur_core);
45                 if (err)
46                         goto error;
47                 cur_core = (cur_core - SSB_ENUM_BASE)
48                            / SSB_CORE_SIZE;
49                 if (cur_core == coreidx)
50                         break;
51
52                 if (attempts++ > SSB_BAR0_MAX_RETRIES)
53                         goto error;
54                 udelay(10);
55         }
56         return 0;
57 error:
58         ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
59         return -ENODEV;
60 }
61
62 int ssb_pci_switch_core(struct ssb_bus *bus,
63                         struct ssb_device *dev)
64 {
65         int err;
66         unsigned long flags;
67
68 #if SSB_VERBOSE_PCICORESWITCH_DEBUG
69         ssb_printk(KERN_INFO PFX
70                    "Switching to %s core, index %d\n",
71                    ssb_core_name(dev->id.coreid),
72                    dev->core_index);
73 #endif
74
75         spin_lock_irqsave(&bus->bar_lock, flags);
76         err = ssb_pci_switch_coreidx(bus, dev->core_index);
77         if (!err)
78                 bus->mapped_device = dev;
79         spin_unlock_irqrestore(&bus->bar_lock, flags);
80
81         return err;
82 }
83
84 /* Enable/disable the on board crystal oscillator and/or PLL. */
85 int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
86 {
87         int err;
88         u32 in, out, outenable;
89         u16 pci_status;
90
91         if (bus->bustype != SSB_BUSTYPE_PCI)
92                 return 0;
93
94         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
95         if (err)
96                 goto err_pci;
97         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
98         if (err)
99                 goto err_pci;
100         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
101         if (err)
102                 goto err_pci;
103
104         outenable |= what;
105
106         if (turn_on) {
107                 /* Avoid glitching the clock if GPRS is already using it.
108                  * We can't actually read the state of the PLLPD so we infer it
109                  * by the value of XTAL_PU which *is* readable via gpioin.
110                  */
111                 if (!(in & SSB_GPIO_XTAL)) {
112                         if (what & SSB_GPIO_XTAL) {
113                                 /* Turn the crystal on */
114                                 out |= SSB_GPIO_XTAL;
115                                 if (what & SSB_GPIO_PLL)
116                                         out |= SSB_GPIO_PLL;
117                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
118                                 if (err)
119                                         goto err_pci;
120                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
121                                                              outenable);
122                                 if (err)
123                                         goto err_pci;
124                                 msleep(1);
125                         }
126                         if (what & SSB_GPIO_PLL) {
127                                 /* Turn the PLL on */
128                                 out &= ~SSB_GPIO_PLL;
129                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
130                                 if (err)
131                                         goto err_pci;
132                                 msleep(5);
133                         }
134                 }
135
136                 err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
137                 if (err)
138                         goto err_pci;
139                 pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
140                 err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
141                 if (err)
142                         goto err_pci;
143         } else {
144                 if (what & SSB_GPIO_XTAL) {
145                         /* Turn the crystal off */
146                         out &= ~SSB_GPIO_XTAL;
147                 }
148                 if (what & SSB_GPIO_PLL) {
149                         /* Turn the PLL off */
150                         out |= SSB_GPIO_PLL;
151                 }
152                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
153                 if (err)
154                         goto err_pci;
155                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
156                 if (err)
157                         goto err_pci;
158         }
159
160 out:
161         return err;
162
163 err_pci:
164         printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n");
165         err = -EBUSY;
166         goto out;
167 }
168
169 /* Get the word-offset for a SSB_SPROM_XXX define. */
170 #define SPOFF(offset)   (((offset) - SSB_SPROM_BASE) / sizeof(u16))
171 /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
172 #define SPEX(_outvar, _offset, _mask, _shift)   \
173         out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
174
175 static inline u8 ssb_crc8(u8 crc, u8 data)
176 {
177         /* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
178         static const u8 t[] = {
179                 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
180                 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
181                 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
182                 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
183                 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
184                 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
185                 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
186                 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
187                 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
188                 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
189                 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
190                 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
191                 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
192                 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
193                 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
194                 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
195                 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
196                 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
197                 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
198                 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
199                 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
200                 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
201                 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
202                 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
203                 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
204                 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
205                 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
206                 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
207                 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
208                 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
209                 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
210                 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
211         };
212         return t[crc ^ data];
213 }
214
215 static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
216 {
217         int word;
218         u8 crc = 0xFF;
219
220         for (word = 0; word < size - 1; word++) {
221                 crc = ssb_crc8(crc, sprom[word] & 0x00FF);
222                 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
223         }
224         crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
225         crc ^= 0xFF;
226
227         return crc;
228 }
229
230 static int sprom_check_crc(const u16 *sprom, u16 size)
231 {
232         u8 crc;
233         u8 expected_crc;
234         u16 tmp;
235
236         crc = ssb_sprom_crc(sprom, size);
237         tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
238         expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
239         if (crc != expected_crc)
240                 return -EPROTO;
241
242         return 0;
243 }
244
245 static void sprom_do_read(struct ssb_bus *bus, u16 *sprom)
246 {
247         int i;
248
249         for (i = 0; i < bus->sprom_size; i++)
250                 sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
251 }
252
253 static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
254 {
255         struct pci_dev *pdev = bus->host_pci;
256         int i, err;
257         u32 spromctl;
258         u16 size = bus->sprom_size;
259
260         ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
261         err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
262         if (err)
263                 goto err_ctlreg;
264         spromctl |= SSB_SPROMCTL_WE;
265         err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
266         if (err)
267                 goto err_ctlreg;
268         ssb_printk(KERN_NOTICE PFX "[ 0%%");
269         msleep(500);
270         for (i = 0; i < size; i++) {
271                 if (i == size / 4)
272                         ssb_printk("25%%");
273                 else if (i == size / 2)
274                         ssb_printk("50%%");
275                 else if (i == (size * 3) / 4)
276                         ssb_printk("75%%");
277                 else if (i % 2)
278                         ssb_printk(".");
279                 writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2));
280                 mmiowb();
281                 msleep(20);
282         }
283         err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
284         if (err)
285                 goto err_ctlreg;
286         spromctl &= ~SSB_SPROMCTL_WE;
287         err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
288         if (err)
289                 goto err_ctlreg;
290         msleep(500);
291         ssb_printk("100%% ]\n");
292         ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
293
294         return 0;
295 err_ctlreg:
296         ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
297         return err;
298 }
299
300 static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
301                                u16 mask, u16 shift)
302 {
303         u16 v;
304         u8 gain;
305
306         v = in[SPOFF(SSB_SPROM1_AGAIN)];
307         gain = (v & mask) >> shift;
308         if (gain == 0xFF)
309                 gain = 2; /* If unset use 2dBm */
310         if (sprom_revision == 1) {
311                 /* Convert to Q5.2 */
312                 gain <<= 2;
313         } else {
314                 /* Q5.2 Fractional part is stored in 0xC0 */
315                 gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
316         }
317
318         return (s8)gain;
319 }
320
321 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
322 {
323         int i;
324         u16 v;
325         s8 gain;
326         u16 loc[3];
327
328         if (out->revision == 3) {                       /* rev 3 moved MAC */
329                 loc[0] = SSB_SPROM3_IL0MAC;
330                 loc[1] = SSB_SPROM3_ET0MAC;
331                 loc[2] = SSB_SPROM3_ET1MAC;
332         } else {
333                 loc[0] = SSB_SPROM1_IL0MAC;
334                 loc[1] = SSB_SPROM1_ET0MAC;
335                 loc[2] = SSB_SPROM1_ET1MAC;
336         }
337         for (i = 0; i < 3; i++) {
338                 v = in[SPOFF(loc[0]) + i];
339                 *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
340         }
341         for (i = 0; i < 3; i++) {
342                 v = in[SPOFF(loc[1]) + i];
343                 *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
344         }
345         for (i = 0; i < 3; i++) {
346                 v = in[SPOFF(loc[2]) + i];
347                 *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
348         }
349         SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
350         SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
351              SSB_SPROM1_ETHPHY_ET1A_SHIFT);
352         SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
353         SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
354         SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
355         SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
356              SSB_SPROM1_BINF_CCODE_SHIFT);
357         SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
358              SSB_SPROM1_BINF_ANTA_SHIFT);
359         SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
360              SSB_SPROM1_BINF_ANTBG_SHIFT);
361         SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
362         SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
363         SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
364         SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
365         SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
366         SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
367         SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
368         SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
369              SSB_SPROM1_GPIOA_P1_SHIFT);
370         SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
371         SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
372              SSB_SPROM1_GPIOB_P3_SHIFT);
373         SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
374              SSB_SPROM1_MAXPWR_A_SHIFT);
375         SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
376         SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
377              SSB_SPROM1_ITSSI_A_SHIFT);
378         SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
379         SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
380
381         /* Extract the antenna gain values. */
382         gain = r123_extract_antgain(out->revision, in,
383                                     SSB_SPROM1_AGAIN_BG,
384                                     SSB_SPROM1_AGAIN_BG_SHIFT);
385         out->antenna_gain.ghz24.a0 = gain;
386         out->antenna_gain.ghz24.a1 = gain;
387         out->antenna_gain.ghz24.a2 = gain;
388         out->antenna_gain.ghz24.a3 = gain;
389         gain = r123_extract_antgain(out->revision, in,
390                                     SSB_SPROM1_AGAIN_A,
391                                     SSB_SPROM1_AGAIN_A_SHIFT);
392         out->antenna_gain.ghz5.a0 = gain;
393         out->antenna_gain.ghz5.a1 = gain;
394         out->antenna_gain.ghz5.a2 = gain;
395         out->antenna_gain.ghz5.a3 = gain;
396 }
397
398 static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in)
399 {
400         int i;
401         u16 v;
402
403         /* extract the equivalent of the r1 variables */
404         for (i = 0; i < 3; i++) {
405                 v = in[SPOFF(SSB_SPROM4_IL0MAC) + i];
406                 *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
407         }
408         for (i = 0; i < 3; i++) {
409                 v = in[SPOFF(SSB_SPROM4_ET0MAC) + i];
410                 *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
411         }
412         for (i = 0; i < 3; i++) {
413                 v = in[SPOFF(SSB_SPROM4_ET1MAC) + i];
414                 *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
415         }
416         SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
417         SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
418              SSB_SPROM4_ETHPHY_ET1A_SHIFT);
419         SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
420         SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
421         SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
422              SSB_SPROM4_ANTAVAIL_A_SHIFT);
423         SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
424              SSB_SPROM4_ANTAVAIL_BG_SHIFT);
425         SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
426         SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
427              SSB_SPROM4_ITSSI_BG_SHIFT);
428         SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
429         SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
430              SSB_SPROM4_ITSSI_A_SHIFT);
431         SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
432         SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
433              SSB_SPROM4_GPIOA_P1_SHIFT);
434         SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
435         SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
436              SSB_SPROM4_GPIOB_P3_SHIFT);
437
438         /* Extract the antenna gain values. */
439         SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
440              SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
441         SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
442              SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
443         SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
444              SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
445         SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
446              SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
447         memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
448                sizeof(out->antenna_gain.ghz5));
449
450         /* TODO - get remaining rev 4 stuff needed */
451 }
452
453 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
454                          const u16 *in, u16 size)
455 {
456         memset(out, 0, sizeof(*out));
457
458         out->revision = in[size - 1] & 0x00FF;
459         ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
460         if ((bus->chip_id & 0xFF00) == 0x4400) {
461                 /* Workaround: The BCM44XX chip has a stupid revision
462                  * number stored in the SPROM.
463                  * Always extract r1. */
464                 out->revision = 1;
465                 sprom_extract_r123(out, in);
466         } else if (bus->chip_id == 0x4321) {
467                 /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
468                 out->revision = 4;
469                 sprom_extract_r4(out, in);
470         } else {
471                 if (out->revision == 0)
472                         goto unsupported;
473                 if (out->revision >= 1 && out->revision <= 3) {
474                         sprom_extract_r123(out, in);
475                 }
476                 if (out->revision == 4)
477                         sprom_extract_r4(out, in);
478                 if (out->revision >= 5)
479                         goto unsupported;
480         }
481
482         return 0;
483 unsupported:
484         ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
485                    "detected. Will extract v1\n", out->revision);
486         sprom_extract_r123(out, in);
487         return 0;
488 }
489
490 static int ssb_pci_sprom_get(struct ssb_bus *bus,
491                              struct ssb_sprom *sprom)
492 {
493         int err = -ENOMEM;
494         u16 *buf;
495
496         buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
497         if (!buf)
498                 goto out;
499         bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
500         sprom_do_read(bus, buf);
501         err = sprom_check_crc(buf, bus->sprom_size);
502         if (err) {
503                 /* check for rev 4 sprom - has special signature */
504                 if (buf[32] == 0x5372) {
505                         kfree(buf);
506                         buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
507                                       GFP_KERNEL);
508                         if (!buf)
509                                 goto out;
510                         bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
511                         sprom_do_read(bus, buf);
512                         err = sprom_check_crc(buf, bus->sprom_size);
513                 }
514                 if (err)
515                         ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
516                                    " SPROM CRC (corrupt SPROM)\n");
517         }
518         err = sprom_extract(bus, sprom, buf, bus->sprom_size);
519
520         kfree(buf);
521 out:
522         return err;
523 }
524
525 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
526                                   struct ssb_boardinfo *bi)
527 {
528         pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
529                              &bi->vendor);
530         pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
531                              &bi->type);
532         pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
533                              &bi->rev);
534 }
535
536 int ssb_pci_get_invariants(struct ssb_bus *bus,
537                            struct ssb_init_invariants *iv)
538 {
539         int err;
540
541         err = ssb_pci_sprom_get(bus, &iv->sprom);
542         if (err)
543                 goto out;
544         ssb_pci_get_boardinfo(bus, &iv->boardinfo);
545
546 out:
547         return err;
548 }
549
550 #ifdef CONFIG_SSB_DEBUG
551 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
552 {
553         if (likely(bus->powered_up))
554                 return 0;
555
556         printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
557                "while accessing PCI MMIO space\n");
558         if (bus->power_warn_count <= 10) {
559                 bus->power_warn_count++;
560                 dump_stack();
561         }
562
563         return -ENODEV;
564 }
565 #else /* DEBUG */
566 static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
567 {
568         return 0;
569 }
570 #endif /* DEBUG */
571
572 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
573 {
574         struct ssb_bus *bus = dev->bus;
575
576         if (unlikely(ssb_pci_assert_buspower(bus)))
577                 return 0xFFFF;
578         if (unlikely(bus->mapped_device != dev)) {
579                 if (unlikely(ssb_pci_switch_core(bus, dev)))
580                         return 0xFFFF;
581         }
582         return ioread16(bus->mmio + offset);
583 }
584
585 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
586 {
587         struct ssb_bus *bus = dev->bus;
588
589         if (unlikely(ssb_pci_assert_buspower(bus)))
590                 return 0xFFFFFFFF;
591         if (unlikely(bus->mapped_device != dev)) {
592                 if (unlikely(ssb_pci_switch_core(bus, dev)))
593                         return 0xFFFFFFFF;
594         }
595         return ioread32(bus->mmio + offset);
596 }
597
598 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
599 {
600         struct ssb_bus *bus = dev->bus;
601
602         if (unlikely(ssb_pci_assert_buspower(bus)))
603                 return;
604         if (unlikely(bus->mapped_device != dev)) {
605                 if (unlikely(ssb_pci_switch_core(bus, dev)))
606                         return;
607         }
608         iowrite16(value, bus->mmio + offset);
609 }
610
611 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
612 {
613         struct ssb_bus *bus = dev->bus;
614
615         if (unlikely(ssb_pci_assert_buspower(bus)))
616                 return;
617         if (unlikely(bus->mapped_device != dev)) {
618                 if (unlikely(ssb_pci_switch_core(bus, dev)))
619                         return;
620         }
621         iowrite32(value, bus->mmio + offset);
622 }
623
624 /* Not "static", as it's used in main.c */
625 const struct ssb_bus_ops ssb_pci_ops = {
626         .read16         = ssb_pci_read16,
627         .read32         = ssb_pci_read32,
628         .write16        = ssb_pci_write16,
629         .write32        = ssb_pci_write32,
630 };
631
632 static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size)
633 {
634         int i, pos = 0;
635
636         for (i = 0; i < size; i++)
637                 pos += snprintf(buf + pos, buf_len - pos - 1,
638                                 "%04X", swab16(sprom[i]) & 0xFFFF);
639         pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
640
641         return pos + 1;
642 }
643
644 static int hex2sprom(u16 *sprom, const char *dump, size_t len, u16 size)
645 {
646         char tmp[5] = { 0 };
647         int cnt = 0;
648         unsigned long parsed;
649
650         if (len < size * 2)
651                 return -EINVAL;
652
653         while (cnt < size) {
654                 memcpy(tmp, dump, 4);
655                 dump += 4;
656                 parsed = simple_strtoul(tmp, NULL, 16);
657                 sprom[cnt++] = swab16((u16)parsed);
658         }
659
660         return 0;
661 }
662
663 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
664                                        struct device_attribute *attr,
665                                        char *buf)
666 {
667         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
668         struct ssb_bus *bus;
669         u16 *sprom;
670         int err = -ENODEV;
671         ssize_t count = 0;
672
673         bus = ssb_pci_dev_to_bus(pdev);
674         if (!bus)
675                 goto out;
676         err = -ENOMEM;
677         sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
678         if (!sprom)
679                 goto out;
680
681         /* Use interruptible locking, as the SPROM write might
682          * be holding the lock for several seconds. So allow userspace
683          * to cancel operation. */
684         err = -ERESTARTSYS;
685         if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
686                 goto out_kfree;
687         sprom_do_read(bus, sprom);
688         mutex_unlock(&bus->pci_sprom_mutex);
689
690         count = sprom2hex(sprom, buf, PAGE_SIZE, bus->sprom_size);
691         err = 0;
692
693 out_kfree:
694         kfree(sprom);
695 out:
696         return err ? err : count;
697 }
698
699 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
700                                         struct device_attribute *attr,
701                                         const char *buf, size_t count)
702 {
703         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
704         struct ssb_bus *bus;
705         u16 *sprom;
706         int res = 0, err = -ENODEV;
707
708         bus = ssb_pci_dev_to_bus(pdev);
709         if (!bus)
710                 goto out;
711         err = -ENOMEM;
712         sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
713         if (!sprom)
714                 goto out;
715         err = hex2sprom(sprom, buf, count, bus->sprom_size);
716         if (err) {
717                 err = -EINVAL;
718                 goto out_kfree;
719         }
720         err = sprom_check_crc(sprom, bus->sprom_size);
721         if (err) {
722                 err = -EINVAL;
723                 goto out_kfree;
724         }
725
726         /* Use interruptible locking, as the SPROM write might
727          * be holding the lock for several seconds. So allow userspace
728          * to cancel operation. */
729         err = -ERESTARTSYS;
730         if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
731                 goto out_kfree;
732         err = ssb_devices_freeze(bus);
733         if (err == -EOPNOTSUPP) {
734                 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
735                            "No suspend support. Is CONFIG_PM enabled?\n");
736                 goto out_unlock;
737         }
738         if (err) {
739                 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
740                 goto out_unlock;
741         }
742         res = sprom_do_write(bus, sprom);
743         err = ssb_devices_thaw(bus);
744         if (err)
745                 ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
746 out_unlock:
747         mutex_unlock(&bus->pci_sprom_mutex);
748 out_kfree:
749         kfree(sprom);
750 out:
751         if (res)
752                 return res;
753         return err ? err : count;
754 }
755
756 static DEVICE_ATTR(ssb_sprom, 0600,
757                    ssb_pci_attr_sprom_show,
758                    ssb_pci_attr_sprom_store);
759
760 void ssb_pci_exit(struct ssb_bus *bus)
761 {
762         struct pci_dev *pdev;
763
764         if (bus->bustype != SSB_BUSTYPE_PCI)
765                 return;
766
767         pdev = bus->host_pci;
768         device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
769 }
770
771 int ssb_pci_init(struct ssb_bus *bus)
772 {
773         struct pci_dev *pdev;
774         int err;
775
776         if (bus->bustype != SSB_BUSTYPE_PCI)
777                 return 0;
778
779         pdev = bus->host_pci;
780         mutex_init(&bus->pci_sprom_mutex);
781         err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
782         if (err)
783                 goto out;
784
785 out:
786         return err;
787 }