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