xref: /openbmc/linux/drivers/ssb/pci.c (revision a1e58bbd)
1 /*
2  * Sonics Silicon Backplane PCI-Hostbus related functions.
3  *
4  * Copyright (C) 2005-2006 Michael Buesch <mb@bu3sch.de>
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/pci.h>
21 #include <linux/delay.h>
22 
23 #include "ssb_private.h"
24 
25 
26 /* Define the following to 1 to enable a printk on each coreswitch. */
27 #define SSB_VERBOSE_PCICORESWITCH_DEBUG		0
28 
29 
30 /* Lowlevel coreswitching */
31 int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
32 {
33 	int err;
34 	int attempts = 0;
35 	u32 cur_core;
36 
37 	while (1) {
38 		err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
39 					     (coreidx * SSB_CORE_SIZE)
40 					     + SSB_ENUM_BASE);
41 		if (err)
42 			goto error;
43 		err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
44 					    &cur_core);
45 		if (err)
46 			goto error;
47 		cur_core = (cur_core - SSB_ENUM_BASE)
48 			   / SSB_CORE_SIZE;
49 		if (cur_core == coreidx)
50 			break;
51 
52 		if (attempts++ > SSB_BAR0_MAX_RETRIES)
53 			goto error;
54 		udelay(10);
55 	}
56 	return 0;
57 error:
58 	ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
59 	return -ENODEV;
60 }
61 
62 int ssb_pci_switch_core(struct ssb_bus *bus,
63 			struct ssb_device *dev)
64 {
65 	int err;
66 	unsigned long flags;
67 
68 #if SSB_VERBOSE_PCICORESWITCH_DEBUG
69 	ssb_printk(KERN_INFO PFX
70 		   "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) - SSB_SPROM_BASE) / sizeof(u16))
171 /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
172 #define SPEX(_outvar, _offset, _mask, _shift)	\
173 	out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
174 
175 static inline u8 ssb_crc8(u8 crc, u8 data)
176 {
177 	/* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
178 	static const u8 t[] = {
179 		0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
180 		0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
181 		0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
182 		0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
183 		0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
184 		0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
185 		0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
186 		0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
187 		0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
188 		0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
189 		0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
190 		0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
191 		0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
192 		0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
193 		0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
194 		0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
195 		0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
196 		0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
197 		0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
198 		0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
199 		0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
200 		0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
201 		0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
202 		0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
203 		0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
204 		0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
205 		0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
206 		0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
207 		0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
208 		0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
209 		0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
210 		0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
211 	};
212 	return t[crc ^ data];
213 }
214 
215 static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
216 {
217 	int word;
218 	u8 crc = 0xFF;
219 
220 	for (word = 0; word < size - 1; word++) {
221 		crc = ssb_crc8(crc, sprom[word] & 0x00FF);
222 		crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
223 	}
224 	crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
225 	crc ^= 0xFF;
226 
227 	return crc;
228 }
229 
230 static int sprom_check_crc(const u16 *sprom, u16 size)
231 {
232 	u8 crc;
233 	u8 expected_crc;
234 	u16 tmp;
235 
236 	crc = ssb_sprom_crc(sprom, size);
237 	tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
238 	expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
239 	if (crc != expected_crc)
240 		return -EPROTO;
241 
242 	return 0;
243 }
244 
245 static void sprom_do_read(struct ssb_bus *bus, u16 *sprom)
246 {
247 	int i;
248 
249 	for (i = 0; i < bus->sprom_size; i++)
250 		sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
251 }
252 
253 static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
254 {
255 	struct pci_dev *pdev = bus->host_pci;
256 	int i, err;
257 	u32 spromctl;
258 	u16 size = bus->sprom_size;
259 
260 	ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
261 	err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
262 	if (err)
263 		goto err_ctlreg;
264 	spromctl |= SSB_SPROMCTL_WE;
265 	err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
266 	if (err)
267 		goto err_ctlreg;
268 	ssb_printk(KERN_NOTICE PFX "[ 0%%");
269 	msleep(500);
270 	for (i = 0; i < size; i++) {
271 		if (i == size / 4)
272 			ssb_printk("25%%");
273 		else if (i == size / 2)
274 			ssb_printk("50%%");
275 		else if (i == (size * 3) / 4)
276 			ssb_printk("75%%");
277 		else if (i % 2)
278 			ssb_printk(".");
279 		writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2));
280 		mmiowb();
281 		msleep(20);
282 	}
283 	err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
284 	if (err)
285 		goto err_ctlreg;
286 	spromctl &= ~SSB_SPROMCTL_WE;
287 	err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
288 	if (err)
289 		goto err_ctlreg;
290 	msleep(500);
291 	ssb_printk("100%% ]\n");
292 	ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
293 
294 	return 0;
295 err_ctlreg:
296 	ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
297 	return err;
298 }
299 
300 static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
301 			       u16 mask, u16 shift)
302 {
303 	u16 v;
304 	u8 gain;
305 
306 	v = in[SPOFF(SSB_SPROM1_AGAIN)];
307 	gain = (v & mask) >> shift;
308 	if (gain == 0xFF)
309 		gain = 2; /* If unset use 2dBm */
310 	if (sprom_revision == 1) {
311 		/* Convert to Q5.2 */
312 		gain <<= 2;
313 	} else {
314 		/* Q5.2 Fractional part is stored in 0xC0 */
315 		gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
316 	}
317 
318 	return (s8)gain;
319 }
320 
321 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
322 {
323 	int i;
324 	u16 v;
325 	s8 gain;
326 	u16 loc[3];
327 
328 	if (out->revision == 3) {			/* rev 3 moved MAC */
329 		loc[0] = SSB_SPROM3_IL0MAC;
330 		loc[1] = SSB_SPROM3_ET0MAC;
331 		loc[2] = SSB_SPROM3_ET1MAC;
332 	} else {
333 		loc[0] = SSB_SPROM1_IL0MAC;
334 		loc[1] = SSB_SPROM1_ET0MAC;
335 		loc[2] = SSB_SPROM1_ET1MAC;
336 	}
337 	for (i = 0; i < 3; i++) {
338 		v = in[SPOFF(loc[0]) + i];
339 		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
340 	}
341 	for (i = 0; i < 3; i++) {
342 		v = in[SPOFF(loc[1]) + i];
343 		*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
344 	}
345 	for (i = 0; i < 3; i++) {
346 		v = in[SPOFF(loc[2]) + i];
347 		*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
348 	}
349 	SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
350 	SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
351 	     SSB_SPROM1_ETHPHY_ET1A_SHIFT);
352 	SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
353 	SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
354 	SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
355 	SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
356 	     SSB_SPROM1_BINF_CCODE_SHIFT);
357 	SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
358 	     SSB_SPROM1_BINF_ANTA_SHIFT);
359 	SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
360 	     SSB_SPROM1_BINF_ANTBG_SHIFT);
361 	SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
362 	SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
363 	SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
364 	SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
365 	SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
366 	SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
367 	SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
368 	SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
369 	     SSB_SPROM1_GPIOA_P1_SHIFT);
370 	SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
371 	SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
372 	     SSB_SPROM1_GPIOB_P3_SHIFT);
373 	SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
374 	     SSB_SPROM1_MAXPWR_A_SHIFT);
375 	SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
376 	SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
377 	     SSB_SPROM1_ITSSI_A_SHIFT);
378 	SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
379 	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
380 	if (out->revision >= 2)
381 		SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
382 
383 	/* Extract the antenna gain values. */
384 	gain = r123_extract_antgain(out->revision, in,
385 				    SSB_SPROM1_AGAIN_BG,
386 				    SSB_SPROM1_AGAIN_BG_SHIFT);
387 	out->antenna_gain.ghz24.a0 = gain;
388 	out->antenna_gain.ghz24.a1 = gain;
389 	out->antenna_gain.ghz24.a2 = gain;
390 	out->antenna_gain.ghz24.a3 = gain;
391 	gain = r123_extract_antgain(out->revision, in,
392 				    SSB_SPROM1_AGAIN_A,
393 				    SSB_SPROM1_AGAIN_A_SHIFT);
394 	out->antenna_gain.ghz5.a0 = gain;
395 	out->antenna_gain.ghz5.a1 = gain;
396 	out->antenna_gain.ghz5.a2 = gain;
397 	out->antenna_gain.ghz5.a3 = gain;
398 }
399 
400 static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in)
401 {
402 	int i;
403 	u16 v;
404 
405 	/* extract the equivalent of the r1 variables */
406 	for (i = 0; i < 3; i++) {
407 		v = in[SPOFF(SSB_SPROM4_IL0MAC) + i];
408 		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
409 	}
410 	for (i = 0; i < 3; i++) {
411 		v = in[SPOFF(SSB_SPROM4_ET0MAC) + i];
412 		*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
413 	}
414 	for (i = 0; i < 3; i++) {
415 		v = in[SPOFF(SSB_SPROM4_ET1MAC) + i];
416 		*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
417 	}
418 	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
419 	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
420 	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
421 	SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
422 	SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
423 	SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
424 	SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
425 	     SSB_SPROM4_ANTAVAIL_A_SHIFT);
426 	SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
427 	     SSB_SPROM4_ANTAVAIL_BG_SHIFT);
428 	SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
429 	SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
430 	     SSB_SPROM4_ITSSI_BG_SHIFT);
431 	SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
432 	SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
433 	     SSB_SPROM4_ITSSI_A_SHIFT);
434 	SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
435 	SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
436 	     SSB_SPROM4_GPIOA_P1_SHIFT);
437 	SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
438 	SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
439 	     SSB_SPROM4_GPIOB_P3_SHIFT);
440 
441 	/* Extract the antenna gain values. */
442 	SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
443 	     SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
444 	SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
445 	     SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
446 	SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
447 	     SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
448 	SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
449 	     SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
450 	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
451 	       sizeof(out->antenna_gain.ghz5));
452 
453 	/* TODO - get remaining rev 4 stuff needed */
454 }
455 
456 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
457 			 const u16 *in, u16 size)
458 {
459 	memset(out, 0, sizeof(*out));
460 
461 	out->revision = in[size - 1] & 0x00FF;
462 	ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
463 	if ((bus->chip_id & 0xFF00) == 0x4400) {
464 		/* Workaround: The BCM44XX chip has a stupid revision
465 		 * number stored in the SPROM.
466 		 * Always extract r1. */
467 		out->revision = 1;
468 		sprom_extract_r123(out, in);
469 	} else if (bus->chip_id == 0x4321) {
470 		/* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
471 		out->revision = 4;
472 		sprom_extract_r4(out, in);
473 	} else {
474 		if (out->revision == 0)
475 			goto unsupported;
476 		if (out->revision >= 1 && out->revision <= 3) {
477 			sprom_extract_r123(out, in);
478 		}
479 		if (out->revision == 4)
480 			sprom_extract_r4(out, in);
481 		if (out->revision >= 5)
482 			goto unsupported;
483 	}
484 
485 	return 0;
486 unsupported:
487 	ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
488 		   "detected. Will extract v1\n", out->revision);
489 	sprom_extract_r123(out, in);
490 	return 0;
491 }
492 
493 static int ssb_pci_sprom_get(struct ssb_bus *bus,
494 			     struct ssb_sprom *sprom)
495 {
496 	int err = -ENOMEM;
497 	u16 *buf;
498 
499 	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
500 	if (!buf)
501 		goto out;
502 	bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
503 	sprom_do_read(bus, buf);
504 	err = sprom_check_crc(buf, bus->sprom_size);
505 	if (err) {
506 		/* check for rev 4 sprom - has special signature */
507 		if (buf[32] == 0x5372) {
508 			kfree(buf);
509 			buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
510 				      GFP_KERNEL);
511 			if (!buf)
512 				goto out;
513 			bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
514 			sprom_do_read(bus, buf);
515 			err = sprom_check_crc(buf, bus->sprom_size);
516 		}
517 		if (err)
518 			ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
519 				   " SPROM CRC (corrupt SPROM)\n");
520 	}
521 	err = sprom_extract(bus, sprom, buf, bus->sprom_size);
522 
523 	kfree(buf);
524 out:
525 	return err;
526 }
527 
528 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
529 				  struct ssb_boardinfo *bi)
530 {
531 	pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
532 			     &bi->vendor);
533 	pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
534 			     &bi->type);
535 	pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
536 			     &bi->rev);
537 }
538 
539 int ssb_pci_get_invariants(struct ssb_bus *bus,
540 			   struct ssb_init_invariants *iv)
541 {
542 	int err;
543 
544 	err = ssb_pci_sprom_get(bus, &iv->sprom);
545 	if (err)
546 		goto out;
547 	ssb_pci_get_boardinfo(bus, &iv->boardinfo);
548 
549 out:
550 	return err;
551 }
552 
553 #ifdef CONFIG_SSB_DEBUG
554 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
555 {
556 	if (likely(bus->powered_up))
557 		return 0;
558 
559 	printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
560 	       "while accessing PCI MMIO space\n");
561 	if (bus->power_warn_count <= 10) {
562 		bus->power_warn_count++;
563 		dump_stack();
564 	}
565 
566 	return -ENODEV;
567 }
568 #else /* DEBUG */
569 static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
570 {
571 	return 0;
572 }
573 #endif /* DEBUG */
574 
575 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
576 {
577 	struct ssb_bus *bus = dev->bus;
578 
579 	if (unlikely(ssb_pci_assert_buspower(bus)))
580 		return 0xFFFF;
581 	if (unlikely(bus->mapped_device != dev)) {
582 		if (unlikely(ssb_pci_switch_core(bus, dev)))
583 			return 0xFFFF;
584 	}
585 	return ioread16(bus->mmio + offset);
586 }
587 
588 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
589 {
590 	struct ssb_bus *bus = dev->bus;
591 
592 	if (unlikely(ssb_pci_assert_buspower(bus)))
593 		return 0xFFFFFFFF;
594 	if (unlikely(bus->mapped_device != dev)) {
595 		if (unlikely(ssb_pci_switch_core(bus, dev)))
596 			return 0xFFFFFFFF;
597 	}
598 	return ioread32(bus->mmio + offset);
599 }
600 
601 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
602 {
603 	struct ssb_bus *bus = dev->bus;
604 
605 	if (unlikely(ssb_pci_assert_buspower(bus)))
606 		return;
607 	if (unlikely(bus->mapped_device != dev)) {
608 		if (unlikely(ssb_pci_switch_core(bus, dev)))
609 			return;
610 	}
611 	iowrite16(value, bus->mmio + offset);
612 }
613 
614 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
615 {
616 	struct ssb_bus *bus = dev->bus;
617 
618 	if (unlikely(ssb_pci_assert_buspower(bus)))
619 		return;
620 	if (unlikely(bus->mapped_device != dev)) {
621 		if (unlikely(ssb_pci_switch_core(bus, dev)))
622 			return;
623 	}
624 	iowrite32(value, bus->mmio + offset);
625 }
626 
627 /* Not "static", as it's used in main.c */
628 const struct ssb_bus_ops ssb_pci_ops = {
629 	.read16		= ssb_pci_read16,
630 	.read32		= ssb_pci_read32,
631 	.write16	= ssb_pci_write16,
632 	.write32	= ssb_pci_write32,
633 };
634 
635 static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size)
636 {
637 	int i, pos = 0;
638 
639 	for (i = 0; i < size; i++)
640 		pos += snprintf(buf + pos, buf_len - pos - 1,
641 				"%04X", swab16(sprom[i]) & 0xFFFF);
642 	pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
643 
644 	return pos + 1;
645 }
646 
647 static int hex2sprom(u16 *sprom, const char *dump, size_t len, u16 size)
648 {
649 	char tmp[5] = { 0 };
650 	int cnt = 0;
651 	unsigned long parsed;
652 
653 	if (len < size * 2)
654 		return -EINVAL;
655 
656 	while (cnt < size) {
657 		memcpy(tmp, dump, 4);
658 		dump += 4;
659 		parsed = simple_strtoul(tmp, NULL, 16);
660 		sprom[cnt++] = swab16((u16)parsed);
661 	}
662 
663 	return 0;
664 }
665 
666 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
667 				       struct device_attribute *attr,
668 				       char *buf)
669 {
670 	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
671 	struct ssb_bus *bus;
672 	u16 *sprom;
673 	int err = -ENODEV;
674 	ssize_t count = 0;
675 
676 	bus = ssb_pci_dev_to_bus(pdev);
677 	if (!bus)
678 		goto out;
679 	err = -ENOMEM;
680 	sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
681 	if (!sprom)
682 		goto out;
683 
684 	/* Use interruptible locking, as the SPROM write might
685 	 * be holding the lock for several seconds. So allow userspace
686 	 * to cancel operation. */
687 	err = -ERESTARTSYS;
688 	if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
689 		goto out_kfree;
690 	sprom_do_read(bus, sprom);
691 	mutex_unlock(&bus->pci_sprom_mutex);
692 
693 	count = sprom2hex(sprom, buf, PAGE_SIZE, bus->sprom_size);
694 	err = 0;
695 
696 out_kfree:
697 	kfree(sprom);
698 out:
699 	return err ? err : count;
700 }
701 
702 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
703 					struct device_attribute *attr,
704 					const char *buf, size_t count)
705 {
706 	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
707 	struct ssb_bus *bus;
708 	u16 *sprom;
709 	int res = 0, err = -ENODEV;
710 
711 	bus = ssb_pci_dev_to_bus(pdev);
712 	if (!bus)
713 		goto out;
714 	err = -ENOMEM;
715 	sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
716 	if (!sprom)
717 		goto out;
718 	err = hex2sprom(sprom, buf, count, bus->sprom_size);
719 	if (err) {
720 		err = -EINVAL;
721 		goto out_kfree;
722 	}
723 	err = sprom_check_crc(sprom, bus->sprom_size);
724 	if (err) {
725 		err = -EINVAL;
726 		goto out_kfree;
727 	}
728 
729 	/* Use interruptible locking, as the SPROM write might
730 	 * be holding the lock for several seconds. So allow userspace
731 	 * to cancel operation. */
732 	err = -ERESTARTSYS;
733 	if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
734 		goto out_kfree;
735 	err = ssb_devices_freeze(bus);
736 	if (err == -EOPNOTSUPP) {
737 		ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
738 			   "No suspend support. Is CONFIG_PM enabled?\n");
739 		goto out_unlock;
740 	}
741 	if (err) {
742 		ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
743 		goto out_unlock;
744 	}
745 	res = sprom_do_write(bus, sprom);
746 	err = ssb_devices_thaw(bus);
747 	if (err)
748 		ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
749 out_unlock:
750 	mutex_unlock(&bus->pci_sprom_mutex);
751 out_kfree:
752 	kfree(sprom);
753 out:
754 	if (res)
755 		return res;
756 	return err ? err : count;
757 }
758 
759 static DEVICE_ATTR(ssb_sprom, 0600,
760 		   ssb_pci_attr_sprom_show,
761 		   ssb_pci_attr_sprom_store);
762 
763 void ssb_pci_exit(struct ssb_bus *bus)
764 {
765 	struct pci_dev *pdev;
766 
767 	if (bus->bustype != SSB_BUSTYPE_PCI)
768 		return;
769 
770 	pdev = bus->host_pci;
771 	device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
772 }
773 
774 int ssb_pci_init(struct ssb_bus *bus)
775 {
776 	struct pci_dev *pdev;
777 	int err;
778 
779 	if (bus->bustype != SSB_BUSTYPE_PCI)
780 		return 0;
781 
782 	pdev = bus->host_pci;
783 	mutex_init(&bus->pci_sprom_mutex);
784 	err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
785 	if (err)
786 		goto out;
787 
788 out:
789 	return err;
790 }
791