pci.c revision b3ae52b6b0335eba547221aad2cb3c50902e3d2d
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/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 */
32int 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;
58error:
59	ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
60	return -ENODEV;
61}
62
63int 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. */
86int 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
161out:
162	return err;
163
164err_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
182static inline u8 ssb_crc8(u8 crc, u8 data)
183{
184	/* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
185	static const u8 t[] = {
186		0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
187		0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
188		0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
189		0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
190		0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
191		0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
192		0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
193		0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
194		0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
195		0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
196		0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
197		0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
198		0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
199		0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
200		0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
201		0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
202		0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
203		0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
204		0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
205		0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
206		0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
207		0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
208		0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
209		0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
210		0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
211		0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
212		0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
213		0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
214		0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
215		0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
216		0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
217		0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
218	};
219	return t[crc ^ data];
220}
221
222static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
223{
224	int word;
225	u8 crc = 0xFF;
226
227	for (word = 0; word < size - 1; word++) {
228		crc = ssb_crc8(crc, sprom[word] & 0x00FF);
229		crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
230	}
231	crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
232	crc ^= 0xFF;
233
234	return crc;
235}
236
237static int sprom_check_crc(const u16 *sprom, size_t size)
238{
239	u8 crc;
240	u8 expected_crc;
241	u16 tmp;
242
243	crc = ssb_sprom_crc(sprom, size);
244	tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
245	expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
246	if (crc != expected_crc)
247		return -EPROTO;
248
249	return 0;
250}
251
252static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
253{
254	int i;
255
256	for (i = 0; i < bus->sprom_size; i++)
257		sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
258
259	return 0;
260}
261
262static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
263{
264	struct pci_dev *pdev = bus->host_pci;
265	int i, err;
266	u32 spromctl;
267	u16 size = bus->sprom_size;
268
269	ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
270	err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
271	if (err)
272		goto err_ctlreg;
273	spromctl |= SSB_SPROMCTL_WE;
274	err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
275	if (err)
276		goto err_ctlreg;
277	ssb_printk(KERN_NOTICE PFX "[ 0%%");
278	msleep(500);
279	for (i = 0; i < size; i++) {
280		if (i == size / 4)
281			ssb_printk("25%%");
282		else if (i == size / 2)
283			ssb_printk("50%%");
284		else if (i == (size * 3) / 4)
285			ssb_printk("75%%");
286		else if (i % 2)
287			ssb_printk(".");
288		writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
289		mmiowb();
290		msleep(20);
291	}
292	err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
293	if (err)
294		goto err_ctlreg;
295	spromctl &= ~SSB_SPROMCTL_WE;
296	err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
297	if (err)
298		goto err_ctlreg;
299	msleep(500);
300	ssb_printk("100%% ]\n");
301	ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
302
303	return 0;
304err_ctlreg:
305	ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
306	return err;
307}
308
309static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
310			       u16 mask, u16 shift)
311{
312	u16 v;
313	u8 gain;
314
315	v = in[SPOFF(SSB_SPROM1_AGAIN)];
316	gain = (v & mask) >> shift;
317	if (gain == 0xFF)
318		gain = 2; /* If unset use 2dBm */
319	if (sprom_revision == 1) {
320		/* Convert to Q5.2 */
321		gain <<= 2;
322	} else {
323		/* Q5.2 Fractional part is stored in 0xC0 */
324		gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
325	}
326
327	return (s8)gain;
328}
329
330static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
331{
332	int i;
333	u16 v;
334	s8 gain;
335	u16 loc[3];
336
337	if (out->revision == 3)			/* rev 3 moved MAC */
338		loc[0] = SSB_SPROM3_IL0MAC;
339	else {
340		loc[0] = SSB_SPROM1_IL0MAC;
341		loc[1] = SSB_SPROM1_ET0MAC;
342		loc[2] = SSB_SPROM1_ET1MAC;
343	}
344	for (i = 0; i < 3; i++) {
345		v = in[SPOFF(loc[0]) + i];
346		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
347	}
348	if (out->revision < 3) { 	/* only rev 1-2 have et0, et1 */
349		for (i = 0; i < 3; i++) {
350			v = in[SPOFF(loc[1]) + i];
351			*(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
352		}
353		for (i = 0; i < 3; i++) {
354			v = in[SPOFF(loc[2]) + i];
355			*(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
356		}
357	}
358	SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
359	SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
360	     SSB_SPROM1_ETHPHY_ET1A_SHIFT);
361	SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
362	SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
363	SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
364	SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
365	     SSB_SPROM1_BINF_CCODE_SHIFT);
366	SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
367	     SSB_SPROM1_BINF_ANTA_SHIFT);
368	SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
369	     SSB_SPROM1_BINF_ANTBG_SHIFT);
370	SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
371	SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
372	SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
373	SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
374	SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
375	SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
376	SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
377	SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
378	     SSB_SPROM1_GPIOA_P1_SHIFT);
379	SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
380	SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
381	     SSB_SPROM1_GPIOB_P3_SHIFT);
382	SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
383	     SSB_SPROM1_MAXPWR_A_SHIFT);
384	SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
385	SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
386	     SSB_SPROM1_ITSSI_A_SHIFT);
387	SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
388	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
389	if (out->revision >= 2)
390		SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
391
392	/* Extract the antenna gain values. */
393	gain = r123_extract_antgain(out->revision, in,
394				    SSB_SPROM1_AGAIN_BG,
395				    SSB_SPROM1_AGAIN_BG_SHIFT);
396	out->antenna_gain.ghz24.a0 = gain;
397	out->antenna_gain.ghz24.a1 = gain;
398	out->antenna_gain.ghz24.a2 = gain;
399	out->antenna_gain.ghz24.a3 = gain;
400	gain = r123_extract_antgain(out->revision, in,
401				    SSB_SPROM1_AGAIN_A,
402				    SSB_SPROM1_AGAIN_A_SHIFT);
403	out->antenna_gain.ghz5.a0 = gain;
404	out->antenna_gain.ghz5.a1 = gain;
405	out->antenna_gain.ghz5.a2 = gain;
406	out->antenna_gain.ghz5.a3 = gain;
407}
408
409/* Revs 4 5 and 8 have partially shared layout */
410static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
411{
412	SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
413	     SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
414	SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
415	     SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
416	SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
417	     SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
418	SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
419	     SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
420
421	SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
422	     SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
423	SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
424	     SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
425	SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
426	     SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
427	SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
428	     SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
429
430	SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
431	     SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
432	SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
433	     SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
434	SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
435	     SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
436	SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
437	     SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
438
439	SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
440	     SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
441	SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
442	     SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
443	SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
444	     SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
445	SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
446	     SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
447}
448
449static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
450{
451	int i;
452	u16 v;
453	u16 il0mac_offset;
454
455	if (out->revision == 4)
456		il0mac_offset = SSB_SPROM4_IL0MAC;
457	else
458		il0mac_offset = SSB_SPROM5_IL0MAC;
459	/* extract the MAC address */
460	for (i = 0; i < 3; i++) {
461		v = in[SPOFF(il0mac_offset) + i];
462		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
463	}
464	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
465	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
466	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
467	if (out->revision == 4) {
468		SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
469		SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
470		SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
471		SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
472		SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
473	} else {
474		SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
475		SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
476		SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
477		SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
478		SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
479	}
480	SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
481	     SSB_SPROM4_ANTAVAIL_A_SHIFT);
482	SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
483	     SSB_SPROM4_ANTAVAIL_BG_SHIFT);
484	SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
485	SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
486	     SSB_SPROM4_ITSSI_BG_SHIFT);
487	SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
488	SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
489	     SSB_SPROM4_ITSSI_A_SHIFT);
490	if (out->revision == 4) {
491		SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
492		SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
493		     SSB_SPROM4_GPIOA_P1_SHIFT);
494		SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
495		SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
496		     SSB_SPROM4_GPIOB_P3_SHIFT);
497	} else {
498		SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
499		SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
500		     SSB_SPROM5_GPIOA_P1_SHIFT);
501		SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
502		SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
503		     SSB_SPROM5_GPIOB_P3_SHIFT);
504	}
505
506	/* Extract the antenna gain values. */
507	SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
508	     SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
509	SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
510	     SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
511	SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
512	     SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
513	SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
514	     SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
515	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
516	       sizeof(out->antenna_gain.ghz5));
517
518	sprom_extract_r458(out, in);
519
520	/* TODO - get remaining rev 4 stuff needed */
521}
522
523static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
524{
525	int i;
526	u16 v;
527
528	/* extract the MAC address */
529	for (i = 0; i < 3; i++) {
530		v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
531		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
532	}
533	SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
534	SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
535	SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
536	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
537	SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
538	SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
539	     SSB_SPROM8_ANTAVAIL_A_SHIFT);
540	SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
541	     SSB_SPROM8_ANTAVAIL_BG_SHIFT);
542	SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
543	SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
544	     SSB_SPROM8_ITSSI_BG_SHIFT);
545	SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
546	SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
547	     SSB_SPROM8_ITSSI_A_SHIFT);
548	SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
549	SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
550	     SSB_SPROM8_MAXP_AL_SHIFT);
551	SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
552	SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
553	     SSB_SPROM8_GPIOA_P1_SHIFT);
554	SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
555	SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
556	     SSB_SPROM8_GPIOB_P3_SHIFT);
557	SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
558	SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
559	     SSB_SPROM8_TRI5G_SHIFT);
560	SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
561	SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
562	     SSB_SPROM8_TRI5GH_SHIFT);
563	SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
564	SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
565	     SSB_SPROM8_RXPO5G_SHIFT);
566	SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
567	SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
568	     SSB_SPROM8_RSSISMC2G_SHIFT);
569	SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
570	     SSB_SPROM8_RSSISAV2G_SHIFT);
571	SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
572	     SSB_SPROM8_BXA2G_SHIFT);
573	SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
574	SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
575	     SSB_SPROM8_RSSISMC5G_SHIFT);
576	SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
577	     SSB_SPROM8_RSSISAV5G_SHIFT);
578	SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
579	     SSB_SPROM8_BXA5G_SHIFT);
580	SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
581	SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
582	SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
583	SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
584	SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
585	SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
586	SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
587	SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
588	SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
589	SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
590	SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
591	SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
592	SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
593	SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
594	SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
595	SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
596	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
597
598	/* Extract the antenna gain values. */
599	SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
600	     SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
601	SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01,
602	     SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
603	SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23,
604	     SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
605	SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23,
606	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
607	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
608	       sizeof(out->antenna_gain.ghz5));
609
610	sprom_extract_r458(out, in);
611
612	/* TODO - get remaining rev 8 stuff needed */
613}
614
615static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
616			 const u16 *in, u16 size)
617{
618	memset(out, 0, sizeof(*out));
619
620	out->revision = in[size - 1] & 0x00FF;
621	ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
622	memset(out->et0mac, 0xFF, 6);		/* preset et0 and et1 mac */
623	memset(out->et1mac, 0xFF, 6);
624
625	if ((bus->chip_id & 0xFF00) == 0x4400) {
626		/* Workaround: The BCM44XX chip has a stupid revision
627		 * number stored in the SPROM.
628		 * Always extract r1. */
629		out->revision = 1;
630		ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
631	}
632
633	switch (out->revision) {
634	case 1:
635	case 2:
636	case 3:
637		sprom_extract_r123(out, in);
638		break;
639	case 4:
640	case 5:
641		sprom_extract_r45(out, in);
642		break;
643	case 8:
644		sprom_extract_r8(out, in);
645		break;
646	default:
647		ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
648			   " revision %d detected. Will extract"
649			   " v1\n", out->revision);
650		out->revision = 1;
651		sprom_extract_r123(out, in);
652	}
653
654	if (out->boardflags_lo == 0xFFFF)
655		out->boardflags_lo = 0;  /* per specs */
656	if (out->boardflags_hi == 0xFFFF)
657		out->boardflags_hi = 0;  /* per specs */
658
659	return 0;
660}
661
662static int ssb_pci_sprom_get(struct ssb_bus *bus,
663			     struct ssb_sprom *sprom)
664{
665	int err;
666	u16 *buf;
667
668	if (!ssb_is_sprom_available(bus)) {
669		ssb_printk(KERN_ERR PFX "No SPROM available!\n");
670		return -ENODEV;
671	}
672	if (bus->chipco.dev) {	/* can be unavailable! */
673		/*
674		 * get SPROM offset: SSB_SPROM_BASE1 except for
675		 * chipcommon rev >= 31 or chip ID is 0x4312 and
676		 * chipcommon status & 3 == 2
677		 */
678		if (bus->chipco.dev->id.revision >= 31)
679			bus->sprom_offset = SSB_SPROM_BASE31;
680		else if (bus->chip_id == 0x4312 &&
681			 (bus->chipco.status & 0x03) == 2)
682			bus->sprom_offset = SSB_SPROM_BASE31;
683		else
684			bus->sprom_offset = SSB_SPROM_BASE1;
685	} else {
686		bus->sprom_offset = SSB_SPROM_BASE1;
687	}
688	ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
689
690	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
691	if (!buf)
692		return -ENOMEM;
693	bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
694	sprom_do_read(bus, buf);
695	err = sprom_check_crc(buf, bus->sprom_size);
696	if (err) {
697		/* try for a 440 byte SPROM - revision 4 and higher */
698		kfree(buf);
699		buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
700			      GFP_KERNEL);
701		if (!buf)
702			return -ENOMEM;
703		bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
704		sprom_do_read(bus, buf);
705		err = sprom_check_crc(buf, bus->sprom_size);
706		if (err) {
707			/* All CRC attempts failed.
708			 * Maybe there is no SPROM on the device?
709			 * Now we ask the arch code if there is some sprom
710			 * available for this device in some other storage */
711			err = ssb_fill_sprom_with_fallback(bus, sprom);
712			if (err) {
713				ssb_printk(KERN_WARNING PFX "WARNING: Using"
714					   " fallback SPROM failed (err %d)\n",
715					   err);
716			} else {
717				ssb_dprintk(KERN_DEBUG PFX "Using SPROM"
718					    " revision %d provided by"
719					    " platform.\n", sprom->revision);
720				err = 0;
721				goto out_free;
722			}
723			ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
724				   " SPROM CRC (corrupt SPROM)\n");
725		}
726	}
727	err = sprom_extract(bus, sprom, buf, bus->sprom_size);
728
729out_free:
730	kfree(buf);
731	return err;
732}
733
734static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
735				  struct ssb_boardinfo *bi)
736{
737	pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
738			     &bi->vendor);
739	pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
740			     &bi->type);
741	pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
742			     &bi->rev);
743}
744
745int ssb_pci_get_invariants(struct ssb_bus *bus,
746			   struct ssb_init_invariants *iv)
747{
748	int err;
749
750	err = ssb_pci_sprom_get(bus, &iv->sprom);
751	if (err)
752		goto out;
753	ssb_pci_get_boardinfo(bus, &iv->boardinfo);
754
755out:
756	return err;
757}
758
759#ifdef CONFIG_SSB_DEBUG
760static int ssb_pci_assert_buspower(struct ssb_bus *bus)
761{
762	if (likely(bus->powered_up))
763		return 0;
764
765	printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
766	       "while accessing PCI MMIO space\n");
767	if (bus->power_warn_count <= 10) {
768		bus->power_warn_count++;
769		dump_stack();
770	}
771
772	return -ENODEV;
773}
774#else /* DEBUG */
775static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
776{
777	return 0;
778}
779#endif /* DEBUG */
780
781static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
782{
783	struct ssb_bus *bus = dev->bus;
784
785	if (unlikely(ssb_pci_assert_buspower(bus)))
786		return 0xFF;
787	if (unlikely(bus->mapped_device != dev)) {
788		if (unlikely(ssb_pci_switch_core(bus, dev)))
789			return 0xFF;
790	}
791	return ioread8(bus->mmio + offset);
792}
793
794static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
795{
796	struct ssb_bus *bus = dev->bus;
797
798	if (unlikely(ssb_pci_assert_buspower(bus)))
799		return 0xFFFF;
800	if (unlikely(bus->mapped_device != dev)) {
801		if (unlikely(ssb_pci_switch_core(bus, dev)))
802			return 0xFFFF;
803	}
804	return ioread16(bus->mmio + offset);
805}
806
807static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
808{
809	struct ssb_bus *bus = dev->bus;
810
811	if (unlikely(ssb_pci_assert_buspower(bus)))
812		return 0xFFFFFFFF;
813	if (unlikely(bus->mapped_device != dev)) {
814		if (unlikely(ssb_pci_switch_core(bus, dev)))
815			return 0xFFFFFFFF;
816	}
817	return ioread32(bus->mmio + offset);
818}
819
820#ifdef CONFIG_SSB_BLOCKIO
821static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
822			       size_t count, u16 offset, u8 reg_width)
823{
824	struct ssb_bus *bus = dev->bus;
825	void __iomem *addr = bus->mmio + offset;
826
827	if (unlikely(ssb_pci_assert_buspower(bus)))
828		goto error;
829	if (unlikely(bus->mapped_device != dev)) {
830		if (unlikely(ssb_pci_switch_core(bus, dev)))
831			goto error;
832	}
833	switch (reg_width) {
834	case sizeof(u8):
835		ioread8_rep(addr, buffer, count);
836		break;
837	case sizeof(u16):
838		SSB_WARN_ON(count & 1);
839		ioread16_rep(addr, buffer, count >> 1);
840		break;
841	case sizeof(u32):
842		SSB_WARN_ON(count & 3);
843		ioread32_rep(addr, buffer, count >> 2);
844		break;
845	default:
846		SSB_WARN_ON(1);
847	}
848
849	return;
850error:
851	memset(buffer, 0xFF, count);
852}
853#endif /* CONFIG_SSB_BLOCKIO */
854
855static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
856{
857	struct ssb_bus *bus = dev->bus;
858
859	if (unlikely(ssb_pci_assert_buspower(bus)))
860		return;
861	if (unlikely(bus->mapped_device != dev)) {
862		if (unlikely(ssb_pci_switch_core(bus, dev)))
863			return;
864	}
865	iowrite8(value, bus->mmio + offset);
866}
867
868static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
869{
870	struct ssb_bus *bus = dev->bus;
871
872	if (unlikely(ssb_pci_assert_buspower(bus)))
873		return;
874	if (unlikely(bus->mapped_device != dev)) {
875		if (unlikely(ssb_pci_switch_core(bus, dev)))
876			return;
877	}
878	iowrite16(value, bus->mmio + offset);
879}
880
881static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
882{
883	struct ssb_bus *bus = dev->bus;
884
885	if (unlikely(ssb_pci_assert_buspower(bus)))
886		return;
887	if (unlikely(bus->mapped_device != dev)) {
888		if (unlikely(ssb_pci_switch_core(bus, dev)))
889			return;
890	}
891	iowrite32(value, bus->mmio + offset);
892}
893
894#ifdef CONFIG_SSB_BLOCKIO
895static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
896				size_t count, u16 offset, u8 reg_width)
897{
898	struct ssb_bus *bus = dev->bus;
899	void __iomem *addr = bus->mmio + offset;
900
901	if (unlikely(ssb_pci_assert_buspower(bus)))
902		return;
903	if (unlikely(bus->mapped_device != dev)) {
904		if (unlikely(ssb_pci_switch_core(bus, dev)))
905			return;
906	}
907	switch (reg_width) {
908	case sizeof(u8):
909		iowrite8_rep(addr, buffer, count);
910		break;
911	case sizeof(u16):
912		SSB_WARN_ON(count & 1);
913		iowrite16_rep(addr, buffer, count >> 1);
914		break;
915	case sizeof(u32):
916		SSB_WARN_ON(count & 3);
917		iowrite32_rep(addr, buffer, count >> 2);
918		break;
919	default:
920		SSB_WARN_ON(1);
921	}
922}
923#endif /* CONFIG_SSB_BLOCKIO */
924
925/* Not "static", as it's used in main.c */
926const struct ssb_bus_ops ssb_pci_ops = {
927	.read8		= ssb_pci_read8,
928	.read16		= ssb_pci_read16,
929	.read32		= ssb_pci_read32,
930	.write8		= ssb_pci_write8,
931	.write16	= ssb_pci_write16,
932	.write32	= ssb_pci_write32,
933#ifdef CONFIG_SSB_BLOCKIO
934	.block_read	= ssb_pci_block_read,
935	.block_write	= ssb_pci_block_write,
936#endif
937};
938
939static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
940				       struct device_attribute *attr,
941				       char *buf)
942{
943	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
944	struct ssb_bus *bus;
945
946	bus = ssb_pci_dev_to_bus(pdev);
947	if (!bus)
948		return -ENODEV;
949
950	return ssb_attr_sprom_show(bus, buf, sprom_do_read);
951}
952
953static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
954					struct device_attribute *attr,
955					const char *buf, size_t count)
956{
957	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
958	struct ssb_bus *bus;
959
960	bus = ssb_pci_dev_to_bus(pdev);
961	if (!bus)
962		return -ENODEV;
963
964	return ssb_attr_sprom_store(bus, buf, count,
965				    sprom_check_crc, sprom_do_write);
966}
967
968static DEVICE_ATTR(ssb_sprom, 0600,
969		   ssb_pci_attr_sprom_show,
970		   ssb_pci_attr_sprom_store);
971
972void ssb_pci_exit(struct ssb_bus *bus)
973{
974	struct pci_dev *pdev;
975
976	if (bus->bustype != SSB_BUSTYPE_PCI)
977		return;
978
979	pdev = bus->host_pci;
980	device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
981}
982
983int ssb_pci_init(struct ssb_bus *bus)
984{
985	struct pci_dev *pdev;
986	int err;
987
988	if (bus->bustype != SSB_BUSTYPE_PCI)
989		return 0;
990
991	pdev = bus->host_pci;
992	mutex_init(&bus->sprom_mutex);
993	err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
994	if (err)
995		goto out;
996
997out:
998	return err;
999}
1000