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