• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/ssb/
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
409static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
410{
411	int i;
412	u16 v;
413	u16 il0mac_offset;
414
415	if (out->revision == 4)
416		il0mac_offset = SSB_SPROM4_IL0MAC;
417	else
418		il0mac_offset = SSB_SPROM5_IL0MAC;
419	/* extract the MAC address */
420	for (i = 0; i < 3; i++) {
421		v = in[SPOFF(il0mac_offset) + i];
422		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
423	}
424	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
425	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
426	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
427	if (out->revision == 4) {
428		SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
429		SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
430		SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
431	} else {
432		SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
433		SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
434		SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
435	}
436	SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
437	     SSB_SPROM4_ANTAVAIL_A_SHIFT);
438	SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
439	     SSB_SPROM4_ANTAVAIL_BG_SHIFT);
440	SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
441	SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
442	     SSB_SPROM4_ITSSI_BG_SHIFT);
443	SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
444	SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
445	     SSB_SPROM4_ITSSI_A_SHIFT);
446	if (out->revision == 4) {
447		SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
448		SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
449		     SSB_SPROM4_GPIOA_P1_SHIFT);
450		SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
451		SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
452		     SSB_SPROM4_GPIOB_P3_SHIFT);
453	} else {
454		SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
455		SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
456		     SSB_SPROM5_GPIOA_P1_SHIFT);
457		SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
458		SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
459		     SSB_SPROM5_GPIOB_P3_SHIFT);
460	}
461
462	/* Extract the antenna gain values. */
463	SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
464	     SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
465	SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
466	     SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
467	SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
468	     SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
469	SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
470	     SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
471	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
472	       sizeof(out->antenna_gain.ghz5));
473
474	/* TODO - get remaining rev 4 stuff needed */
475}
476
477static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
478{
479	int i;
480	u16 v;
481
482	/* extract the MAC address */
483	for (i = 0; i < 3; i++) {
484		v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
485		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
486	}
487	SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
488	SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
489	SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
490	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
491	SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
492	SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
493	     SSB_SPROM8_ANTAVAIL_A_SHIFT);
494	SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
495	     SSB_SPROM8_ANTAVAIL_BG_SHIFT);
496	SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
497	SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
498	     SSB_SPROM8_ITSSI_BG_SHIFT);
499	SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
500	SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
501	     SSB_SPROM8_ITSSI_A_SHIFT);
502	SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
503	SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
504	     SSB_SPROM8_MAXP_AL_SHIFT);
505	SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
506	SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
507	     SSB_SPROM8_GPIOA_P1_SHIFT);
508	SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
509	SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
510	     SSB_SPROM8_GPIOB_P3_SHIFT);
511	SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
512	SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
513	     SSB_SPROM8_TRI5G_SHIFT);
514	SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
515	SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
516	     SSB_SPROM8_TRI5GH_SHIFT);
517	SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
518	SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
519	     SSB_SPROM8_RXPO5G_SHIFT);
520	SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
521	SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
522	     SSB_SPROM8_RSSISMC2G_SHIFT);
523	SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
524	     SSB_SPROM8_RSSISAV2G_SHIFT);
525	SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
526	     SSB_SPROM8_BXA2G_SHIFT);
527	SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
528	SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
529	     SSB_SPROM8_RSSISMC5G_SHIFT);
530	SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
531	     SSB_SPROM8_RSSISAV5G_SHIFT);
532	SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
533	     SSB_SPROM8_BXA5G_SHIFT);
534	SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
535	SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
536	SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
537	SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
538	SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
539	SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
540	SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
541	SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
542	SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
543	SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
544	SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
545	SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
546	SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
547	SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
548	SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
549	SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
550	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
551
552	/* Extract the antenna gain values. */
553	SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
554	     SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
555	SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01,
556	     SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
557	SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23,
558	     SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
559	SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23,
560	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
561	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
562	       sizeof(out->antenna_gain.ghz5));
563
564	/* TODO - get remaining rev 8 stuff needed */
565}
566
567static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
568			 const u16 *in, u16 size)
569{
570	memset(out, 0, sizeof(*out));
571
572	out->revision = in[size - 1] & 0x00FF;
573	ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
574	memset(out->et0mac, 0xFF, 6);		/* preset et0 and et1 mac */
575	memset(out->et1mac, 0xFF, 6);
576	if ((bus->chip_id & 0xFF00) == 0x4400) {
577		out->revision = 1;
578		sprom_extract_r123(out, in);
579	} else if (bus->chip_id == 0x4321) {
580		/* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
581		out->revision = 4;
582		sprom_extract_r45(out, in);
583	} else {
584		switch (out->revision) {
585		case 1:
586		case 2:
587		case 3:
588			sprom_extract_r123(out, in);
589			break;
590		case 4:
591		case 5:
592			sprom_extract_r45(out, in);
593			break;
594		case 8:
595			sprom_extract_r8(out, in);
596			break;
597		default:
598			ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
599				   "  revision %d detected. Will extract"
600				   " v1\n", out->revision);
601			out->revision = 1;
602			sprom_extract_r123(out, in);
603		}
604	}
605
606	if (out->boardflags_lo == 0xFFFF)
607		out->boardflags_lo = 0;  /* per specs */
608	if (out->boardflags_hi == 0xFFFF)
609		out->boardflags_hi = 0;  /* per specs */
610
611	return 0;
612}
613
614static int ssb_pci_sprom_get(struct ssb_bus *bus,
615			     struct ssb_sprom *sprom)
616{
617	const struct ssb_sprom *fallback;
618	int err = -ENOMEM;
619	u16 *buf;
620
621	if (!ssb_is_sprom_available(bus)) {
622		ssb_printk(KERN_ERR PFX "No SPROM available!\n");
623		return -ENODEV;
624	}
625	if (bus->chipco.dev) {	/* can be unavailible! */
626		/*
627		 * get SPROM offset: SSB_SPROM_BASE1 except for
628		 * chipcommon rev >= 31 or chip ID is 0x4312 and
629		 * chipcommon status & 3 == 2
630		 */
631		if (bus->chipco.dev->id.revision >= 31)
632			bus->sprom_offset = SSB_SPROM_BASE31;
633		else if (bus->chip_id == 0x4312 &&
634			 (bus->chipco.status & 0x03) == 2)
635			bus->sprom_offset = SSB_SPROM_BASE31;
636		else
637			bus->sprom_offset = SSB_SPROM_BASE1;
638	} else {
639		bus->sprom_offset = SSB_SPROM_BASE1;
640	}
641	ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
642
643	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
644	if (!buf)
645		goto out;
646	bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
647	sprom_do_read(bus, buf);
648	err = sprom_check_crc(buf, bus->sprom_size);
649	if (err) {
650		/* try for a 440 byte SPROM - revision 4 and higher */
651		kfree(buf);
652		buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
653			      GFP_KERNEL);
654		if (!buf)
655			goto out;
656		bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
657		sprom_do_read(bus, buf);
658		err = sprom_check_crc(buf, bus->sprom_size);
659		if (err) {
660			/* All CRC attempts failed.
661			 * Maybe there is no SPROM on the device?
662			 * If we have a fallback, use that. */
663			fallback = ssb_get_fallback_sprom();
664			if (fallback) {
665				memcpy(sprom, fallback, sizeof(*sprom));
666				err = 0;
667				goto out_free;
668			}
669			ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
670				   " SPROM CRC (corrupt SPROM)\n");
671		}
672	}
673	err = sprom_extract(bus, sprom, buf, bus->sprom_size);
674
675out_free:
676	kfree(buf);
677out:
678	return err;
679}
680
681static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
682				  struct ssb_boardinfo *bi)
683{
684	pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
685			     &bi->vendor);
686	pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
687			     &bi->type);
688	pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
689			     &bi->rev);
690}
691
692int ssb_pci_get_invariants(struct ssb_bus *bus,
693			   struct ssb_init_invariants *iv)
694{
695	int err;
696
697	err = ssb_pci_sprom_get(bus, &iv->sprom);
698	if (err)
699		goto out;
700	ssb_pci_get_boardinfo(bus, &iv->boardinfo);
701
702out:
703	return err;
704}
705
706#ifdef CONFIG_SSB_DEBUG
707static int ssb_pci_assert_buspower(struct ssb_bus *bus)
708{
709	if (likely(bus->powered_up))
710		return 0;
711
712	printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
713	       "while accessing PCI MMIO space\n");
714	if (bus->power_warn_count <= 10) {
715		bus->power_warn_count++;
716		dump_stack();
717	}
718
719	return -ENODEV;
720}
721#else /* DEBUG */
722static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
723{
724	return 0;
725}
726#endif /* DEBUG */
727
728static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
729{
730	struct ssb_bus *bus = dev->bus;
731
732	if (unlikely(ssb_pci_assert_buspower(bus)))
733		return 0xFF;
734	if (unlikely(bus->mapped_device != dev)) {
735		if (unlikely(ssb_pci_switch_core(bus, dev)))
736			return 0xFF;
737	}
738	return ioread8(bus->mmio + offset);
739}
740
741static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
742{
743	struct ssb_bus *bus = dev->bus;
744
745	if (unlikely(ssb_pci_assert_buspower(bus)))
746		return 0xFFFF;
747	if (unlikely(bus->mapped_device != dev)) {
748		if (unlikely(ssb_pci_switch_core(bus, dev)))
749			return 0xFFFF;
750	}
751	return ioread16(bus->mmio + offset);
752}
753
754static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
755{
756	struct ssb_bus *bus = dev->bus;
757
758	if (unlikely(ssb_pci_assert_buspower(bus)))
759		return 0xFFFFFFFF;
760	if (unlikely(bus->mapped_device != dev)) {
761		if (unlikely(ssb_pci_switch_core(bus, dev)))
762			return 0xFFFFFFFF;
763	}
764	return ioread32(bus->mmio + offset);
765}
766
767#ifdef CONFIG_SSB_BLOCKIO
768static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
769			       size_t count, u16 offset, u8 reg_width)
770{
771	struct ssb_bus *bus = dev->bus;
772	void __iomem *addr = bus->mmio + offset;
773
774	if (unlikely(ssb_pci_assert_buspower(bus)))
775		goto error;
776	if (unlikely(bus->mapped_device != dev)) {
777		if (unlikely(ssb_pci_switch_core(bus, dev)))
778			goto error;
779	}
780	switch (reg_width) {
781	case sizeof(u8):
782		ioread8_rep(addr, buffer, count);
783		break;
784	case sizeof(u16):
785		SSB_WARN_ON(count & 1);
786		ioread16_rep(addr, buffer, count >> 1);
787		break;
788	case sizeof(u32):
789		SSB_WARN_ON(count & 3);
790		ioread32_rep(addr, buffer, count >> 2);
791		break;
792	default:
793		SSB_WARN_ON(1);
794	}
795
796	return;
797error:
798	memset(buffer, 0xFF, count);
799}
800#endif /* CONFIG_SSB_BLOCKIO */
801
802static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
803{
804	struct ssb_bus *bus = dev->bus;
805
806	if (unlikely(ssb_pci_assert_buspower(bus)))
807		return;
808	if (unlikely(bus->mapped_device != dev)) {
809		if (unlikely(ssb_pci_switch_core(bus, dev)))
810			return;
811	}
812	iowrite8(value, bus->mmio + offset);
813}
814
815static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
816{
817	struct ssb_bus *bus = dev->bus;
818
819	if (unlikely(ssb_pci_assert_buspower(bus)))
820		return;
821	if (unlikely(bus->mapped_device != dev)) {
822		if (unlikely(ssb_pci_switch_core(bus, dev)))
823			return;
824	}
825	iowrite16(value, bus->mmio + offset);
826}
827
828static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
829{
830	struct ssb_bus *bus = dev->bus;
831
832	if (unlikely(ssb_pci_assert_buspower(bus)))
833		return;
834	if (unlikely(bus->mapped_device != dev)) {
835		if (unlikely(ssb_pci_switch_core(bus, dev)))
836			return;
837	}
838	iowrite32(value, bus->mmio + offset);
839}
840
841#ifdef CONFIG_SSB_BLOCKIO
842static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
843				size_t count, u16 offset, u8 reg_width)
844{
845	struct ssb_bus *bus = dev->bus;
846	void __iomem *addr = bus->mmio + offset;
847
848	if (unlikely(ssb_pci_assert_buspower(bus)))
849		return;
850	if (unlikely(bus->mapped_device != dev)) {
851		if (unlikely(ssb_pci_switch_core(bus, dev)))
852			return;
853	}
854	switch (reg_width) {
855	case sizeof(u8):
856		iowrite8_rep(addr, buffer, count);
857		break;
858	case sizeof(u16):
859		SSB_WARN_ON(count & 1);
860		iowrite16_rep(addr, buffer, count >> 1);
861		break;
862	case sizeof(u32):
863		SSB_WARN_ON(count & 3);
864		iowrite32_rep(addr, buffer, count >> 2);
865		break;
866	default:
867		SSB_WARN_ON(1);
868	}
869}
870#endif /* CONFIG_SSB_BLOCKIO */
871
872/* Not "static", as it's used in main.c */
873const struct ssb_bus_ops ssb_pci_ops = {
874	.read8		= ssb_pci_read8,
875	.read16		= ssb_pci_read16,
876	.read32		= ssb_pci_read32,
877	.write8		= ssb_pci_write8,
878	.write16	= ssb_pci_write16,
879	.write32	= ssb_pci_write32,
880#ifdef CONFIG_SSB_BLOCKIO
881	.block_read	= ssb_pci_block_read,
882	.block_write	= ssb_pci_block_write,
883#endif
884};
885
886static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
887				       struct device_attribute *attr,
888				       char *buf)
889{
890	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
891	struct ssb_bus *bus;
892
893	bus = ssb_pci_dev_to_bus(pdev);
894	if (!bus)
895		return -ENODEV;
896
897	return ssb_attr_sprom_show(bus, buf, sprom_do_read);
898}
899
900static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
901					struct device_attribute *attr,
902					const char *buf, size_t count)
903{
904	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
905	struct ssb_bus *bus;
906
907	bus = ssb_pci_dev_to_bus(pdev);
908	if (!bus)
909		return -ENODEV;
910
911	return ssb_attr_sprom_store(bus, buf, count,
912				    sprom_check_crc, sprom_do_write);
913}
914
915static DEVICE_ATTR(ssb_sprom, 0600,
916		   ssb_pci_attr_sprom_show,
917		   ssb_pci_attr_sprom_store);
918
919void ssb_pci_exit(struct ssb_bus *bus)
920{
921	struct pci_dev *pdev;
922
923	if (bus->bustype != SSB_BUSTYPE_PCI)
924		return;
925
926	pdev = bus->host_pci;
927	device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
928}
929
930int ssb_pci_init(struct ssb_bus *bus)
931{
932	struct pci_dev *pdev;
933	int err;
934
935	if (bus->bustype != SSB_BUSTYPE_PCI)
936		return 0;
937
938	pdev = bus->host_pci;
939	mutex_init(&bus->sprom_mutex);
940	err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
941	if (err)
942		goto out;
943
944out:
945	return err;
946}
947