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