]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/ssb/pci.c
ssb: Convert to use of the new SPROM structure
[linux-2.6-omap-h63xx.git] / 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] = readw(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 void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in)
301 {
302         int i;
303         u16 v;
304
305         SPEX(pci_spid, SSB_SPROM1_SPID, 0xFFFF, 0);
306         SPEX(pci_svid, SSB_SPROM1_SVID, 0xFFFF, 0);
307         SPEX(pci_pid, SSB_SPROM1_PID, 0xFFFF, 0);
308         for (i = 0; i < 3; i++) {
309                 v = in[SPOFF(SSB_SPROM1_IL0MAC) + i];
310                 *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
311         }
312         for (i = 0; i < 3; i++) {
313                 v = in[SPOFF(SSB_SPROM1_ET0MAC) + i];
314                 *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
315         }
316         for (i = 0; i < 3; i++) {
317                 v = in[SPOFF(SSB_SPROM1_ET1MAC) + i];
318                 *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
319         }
320         SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
321         SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
322              SSB_SPROM1_ETHPHY_ET1A_SHIFT);
323         SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
324         SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
325         SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
326         SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
327              SSB_SPROM1_BINF_CCODE_SHIFT);
328         SPEX(antenna_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
329              SSB_SPROM1_BINF_ANTA_SHIFT);
330         SPEX(antenna_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
331              SSB_SPROM1_BINF_ANTBG_SHIFT);
332         SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
333         SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
334         SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
335         SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
336         SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
337         SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
338         SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
339         SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
340              SSB_SPROM1_GPIOA_P1_SHIFT);
341         SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
342         SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
343              SSB_SPROM1_GPIOB_P3_SHIFT);
344         SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
345              SSB_SPROM1_MAXPWR_A_SHIFT);
346         SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
347         SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
348              SSB_SPROM1_ITSSI_A_SHIFT);
349         SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
350         SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
351         SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0);
352         SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG,
353              SSB_SPROM1_AGAIN_BG_SHIFT);
354 }
355
356 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
357 {
358         int i;
359         u16 v;
360         u16 loc[3];
361
362         if (out->revision == 3) {                       /* rev 3 moved MAC */
363                 loc[0] = SSB_SPROM3_IL0MAC;
364                 loc[1] = SSB_SPROM3_ET0MAC;
365                 loc[2] = SSB_SPROM3_ET1MAC;
366         } else {
367                 loc[0] = SSB_SPROM1_IL0MAC;
368                 loc[1] = SSB_SPROM1_ET0MAC;
369                 loc[2] = SSB_SPROM1_ET1MAC;
370         }
371         for (i = 0; i < 3; i++) {
372                 v = in[SPOFF(loc[0]) + i];
373                 *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
374         }
375         for (i = 0; i < 3; i++) {
376                 v = in[SPOFF(loc[1]) + i];
377                 *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
378         }
379         for (i = 0; i < 3; i++) {
380                 v = in[SPOFF(loc[2]) + i];
381                 *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
382         }
383         SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
384         SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
385              SSB_SPROM1_ETHPHY_ET1A_SHIFT);
386         SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
387              SSB_SPROM1_BINF_CCODE_SHIFT);
388         SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
389         SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
390         SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
391         SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
392         SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
393         SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
394         SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
395         SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
396              SSB_SPROM1_GPIOA_P1_SHIFT);
397         SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
398         SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
399              SSB_SPROM1_GPIOB_P3_SHIFT);
400         SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
401              SSB_SPROM1_MAXPWR_A_SHIFT);
402         SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
403         SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
404              SSB_SPROM1_ITSSI_A_SHIFT);
405         SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
406         SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
407         SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0);
408         SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG,
409              SSB_SPROM1_AGAIN_BG_SHIFT);
410 }
411
412 static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in)
413 {
414         int i;
415         u16 v;
416
417         /* extract the r1 variables */
418         for (i = 0; i < 3; i++) {
419                 v = in[SPOFF(SSB_SPROM4_IL0MAC) + i];
420                 *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
421         }
422         for (i = 0; i < 3; i++) {
423                 v = in[SPOFF(SSB_SPROM4_ET0MAC) + i];
424                 *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
425         }
426         for (i = 0; i < 3; i++) {
427                 v = in[SPOFF(SSB_SPROM4_ET1MAC) + i];
428                 *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
429         }
430         SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
431         SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
432              SSB_SPROM4_ETHPHY_ET1A_SHIFT);
433         SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
434         SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
435         SPEX(antenna_gain_a, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_0, 0);
436         SPEX(antenna_gain_bg, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_1,
437              SSB_SPROM4_AGAIN_1_SHIFT);
438         /* TODO - get remaining rev 4 stuff needed */
439 }
440
441 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
442                          const u16 *in, u16 size)
443 {
444         memset(out, 0, sizeof(*out));
445
446         out->revision = in[size - 1] & 0x00FF;
447         if ((bus->chip_id & 0xFF00) == 0x4400) {
448                 /* Workaround: The BCM44XX chip has a stupid revision
449                  * number stored in the SPROM.
450                  * Always extract r1. */
451                 out->revision = 1;
452                 sprom_extract_r123(out, in);
453                 sprom_extract_r1(&out->r1, in);
454         } else if (bus->chip_id == 0x4321) {
455                 /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
456                 out->revision = 4;
457                 sprom_extract_r4(out, in);
458         } else {
459                 if (out->revision == 0)
460                         goto unsupported;
461                 if (out->revision >= 1 && out->revision <= 3) {
462                         sprom_extract_r123(out, in);
463                         sprom_extract_r1(&out->r1, in);
464                 }
465                 if (out->revision == 4)
466                         sprom_extract_r4(out, in);
467                 if (out->revision >= 5)
468                         goto unsupported;
469         }
470
471         return 0;
472 unsupported:
473         ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
474                    "detected. Will extract v1\n", out->revision);
475         sprom_extract_r1(&out->r1, in);
476         return 0;
477 }
478
479 static int ssb_pci_sprom_get(struct ssb_bus *bus,
480                              struct ssb_sprom *sprom)
481 {
482         int err = -ENOMEM;
483         u16 *buf;
484
485         buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
486         if (!buf)
487                 goto out;
488         bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
489         sprom_do_read(bus, buf);
490         err = sprom_check_crc(buf, bus->sprom_size);
491         if (err) {
492                 /* check for rev 4 sprom - has special signature */
493                 if (buf [32] == 0x5372) {
494                         ssb_printk(KERN_WARNING PFX "Extracting a rev 4"
495                                    " SPROM\n");
496                         kfree(buf);
497                         buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
498                                       GFP_KERNEL);
499                         if (!buf)
500                                 goto out;
501                         bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
502                         sprom_do_read(bus, buf);
503                         err = sprom_check_crc(buf, bus->sprom_size);
504                 }
505                 if (err)
506                         ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
507                                    " SPROM CRC (corrupt SPROM)\n");
508         }
509         err = sprom_extract(bus, sprom, buf, bus->sprom_size);
510
511         kfree(buf);
512 out:
513         return err;
514 }
515
516 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
517                                   struct ssb_boardinfo *bi)
518 {
519         pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
520                              &bi->vendor);
521         pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
522                              &bi->type);
523         pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
524                              &bi->rev);
525 }
526
527 int ssb_pci_get_invariants(struct ssb_bus *bus,
528                            struct ssb_init_invariants *iv)
529 {
530         int err;
531
532         err = ssb_pci_sprom_get(bus, &iv->sprom);
533         if (err)
534                 goto out;
535         ssb_pci_get_boardinfo(bus, &iv->boardinfo);
536
537 out:
538         return err;
539 }
540
541 #ifdef CONFIG_SSB_DEBUG
542 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
543 {
544         if (likely(bus->powered_up))
545                 return 0;
546
547         printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
548                "while accessing PCI MMIO space\n");
549         if (bus->power_warn_count <= 10) {
550                 bus->power_warn_count++;
551                 dump_stack();
552         }
553
554         return -ENODEV;
555 }
556 #else /* DEBUG */
557 static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
558 {
559         return 0;
560 }
561 #endif /* DEBUG */
562
563 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
564 {
565         struct ssb_bus *bus = dev->bus;
566
567         if (unlikely(ssb_pci_assert_buspower(bus)))
568                 return 0xFFFF;
569         if (unlikely(bus->mapped_device != dev)) {
570                 if (unlikely(ssb_pci_switch_core(bus, dev)))
571                         return 0xFFFF;
572         }
573         return ioread16(bus->mmio + offset);
574 }
575
576 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
577 {
578         struct ssb_bus *bus = dev->bus;
579
580         if (unlikely(ssb_pci_assert_buspower(bus)))
581                 return 0xFFFFFFFF;
582         if (unlikely(bus->mapped_device != dev)) {
583                 if (unlikely(ssb_pci_switch_core(bus, dev)))
584                         return 0xFFFFFFFF;
585         }
586         return ioread32(bus->mmio + offset);
587 }
588
589 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
590 {
591         struct ssb_bus *bus = dev->bus;
592
593         if (unlikely(ssb_pci_assert_buspower(bus)))
594                 return;
595         if (unlikely(bus->mapped_device != dev)) {
596                 if (unlikely(ssb_pci_switch_core(bus, dev)))
597                         return;
598         }
599         iowrite16(value, bus->mmio + offset);
600 }
601
602 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
603 {
604         struct ssb_bus *bus = dev->bus;
605
606         if (unlikely(ssb_pci_assert_buspower(bus)))
607                 return;
608         if (unlikely(bus->mapped_device != dev)) {
609                 if (unlikely(ssb_pci_switch_core(bus, dev)))
610                         return;
611         }
612         iowrite32(value, bus->mmio + offset);
613 }
614
615 /* Not "static", as it's used in main.c */
616 const struct ssb_bus_ops ssb_pci_ops = {
617         .read16         = ssb_pci_read16,
618         .read32         = ssb_pci_read32,
619         .write16        = ssb_pci_write16,
620         .write32        = ssb_pci_write32,
621 };
622
623 static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size)
624 {
625         int i, pos = 0;
626
627         for (i = 0; i < size; i++)
628                 pos += snprintf(buf + pos, buf_len - pos - 1,
629                                 "%04X", swab16(sprom[i]) & 0xFFFF);
630         pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
631
632         return pos + 1;
633 }
634
635 static int hex2sprom(u16 *sprom, const char *dump, size_t len, u16 size)
636 {
637         char tmp[5] = { 0 };
638         int cnt = 0;
639         unsigned long parsed;
640
641         if (len < size * 2)
642                 return -EINVAL;
643
644         while (cnt < size) {
645                 memcpy(tmp, dump, 4);
646                 dump += 4;
647                 parsed = simple_strtoul(tmp, NULL, 16);
648                 sprom[cnt++] = swab16((u16)parsed);
649         }
650
651         return 0;
652 }
653
654 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
655                                        struct device_attribute *attr,
656                                        char *buf)
657 {
658         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
659         struct ssb_bus *bus;
660         u16 *sprom;
661         int err = -ENODEV;
662         ssize_t count = 0;
663
664         bus = ssb_pci_dev_to_bus(pdev);
665         if (!bus)
666                 goto out;
667         err = -ENOMEM;
668         sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
669         if (!sprom)
670                 goto out;
671
672         /* Use interruptible locking, as the SPROM write might
673          * be holding the lock for several seconds. So allow userspace
674          * to cancel operation. */
675         err = -ERESTARTSYS;
676         if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
677                 goto out_kfree;
678         sprom_do_read(bus, sprom);
679         mutex_unlock(&bus->pci_sprom_mutex);
680
681         count = sprom2hex(sprom, buf, PAGE_SIZE, bus->sprom_size);
682         err = 0;
683
684 out_kfree:
685         kfree(sprom);
686 out:
687         return err ? err : count;
688 }
689
690 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
691                                         struct device_attribute *attr,
692                                         const char *buf, size_t count)
693 {
694         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
695         struct ssb_bus *bus;
696         u16 *sprom;
697         int res = 0, err = -ENODEV;
698
699         bus = ssb_pci_dev_to_bus(pdev);
700         if (!bus)
701                 goto out;
702         err = -ENOMEM;
703         sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
704         if (!sprom)
705                 goto out;
706         err = hex2sprom(sprom, buf, count, bus->sprom_size);
707         if (err) {
708                 err = -EINVAL;
709                 goto out_kfree;
710         }
711         err = sprom_check_crc(sprom, bus->sprom_size);
712         if (err) {
713                 err = -EINVAL;
714                 goto out_kfree;
715         }
716
717         /* Use interruptible locking, as the SPROM write might
718          * be holding the lock for several seconds. So allow userspace
719          * to cancel operation. */
720         err = -ERESTARTSYS;
721         if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
722                 goto out_kfree;
723         err = ssb_devices_freeze(bus);
724         if (err == -EOPNOTSUPP) {
725                 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
726                            "No suspend support. Is CONFIG_PM enabled?\n");
727                 goto out_unlock;
728         }
729         if (err) {
730                 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
731                 goto out_unlock;
732         }
733         res = sprom_do_write(bus, sprom);
734         err = ssb_devices_thaw(bus);
735         if (err)
736                 ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
737 out_unlock:
738         mutex_unlock(&bus->pci_sprom_mutex);
739 out_kfree:
740         kfree(sprom);
741 out:
742         if (res)
743                 return res;
744         return err ? err : count;
745 }
746
747 static DEVICE_ATTR(ssb_sprom, 0600,
748                    ssb_pci_attr_sprom_show,
749                    ssb_pci_attr_sprom_store);
750
751 void ssb_pci_exit(struct ssb_bus *bus)
752 {
753         struct pci_dev *pdev;
754
755         if (bus->bustype != SSB_BUSTYPE_PCI)
756                 return;
757
758         pdev = bus->host_pci;
759         device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
760 }
761
762 int ssb_pci_init(struct ssb_bus *bus)
763 {
764         struct pci_dev *pdev;
765         int err;
766
767         if (bus->bustype != SSB_BUSTYPE_PCI)
768                 return 0;
769
770         pdev = bus->host_pci;
771         mutex_init(&bus->pci_sprom_mutex);
772         err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
773         if (err)
774                 goto out;
775
776 out:
777         return err;
778 }