xref: /linux/drivers/ssb/pci.c (revision 24bce201d79807b668bf9d9e0aca801c5c0d5f78)
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 		msleep(20);
309 	}
310 	err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
311 	if (err)
312 		goto err_ctlreg;
313 	spromctl &= ~SSB_SPROMCTL_WE;
314 	err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
315 	if (err)
316 		goto err_ctlreg;
317 	msleep(500);
318 	pr_cont("100%% ]\n");
319 	pr_notice("SPROM written\n");
320 
321 	return 0;
322 err_ctlreg:
323 	pr_err("Could not access SPROM control register.\n");
324 	return err;
325 }
326 
327 static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset,
328 				u16 mask, u16 shift)
329 {
330 	u16 v;
331 	u8 gain;
332 
333 	v = in[SPOFF(offset)];
334 	gain = (v & mask) >> shift;
335 	if (gain == 0xFF)
336 		gain = 2; /* If unset use 2dBm */
337 	if (sprom_revision == 1) {
338 		/* Convert to Q5.2 */
339 		gain <<= 2;
340 	} else {
341 		/* Q5.2 Fractional part is stored in 0xC0 */
342 		gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
343 	}
344 
345 	return (s8)gain;
346 }
347 
348 static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in)
349 {
350 	SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
351 	SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
352 	SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
353 	SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
354 	SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
355 	SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
356 	SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
357 	SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
358 	SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
359 	SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
360 	     SSB_SPROM2_MAXP_A_LO_SHIFT);
361 }
362 
363 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
364 {
365 	u16 loc[3];
366 
367 	if (out->revision == 3)			/* rev 3 moved MAC */
368 		loc[0] = SSB_SPROM3_IL0MAC;
369 	else {
370 		loc[0] = SSB_SPROM1_IL0MAC;
371 		loc[1] = SSB_SPROM1_ET0MAC;
372 		loc[2] = SSB_SPROM1_ET1MAC;
373 	}
374 	sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
375 	if (out->revision < 3) { 	/* only rev 1-2 have et0, et1 */
376 		sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
377 		sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
378 	}
379 	SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
380 	SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
381 	     SSB_SPROM1_ETHPHY_ET1A_SHIFT);
382 	SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
383 	SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
384 	SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
385 	SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
386 	if (out->revision == 1)
387 		SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
388 		     SSB_SPROM1_BINF_CCODE_SHIFT);
389 	SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
390 	     SSB_SPROM1_BINF_ANTA_SHIFT);
391 	SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
392 	     SSB_SPROM1_BINF_ANTBG_SHIFT);
393 	SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
394 	SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
395 	SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
396 	SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
397 	SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
398 	SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
399 	SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
400 	SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
401 	     SSB_SPROM1_GPIOA_P1_SHIFT);
402 	SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
403 	SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
404 	     SSB_SPROM1_GPIOB_P3_SHIFT);
405 	SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
406 	     SSB_SPROM1_MAXPWR_A_SHIFT);
407 	SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
408 	SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
409 	     SSB_SPROM1_ITSSI_A_SHIFT);
410 	SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
411 	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
412 
413 	SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
414 	SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
415 
416 	/* Extract the antenna gain values. */
417 	out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
418 						     SSB_SPROM1_AGAIN,
419 						     SSB_SPROM1_AGAIN_BG,
420 						     SSB_SPROM1_AGAIN_BG_SHIFT);
421 	out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
422 						     SSB_SPROM1_AGAIN,
423 						     SSB_SPROM1_AGAIN_A,
424 						     SSB_SPROM1_AGAIN_A_SHIFT);
425 	if (out->revision >= 2)
426 		sprom_extract_r23(out, in);
427 }
428 
429 /* Revs 4 5 and 8 have partially shared layout */
430 static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
431 {
432 	SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
433 	     SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
434 	SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
435 	     SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
436 	SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
437 	     SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
438 	SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
439 	     SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
440 
441 	SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
442 	     SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
443 	SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
444 	     SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
445 	SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
446 	     SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
447 	SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
448 	     SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
449 
450 	SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
451 	     SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
452 	SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
453 	     SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
454 	SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
455 	     SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
456 	SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
457 	     SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
458 
459 	SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
460 	     SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
461 	SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
462 	     SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
463 	SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
464 	     SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
465 	SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
466 	     SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
467 }
468 
469 static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
470 {
471 	static const u16 pwr_info_offset[] = {
472 		SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1,
473 		SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3
474 	};
475 	u16 il0mac_offset;
476 	int i;
477 
478 	BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
479 		     ARRAY_SIZE(out->core_pwr_info));
480 
481 	if (out->revision == 4)
482 		il0mac_offset = SSB_SPROM4_IL0MAC;
483 	else
484 		il0mac_offset = SSB_SPROM5_IL0MAC;
485 
486 	sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
487 
488 	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
489 	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
490 	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
491 	SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
492 	SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
493 	if (out->revision == 4) {
494 		SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
495 		SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
496 		SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
497 		SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
498 		SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
499 		SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
500 	} else {
501 		SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
502 		SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
503 		SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
504 		SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
505 		SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
506 		SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
507 	}
508 	SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
509 	     SSB_SPROM4_ANTAVAIL_A_SHIFT);
510 	SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
511 	     SSB_SPROM4_ANTAVAIL_BG_SHIFT);
512 	SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
513 	SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
514 	     SSB_SPROM4_ITSSI_BG_SHIFT);
515 	SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
516 	SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
517 	     SSB_SPROM4_ITSSI_A_SHIFT);
518 	if (out->revision == 4) {
519 		SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
520 		SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
521 		     SSB_SPROM4_GPIOA_P1_SHIFT);
522 		SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
523 		SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
524 		     SSB_SPROM4_GPIOB_P3_SHIFT);
525 	} else {
526 		SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
527 		SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
528 		     SSB_SPROM5_GPIOA_P1_SHIFT);
529 		SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
530 		SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
531 		     SSB_SPROM5_GPIOB_P3_SHIFT);
532 	}
533 
534 	/* Extract the antenna gain values. */
535 	out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
536 						     SSB_SPROM4_AGAIN01,
537 						     SSB_SPROM4_AGAIN0,
538 						     SSB_SPROM4_AGAIN0_SHIFT);
539 	out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
540 						     SSB_SPROM4_AGAIN01,
541 						     SSB_SPROM4_AGAIN1,
542 						     SSB_SPROM4_AGAIN1_SHIFT);
543 	out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
544 						     SSB_SPROM4_AGAIN23,
545 						     SSB_SPROM4_AGAIN2,
546 						     SSB_SPROM4_AGAIN2_SHIFT);
547 	out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
548 						     SSB_SPROM4_AGAIN23,
549 						     SSB_SPROM4_AGAIN3,
550 						     SSB_SPROM4_AGAIN3_SHIFT);
551 
552 	/* Extract cores power info info */
553 	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
554 		u16 o = pwr_info_offset[i];
555 
556 		SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
557 			SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT);
558 		SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
559 			SSB_SPROM4_2G_MAXP, 0);
560 
561 		SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0);
562 		SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0);
563 		SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0);
564 		SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0);
565 
566 		SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
567 			SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT);
568 		SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
569 			SSB_SPROM4_5G_MAXP, 0);
570 		SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP,
571 			SSB_SPROM4_5GH_MAXP, 0);
572 		SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP,
573 			SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT);
574 
575 		SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0);
576 		SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0);
577 		SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0);
578 		SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0);
579 		SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0);
580 		SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0);
581 		SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0);
582 		SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0);
583 		SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0);
584 		SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0);
585 		SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0);
586 		SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0);
587 	}
588 
589 	sprom_extract_r458(out, in);
590 
591 	/* TODO - get remaining rev 4 stuff needed */
592 }
593 
594 static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
595 {
596 	int i;
597 	u16 o;
598 	static const u16 pwr_info_offset[] = {
599 		SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
600 		SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
601 	};
602 	BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
603 			ARRAY_SIZE(out->core_pwr_info));
604 
605 	/* extract the MAC address */
606 	sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
607 
608 	SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
609 	SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
610 	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
611 	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
612 	SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
613 	SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
614 	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
615 	SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
616 	SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
617 	     SSB_SPROM8_ANTAVAIL_A_SHIFT);
618 	SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
619 	     SSB_SPROM8_ANTAVAIL_BG_SHIFT);
620 	SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
621 	SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
622 	     SSB_SPROM8_ITSSI_BG_SHIFT);
623 	SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
624 	SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
625 	     SSB_SPROM8_ITSSI_A_SHIFT);
626 	SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
627 	SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
628 	     SSB_SPROM8_MAXP_AL_SHIFT);
629 	SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
630 	SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
631 	     SSB_SPROM8_GPIOA_P1_SHIFT);
632 	SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
633 	SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
634 	     SSB_SPROM8_GPIOB_P3_SHIFT);
635 	SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
636 	SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
637 	     SSB_SPROM8_TRI5G_SHIFT);
638 	SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
639 	SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
640 	     SSB_SPROM8_TRI5GH_SHIFT);
641 	SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
642 	SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
643 	     SSB_SPROM8_RXPO5G_SHIFT);
644 	SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
645 	SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
646 	     SSB_SPROM8_RSSISMC2G_SHIFT);
647 	SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
648 	     SSB_SPROM8_RSSISAV2G_SHIFT);
649 	SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
650 	     SSB_SPROM8_BXA2G_SHIFT);
651 	SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
652 	SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
653 	     SSB_SPROM8_RSSISMC5G_SHIFT);
654 	SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
655 	     SSB_SPROM8_RSSISAV5G_SHIFT);
656 	SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
657 	     SSB_SPROM8_BXA5G_SHIFT);
658 	SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
659 	SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
660 	SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
661 	SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
662 	SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
663 	SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
664 	SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
665 	SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
666 	SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
667 	SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
668 	SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
669 	SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
670 	SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
671 	SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
672 	SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
673 	SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
674 	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
675 
676 	/* Extract the antenna gain values. */
677 	out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
678 						     SSB_SPROM8_AGAIN01,
679 						     SSB_SPROM8_AGAIN0,
680 						     SSB_SPROM8_AGAIN0_SHIFT);
681 	out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
682 						     SSB_SPROM8_AGAIN01,
683 						     SSB_SPROM8_AGAIN1,
684 						     SSB_SPROM8_AGAIN1_SHIFT);
685 	out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
686 						     SSB_SPROM8_AGAIN23,
687 						     SSB_SPROM8_AGAIN2,
688 						     SSB_SPROM8_AGAIN2_SHIFT);
689 	out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
690 						     SSB_SPROM8_AGAIN23,
691 						     SSB_SPROM8_AGAIN3,
692 						     SSB_SPROM8_AGAIN3_SHIFT);
693 
694 	/* Extract cores power info info */
695 	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
696 		o = pwr_info_offset[i];
697 		SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
698 			SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
699 		SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
700 			SSB_SPROM8_2G_MAXP, 0);
701 
702 		SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
703 		SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
704 		SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
705 
706 		SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
707 			SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
708 		SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
709 			SSB_SPROM8_5G_MAXP, 0);
710 		SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
711 			SSB_SPROM8_5GH_MAXP, 0);
712 		SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
713 			SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
714 
715 		SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
716 		SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
717 		SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
718 		SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
719 		SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
720 		SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
721 		SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
722 		SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
723 		SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
724 	}
725 
726 	/* Extract FEM info */
727 	SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
728 		SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
729 	SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
730 		SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
731 	SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
732 		SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
733 	SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
734 		SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
735 	SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
736 		SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
737 
738 	SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
739 		SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
740 	SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
741 		SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
742 	SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
743 		SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
744 	SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
745 		SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
746 	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
747 		SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
748 
749 	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
750 	     SSB_SPROM8_LEDDC_ON_SHIFT);
751 	SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
752 	     SSB_SPROM8_LEDDC_OFF_SHIFT);
753 
754 	SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
755 	     SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
756 	SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
757 	     SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
758 	SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
759 	     SSB_SPROM8_TXRXC_SWITCH_SHIFT);
760 
761 	SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
762 
763 	SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
764 	SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
765 	SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
766 	SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
767 
768 	SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
769 	     SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
770 	SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
771 	     SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
772 	SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
773 	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
774 	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
775 	SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
776 	     SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
777 	SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
778 	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
779 	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
780 	SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
781 	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
782 	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
783 	SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
784 	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
785 	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
786 	SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
787 	     SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
788 
789 	SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
790 	SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
791 	SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
792 	SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
793 
794 	SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
795 	     SSB_SPROM8_THERMAL_TRESH_SHIFT);
796 	SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
797 	     SSB_SPROM8_THERMAL_OFFSET_SHIFT);
798 	SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
799 	     SSB_SPROM8_TEMPDELTA_PHYCAL,
800 	     SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
801 	SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
802 	     SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
803 	SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
804 	     SSB_SPROM8_TEMPDELTA_HYSTERESIS,
805 	     SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
806 	sprom_extract_r458(out, in);
807 
808 	/* TODO - get remaining rev 8 stuff needed */
809 }
810 
811 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
812 			 const u16 *in, u16 size)
813 {
814 	memset(out, 0, sizeof(*out));
815 
816 	out->revision = in[size - 1] & 0x00FF;
817 	pr_debug("SPROM revision %d detected\n", out->revision);
818 	memset(out->et0mac, 0xFF, 6);		/* preset et0 and et1 mac */
819 	memset(out->et1mac, 0xFF, 6);
820 
821 	if ((bus->chip_id & 0xFF00) == 0x4400) {
822 		/* Workaround: The BCM44XX chip has a stupid revision
823 		 * number stored in the SPROM.
824 		 * Always extract r1. */
825 		out->revision = 1;
826 		pr_debug("SPROM treated as revision %d\n", out->revision);
827 	}
828 
829 	switch (out->revision) {
830 	case 1:
831 	case 2:
832 	case 3:
833 		sprom_extract_r123(out, in);
834 		break;
835 	case 4:
836 	case 5:
837 		sprom_extract_r45(out, in);
838 		break;
839 	case 8:
840 		sprom_extract_r8(out, in);
841 		break;
842 	default:
843 		pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
844 			out->revision);
845 		out->revision = 1;
846 		sprom_extract_r123(out, in);
847 	}
848 
849 	if (out->boardflags_lo == 0xFFFF)
850 		out->boardflags_lo = 0;  /* per specs */
851 	if (out->boardflags_hi == 0xFFFF)
852 		out->boardflags_hi = 0;  /* per specs */
853 
854 	return 0;
855 }
856 
857 static int ssb_pci_sprom_get(struct ssb_bus *bus,
858 			     struct ssb_sprom *sprom)
859 {
860 	int err;
861 	u16 *buf;
862 
863 	if (!ssb_is_sprom_available(bus)) {
864 		pr_err("No SPROM available!\n");
865 		return -ENODEV;
866 	}
867 	if (bus->chipco.dev) {	/* can be unavailable! */
868 		/*
869 		 * get SPROM offset: SSB_SPROM_BASE1 except for
870 		 * chipcommon rev >= 31 or chip ID is 0x4312 and
871 		 * chipcommon status & 3 == 2
872 		 */
873 		if (bus->chipco.dev->id.revision >= 31)
874 			bus->sprom_offset = SSB_SPROM_BASE31;
875 		else if (bus->chip_id == 0x4312 &&
876 			 (bus->chipco.status & 0x03) == 2)
877 			bus->sprom_offset = SSB_SPROM_BASE31;
878 		else
879 			bus->sprom_offset = SSB_SPROM_BASE1;
880 	} else {
881 		bus->sprom_offset = SSB_SPROM_BASE1;
882 	}
883 	pr_debug("SPROM offset is 0x%x\n", bus->sprom_offset);
884 
885 	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
886 	if (!buf)
887 		return -ENOMEM;
888 	bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
889 	sprom_do_read(bus, buf);
890 	err = sprom_check_crc(buf, bus->sprom_size);
891 	if (err) {
892 		/* try for a 440 byte SPROM - revision 4 and higher */
893 		kfree(buf);
894 		buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
895 			      GFP_KERNEL);
896 		if (!buf)
897 			return -ENOMEM;
898 		bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
899 		sprom_do_read(bus, buf);
900 		err = sprom_check_crc(buf, bus->sprom_size);
901 		if (err) {
902 			/* All CRC attempts failed.
903 			 * Maybe there is no SPROM on the device?
904 			 * Now we ask the arch code if there is some sprom
905 			 * available for this device in some other storage */
906 			err = ssb_fill_sprom_with_fallback(bus, sprom);
907 			if (err) {
908 				pr_warn("WARNING: Using fallback SPROM failed (err %d)\n",
909 					err);
910 				goto out_free;
911 			} else {
912 				pr_debug("Using SPROM revision %d provided by platform\n",
913 					 sprom->revision);
914 				err = 0;
915 				goto out_free;
916 			}
917 		}
918 	}
919 	err = sprom_extract(bus, sprom, buf, bus->sprom_size);
920 
921 out_free:
922 	kfree(buf);
923 	return err;
924 }
925 
926 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
927 				  struct ssb_boardinfo *bi)
928 {
929 	bi->vendor = bus->host_pci->subsystem_vendor;
930 	bi->type = bus->host_pci->subsystem_device;
931 }
932 
933 int ssb_pci_get_invariants(struct ssb_bus *bus,
934 			   struct ssb_init_invariants *iv)
935 {
936 	int err;
937 
938 	err = ssb_pci_sprom_get(bus, &iv->sprom);
939 	if (err)
940 		goto out;
941 	ssb_pci_get_boardinfo(bus, &iv->boardinfo);
942 
943 out:
944 	return err;
945 }
946 
947 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
948 {
949 	if (likely(bus->powered_up))
950 		return 0;
951 
952 	pr_err("FATAL ERROR: Bus powered down while accessing PCI MMIO space\n");
953 	if (bus->power_warn_count <= 10) {
954 		bus->power_warn_count++;
955 		dump_stack();
956 	}
957 
958 	return -ENODEV;
959 }
960 
961 static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
962 {
963 	struct ssb_bus *bus = dev->bus;
964 
965 	if (unlikely(ssb_pci_assert_buspower(bus)))
966 		return 0xFF;
967 	if (unlikely(bus->mapped_device != dev)) {
968 		if (unlikely(ssb_pci_switch_core(bus, dev)))
969 			return 0xFF;
970 	}
971 	return ioread8(bus->mmio + offset);
972 }
973 
974 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
975 {
976 	struct ssb_bus *bus = dev->bus;
977 
978 	if (unlikely(ssb_pci_assert_buspower(bus)))
979 		return 0xFFFF;
980 	if (unlikely(bus->mapped_device != dev)) {
981 		if (unlikely(ssb_pci_switch_core(bus, dev)))
982 			return 0xFFFF;
983 	}
984 	return ioread16(bus->mmio + offset);
985 }
986 
987 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
988 {
989 	struct ssb_bus *bus = dev->bus;
990 
991 	if (unlikely(ssb_pci_assert_buspower(bus)))
992 		return 0xFFFFFFFF;
993 	if (unlikely(bus->mapped_device != dev)) {
994 		if (unlikely(ssb_pci_switch_core(bus, dev)))
995 			return 0xFFFFFFFF;
996 	}
997 	return ioread32(bus->mmio + offset);
998 }
999 
1000 #ifdef CONFIG_SSB_BLOCKIO
1001 static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
1002 			       size_t count, u16 offset, u8 reg_width)
1003 {
1004 	struct ssb_bus *bus = dev->bus;
1005 	void __iomem *addr = bus->mmio + offset;
1006 
1007 	if (unlikely(ssb_pci_assert_buspower(bus)))
1008 		goto error;
1009 	if (unlikely(bus->mapped_device != dev)) {
1010 		if (unlikely(ssb_pci_switch_core(bus, dev)))
1011 			goto error;
1012 	}
1013 	switch (reg_width) {
1014 	case sizeof(u8):
1015 		ioread8_rep(addr, buffer, count);
1016 		break;
1017 	case sizeof(u16):
1018 		WARN_ON(count & 1);
1019 		ioread16_rep(addr, buffer, count >> 1);
1020 		break;
1021 	case sizeof(u32):
1022 		WARN_ON(count & 3);
1023 		ioread32_rep(addr, buffer, count >> 2);
1024 		break;
1025 	default:
1026 		WARN_ON(1);
1027 	}
1028 
1029 	return;
1030 error:
1031 	memset(buffer, 0xFF, count);
1032 }
1033 #endif /* CONFIG_SSB_BLOCKIO */
1034 
1035 static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
1036 {
1037 	struct ssb_bus *bus = dev->bus;
1038 
1039 	if (unlikely(ssb_pci_assert_buspower(bus)))
1040 		return;
1041 	if (unlikely(bus->mapped_device != dev)) {
1042 		if (unlikely(ssb_pci_switch_core(bus, dev)))
1043 			return;
1044 	}
1045 	iowrite8(value, bus->mmio + offset);
1046 }
1047 
1048 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
1049 {
1050 	struct ssb_bus *bus = dev->bus;
1051 
1052 	if (unlikely(ssb_pci_assert_buspower(bus)))
1053 		return;
1054 	if (unlikely(bus->mapped_device != dev)) {
1055 		if (unlikely(ssb_pci_switch_core(bus, dev)))
1056 			return;
1057 	}
1058 	iowrite16(value, bus->mmio + offset);
1059 }
1060 
1061 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
1062 {
1063 	struct ssb_bus *bus = dev->bus;
1064 
1065 	if (unlikely(ssb_pci_assert_buspower(bus)))
1066 		return;
1067 	if (unlikely(bus->mapped_device != dev)) {
1068 		if (unlikely(ssb_pci_switch_core(bus, dev)))
1069 			return;
1070 	}
1071 	iowrite32(value, bus->mmio + offset);
1072 }
1073 
1074 #ifdef CONFIG_SSB_BLOCKIO
1075 static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1076 				size_t count, u16 offset, u8 reg_width)
1077 {
1078 	struct ssb_bus *bus = dev->bus;
1079 	void __iomem *addr = bus->mmio + offset;
1080 
1081 	if (unlikely(ssb_pci_assert_buspower(bus)))
1082 		return;
1083 	if (unlikely(bus->mapped_device != dev)) {
1084 		if (unlikely(ssb_pci_switch_core(bus, dev)))
1085 			return;
1086 	}
1087 	switch (reg_width) {
1088 	case sizeof(u8):
1089 		iowrite8_rep(addr, buffer, count);
1090 		break;
1091 	case sizeof(u16):
1092 		WARN_ON(count & 1);
1093 		iowrite16_rep(addr, buffer, count >> 1);
1094 		break;
1095 	case sizeof(u32):
1096 		WARN_ON(count & 3);
1097 		iowrite32_rep(addr, buffer, count >> 2);
1098 		break;
1099 	default:
1100 		WARN_ON(1);
1101 	}
1102 }
1103 #endif /* CONFIG_SSB_BLOCKIO */
1104 
1105 /* Not "static", as it's used in main.c */
1106 const struct ssb_bus_ops ssb_pci_ops = {
1107 	.read8		= ssb_pci_read8,
1108 	.read16		= ssb_pci_read16,
1109 	.read32		= ssb_pci_read32,
1110 	.write8		= ssb_pci_write8,
1111 	.write16	= ssb_pci_write16,
1112 	.write32	= ssb_pci_write32,
1113 #ifdef CONFIG_SSB_BLOCKIO
1114 	.block_read	= ssb_pci_block_read,
1115 	.block_write	= ssb_pci_block_write,
1116 #endif
1117 };
1118 
1119 static ssize_t ssb_sprom_show(struct device *pcidev,
1120 			      struct device_attribute *attr,
1121 			      char *buf)
1122 {
1123 	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1124 	struct ssb_bus *bus;
1125 
1126 	bus = ssb_pci_dev_to_bus(pdev);
1127 	if (!bus)
1128 		return -ENODEV;
1129 
1130 	return ssb_attr_sprom_show(bus, buf, sprom_do_read);
1131 }
1132 
1133 static ssize_t ssb_sprom_store(struct device *pcidev,
1134 			       struct device_attribute *attr,
1135 			       const char *buf, size_t count)
1136 {
1137 	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1138 	struct ssb_bus *bus;
1139 
1140 	bus = ssb_pci_dev_to_bus(pdev);
1141 	if (!bus)
1142 		return -ENODEV;
1143 
1144 	return ssb_attr_sprom_store(bus, buf, count,
1145 				    sprom_check_crc, sprom_do_write);
1146 }
1147 
1148 static DEVICE_ATTR_ADMIN_RW(ssb_sprom);
1149 
1150 void ssb_pci_exit(struct ssb_bus *bus)
1151 {
1152 	struct pci_dev *pdev;
1153 
1154 	if (bus->bustype != SSB_BUSTYPE_PCI)
1155 		return;
1156 
1157 	pdev = bus->host_pci;
1158 	device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1159 }
1160 
1161 int ssb_pci_init(struct ssb_bus *bus)
1162 {
1163 	struct pci_dev *pdev;
1164 
1165 	if (bus->bustype != SSB_BUSTYPE_PCI)
1166 		return 0;
1167 
1168 	pdev = bus->host_pci;
1169 	mutex_init(&bus->sprom_mutex);
1170 
1171 	return device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1172 }
1173