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