xref: /openbmc/linux/drivers/ssb/pci.c (revision 609e478b)
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 			} else {
913 				ssb_dbg("Using SPROM revision %d provided by platform\n",
914 					sprom->revision);
915 				err = 0;
916 				goto out_free;
917 			}
918 			ssb_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 #ifdef CONFIG_SSB_DEBUG
950 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
951 {
952 	if (likely(bus->powered_up))
953 		return 0;
954 
955 	printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
956 	       "while accessing PCI MMIO space\n");
957 	if (bus->power_warn_count <= 10) {
958 		bus->power_warn_count++;
959 		dump_stack();
960 	}
961 
962 	return -ENODEV;
963 }
964 #else /* DEBUG */
965 static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
966 {
967 	return 0;
968 }
969 #endif /* DEBUG */
970 
971 static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
972 {
973 	struct ssb_bus *bus = dev->bus;
974 
975 	if (unlikely(ssb_pci_assert_buspower(bus)))
976 		return 0xFF;
977 	if (unlikely(bus->mapped_device != dev)) {
978 		if (unlikely(ssb_pci_switch_core(bus, dev)))
979 			return 0xFF;
980 	}
981 	return ioread8(bus->mmio + offset);
982 }
983 
984 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
985 {
986 	struct ssb_bus *bus = dev->bus;
987 
988 	if (unlikely(ssb_pci_assert_buspower(bus)))
989 		return 0xFFFF;
990 	if (unlikely(bus->mapped_device != dev)) {
991 		if (unlikely(ssb_pci_switch_core(bus, dev)))
992 			return 0xFFFF;
993 	}
994 	return ioread16(bus->mmio + offset);
995 }
996 
997 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
998 {
999 	struct ssb_bus *bus = dev->bus;
1000 
1001 	if (unlikely(ssb_pci_assert_buspower(bus)))
1002 		return 0xFFFFFFFF;
1003 	if (unlikely(bus->mapped_device != dev)) {
1004 		if (unlikely(ssb_pci_switch_core(bus, dev)))
1005 			return 0xFFFFFFFF;
1006 	}
1007 	return ioread32(bus->mmio + offset);
1008 }
1009 
1010 #ifdef CONFIG_SSB_BLOCKIO
1011 static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
1012 			       size_t count, u16 offset, u8 reg_width)
1013 {
1014 	struct ssb_bus *bus = dev->bus;
1015 	void __iomem *addr = bus->mmio + offset;
1016 
1017 	if (unlikely(ssb_pci_assert_buspower(bus)))
1018 		goto error;
1019 	if (unlikely(bus->mapped_device != dev)) {
1020 		if (unlikely(ssb_pci_switch_core(bus, dev)))
1021 			goto error;
1022 	}
1023 	switch (reg_width) {
1024 	case sizeof(u8):
1025 		ioread8_rep(addr, buffer, count);
1026 		break;
1027 	case sizeof(u16):
1028 		SSB_WARN_ON(count & 1);
1029 		ioread16_rep(addr, buffer, count >> 1);
1030 		break;
1031 	case sizeof(u32):
1032 		SSB_WARN_ON(count & 3);
1033 		ioread32_rep(addr, buffer, count >> 2);
1034 		break;
1035 	default:
1036 		SSB_WARN_ON(1);
1037 	}
1038 
1039 	return;
1040 error:
1041 	memset(buffer, 0xFF, count);
1042 }
1043 #endif /* CONFIG_SSB_BLOCKIO */
1044 
1045 static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
1046 {
1047 	struct ssb_bus *bus = dev->bus;
1048 
1049 	if (unlikely(ssb_pci_assert_buspower(bus)))
1050 		return;
1051 	if (unlikely(bus->mapped_device != dev)) {
1052 		if (unlikely(ssb_pci_switch_core(bus, dev)))
1053 			return;
1054 	}
1055 	iowrite8(value, bus->mmio + offset);
1056 }
1057 
1058 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
1059 {
1060 	struct ssb_bus *bus = dev->bus;
1061 
1062 	if (unlikely(ssb_pci_assert_buspower(bus)))
1063 		return;
1064 	if (unlikely(bus->mapped_device != dev)) {
1065 		if (unlikely(ssb_pci_switch_core(bus, dev)))
1066 			return;
1067 	}
1068 	iowrite16(value, bus->mmio + offset);
1069 }
1070 
1071 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
1072 {
1073 	struct ssb_bus *bus = dev->bus;
1074 
1075 	if (unlikely(ssb_pci_assert_buspower(bus)))
1076 		return;
1077 	if (unlikely(bus->mapped_device != dev)) {
1078 		if (unlikely(ssb_pci_switch_core(bus, dev)))
1079 			return;
1080 	}
1081 	iowrite32(value, bus->mmio + offset);
1082 }
1083 
1084 #ifdef CONFIG_SSB_BLOCKIO
1085 static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1086 				size_t count, u16 offset, u8 reg_width)
1087 {
1088 	struct ssb_bus *bus = dev->bus;
1089 	void __iomem *addr = bus->mmio + offset;
1090 
1091 	if (unlikely(ssb_pci_assert_buspower(bus)))
1092 		return;
1093 	if (unlikely(bus->mapped_device != dev)) {
1094 		if (unlikely(ssb_pci_switch_core(bus, dev)))
1095 			return;
1096 	}
1097 	switch (reg_width) {
1098 	case sizeof(u8):
1099 		iowrite8_rep(addr, buffer, count);
1100 		break;
1101 	case sizeof(u16):
1102 		SSB_WARN_ON(count & 1);
1103 		iowrite16_rep(addr, buffer, count >> 1);
1104 		break;
1105 	case sizeof(u32):
1106 		SSB_WARN_ON(count & 3);
1107 		iowrite32_rep(addr, buffer, count >> 2);
1108 		break;
1109 	default:
1110 		SSB_WARN_ON(1);
1111 	}
1112 }
1113 #endif /* CONFIG_SSB_BLOCKIO */
1114 
1115 /* Not "static", as it's used in main.c */
1116 const struct ssb_bus_ops ssb_pci_ops = {
1117 	.read8		= ssb_pci_read8,
1118 	.read16		= ssb_pci_read16,
1119 	.read32		= ssb_pci_read32,
1120 	.write8		= ssb_pci_write8,
1121 	.write16	= ssb_pci_write16,
1122 	.write32	= ssb_pci_write32,
1123 #ifdef CONFIG_SSB_BLOCKIO
1124 	.block_read	= ssb_pci_block_read,
1125 	.block_write	= ssb_pci_block_write,
1126 #endif
1127 };
1128 
1129 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
1130 				       struct device_attribute *attr,
1131 				       char *buf)
1132 {
1133 	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1134 	struct ssb_bus *bus;
1135 
1136 	bus = ssb_pci_dev_to_bus(pdev);
1137 	if (!bus)
1138 		return -ENODEV;
1139 
1140 	return ssb_attr_sprom_show(bus, buf, sprom_do_read);
1141 }
1142 
1143 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
1144 					struct device_attribute *attr,
1145 					const char *buf, size_t count)
1146 {
1147 	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1148 	struct ssb_bus *bus;
1149 
1150 	bus = ssb_pci_dev_to_bus(pdev);
1151 	if (!bus)
1152 		return -ENODEV;
1153 
1154 	return ssb_attr_sprom_store(bus, buf, count,
1155 				    sprom_check_crc, sprom_do_write);
1156 }
1157 
1158 static DEVICE_ATTR(ssb_sprom, 0600,
1159 		   ssb_pci_attr_sprom_show,
1160 		   ssb_pci_attr_sprom_store);
1161 
1162 void ssb_pci_exit(struct ssb_bus *bus)
1163 {
1164 	struct pci_dev *pdev;
1165 
1166 	if (bus->bustype != SSB_BUSTYPE_PCI)
1167 		return;
1168 
1169 	pdev = bus->host_pci;
1170 	device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1171 }
1172 
1173 int ssb_pci_init(struct ssb_bus *bus)
1174 {
1175 	struct pci_dev *pdev;
1176 	int err;
1177 
1178 	if (bus->bustype != SSB_BUSTYPE_PCI)
1179 		return 0;
1180 
1181 	pdev = bus->host_pci;
1182 	mutex_init(&bus->sprom_mutex);
1183 	err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1184 	if (err)
1185 		goto out;
1186 
1187 out:
1188 	return err;
1189 }
1190