Linux Audio

Check our new training course

Loading...
v3.1
  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 */
 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	bi->vendor = bus->host_pci->subsystem_vendor;
738	bi->type = bus->host_pci->subsystem_device;
739	bi->rev = bus->host_pci->revision;
740}
741
742int ssb_pci_get_invariants(struct ssb_bus *bus,
743			   struct ssb_init_invariants *iv)
744{
745	int err;
746
747	err = ssb_pci_sprom_get(bus, &iv->sprom);
748	if (err)
749		goto out;
750	ssb_pci_get_boardinfo(bus, &iv->boardinfo);
751
752out:
753	return err;
754}
755
756#ifdef CONFIG_SSB_DEBUG
757static int ssb_pci_assert_buspower(struct ssb_bus *bus)
758{
759	if (likely(bus->powered_up))
760		return 0;
761
762	printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
763	       "while accessing PCI MMIO space\n");
764	if (bus->power_warn_count <= 10) {
765		bus->power_warn_count++;
766		dump_stack();
767	}
768
769	return -ENODEV;
770}
771#else /* DEBUG */
772static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
773{
774	return 0;
775}
776#endif /* DEBUG */
777
778static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
779{
780	struct ssb_bus *bus = dev->bus;
781
782	if (unlikely(ssb_pci_assert_buspower(bus)))
783		return 0xFF;
784	if (unlikely(bus->mapped_device != dev)) {
785		if (unlikely(ssb_pci_switch_core(bus, dev)))
786			return 0xFF;
787	}
788	return ioread8(bus->mmio + offset);
789}
790
791static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
792{
793	struct ssb_bus *bus = dev->bus;
794
795	if (unlikely(ssb_pci_assert_buspower(bus)))
796		return 0xFFFF;
797	if (unlikely(bus->mapped_device != dev)) {
798		if (unlikely(ssb_pci_switch_core(bus, dev)))
799			return 0xFFFF;
800	}
801	return ioread16(bus->mmio + offset);
802}
803
804static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
805{
806	struct ssb_bus *bus = dev->bus;
807
808	if (unlikely(ssb_pci_assert_buspower(bus)))
809		return 0xFFFFFFFF;
810	if (unlikely(bus->mapped_device != dev)) {
811		if (unlikely(ssb_pci_switch_core(bus, dev)))
812			return 0xFFFFFFFF;
813	}
814	return ioread32(bus->mmio + offset);
815}
816
817#ifdef CONFIG_SSB_BLOCKIO
818static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
819			       size_t count, u16 offset, u8 reg_width)
820{
821	struct ssb_bus *bus = dev->bus;
822	void __iomem *addr = bus->mmio + offset;
823
824	if (unlikely(ssb_pci_assert_buspower(bus)))
825		goto error;
826	if (unlikely(bus->mapped_device != dev)) {
827		if (unlikely(ssb_pci_switch_core(bus, dev)))
828			goto error;
829	}
830	switch (reg_width) {
831	case sizeof(u8):
832		ioread8_rep(addr, buffer, count);
833		break;
834	case sizeof(u16):
835		SSB_WARN_ON(count & 1);
836		ioread16_rep(addr, buffer, count >> 1);
837		break;
838	case sizeof(u32):
839		SSB_WARN_ON(count & 3);
840		ioread32_rep(addr, buffer, count >> 2);
841		break;
842	default:
843		SSB_WARN_ON(1);
844	}
845
846	return;
847error:
848	memset(buffer, 0xFF, count);
849}
850#endif /* CONFIG_SSB_BLOCKIO */
851
852static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
853{
854	struct ssb_bus *bus = dev->bus;
855
856	if (unlikely(ssb_pci_assert_buspower(bus)))
857		return;
858	if (unlikely(bus->mapped_device != dev)) {
859		if (unlikely(ssb_pci_switch_core(bus, dev)))
860			return;
861	}
862	iowrite8(value, bus->mmio + offset);
863}
864
865static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
866{
867	struct ssb_bus *bus = dev->bus;
868
869	if (unlikely(ssb_pci_assert_buspower(bus)))
870		return;
871	if (unlikely(bus->mapped_device != dev)) {
872		if (unlikely(ssb_pci_switch_core(bus, dev)))
873			return;
874	}
875	iowrite16(value, bus->mmio + offset);
876}
877
878static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
879{
880	struct ssb_bus *bus = dev->bus;
881
882	if (unlikely(ssb_pci_assert_buspower(bus)))
883		return;
884	if (unlikely(bus->mapped_device != dev)) {
885		if (unlikely(ssb_pci_switch_core(bus, dev)))
886			return;
887	}
888	iowrite32(value, bus->mmio + offset);
889}
890
891#ifdef CONFIG_SSB_BLOCKIO
892static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
893				size_t count, u16 offset, u8 reg_width)
894{
895	struct ssb_bus *bus = dev->bus;
896	void __iomem *addr = bus->mmio + offset;
897
898	if (unlikely(ssb_pci_assert_buspower(bus)))
899		return;
900	if (unlikely(bus->mapped_device != dev)) {
901		if (unlikely(ssb_pci_switch_core(bus, dev)))
902			return;
903	}
904	switch (reg_width) {
905	case sizeof(u8):
906		iowrite8_rep(addr, buffer, count);
907		break;
908	case sizeof(u16):
909		SSB_WARN_ON(count & 1);
910		iowrite16_rep(addr, buffer, count >> 1);
911		break;
912	case sizeof(u32):
913		SSB_WARN_ON(count & 3);
914		iowrite32_rep(addr, buffer, count >> 2);
915		break;
916	default:
917		SSB_WARN_ON(1);
918	}
919}
920#endif /* CONFIG_SSB_BLOCKIO */
921
922/* Not "static", as it's used in main.c */
923const struct ssb_bus_ops ssb_pci_ops = {
924	.read8		= ssb_pci_read8,
925	.read16		= ssb_pci_read16,
926	.read32		= ssb_pci_read32,
927	.write8		= ssb_pci_write8,
928	.write16	= ssb_pci_write16,
929	.write32	= ssb_pci_write32,
930#ifdef CONFIG_SSB_BLOCKIO
931	.block_read	= ssb_pci_block_read,
932	.block_write	= ssb_pci_block_write,
933#endif
934};
935
936static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
937				       struct device_attribute *attr,
938				       char *buf)
939{
940	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
941	struct ssb_bus *bus;
942
943	bus = ssb_pci_dev_to_bus(pdev);
944	if (!bus)
945		return -ENODEV;
946
947	return ssb_attr_sprom_show(bus, buf, sprom_do_read);
948}
949
950static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
951					struct device_attribute *attr,
952					const char *buf, size_t count)
953{
954	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
955	struct ssb_bus *bus;
956
957	bus = ssb_pci_dev_to_bus(pdev);
958	if (!bus)
959		return -ENODEV;
960
961	return ssb_attr_sprom_store(bus, buf, count,
962				    sprom_check_crc, sprom_do_write);
963}
964
965static DEVICE_ATTR(ssb_sprom, 0600,
966		   ssb_pci_attr_sprom_show,
967		   ssb_pci_attr_sprom_store);
968
969void ssb_pci_exit(struct ssb_bus *bus)
970{
971	struct pci_dev *pdev;
972
973	if (bus->bustype != SSB_BUSTYPE_PCI)
974		return;
975
976	pdev = bus->host_pci;
977	device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
978}
979
980int ssb_pci_init(struct ssb_bus *bus)
981{
982	struct pci_dev *pdev;
983	int err;
984
985	if (bus->bustype != SSB_BUSTYPE_PCI)
986		return 0;
987
988	pdev = bus->host_pci;
989	mutex_init(&bus->sprom_mutex);
990	err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
991	if (err)
992		goto out;
993
994out:
995	return err;
996}
v3.5.6
   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 */
  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#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
 194static 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
 234static 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
 249static 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
 264static 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
 274static 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;
 316err_ctlreg:
 317	ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
 318	return err;
 319}
 320
 321static 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
 342static 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 */
 416static 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
 455static 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
 530static 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
 740static 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
 787static 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
 854out_free:
 855	kfree(buf);
 856	return err;
 857}
 858
 859static 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
 866int 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
 876out:
 877	return err;
 878}
 879
 880#ifdef CONFIG_SSB_DEBUG
 881static 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 */
 896static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
 897{
 898	return 0;
 899}
 900#endif /* DEBUG */
 901
 902static 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
 915static 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
 928static 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
 942static 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;
 971error:
 972	memset(buffer, 0xFF, count);
 973}
 974#endif /* CONFIG_SSB_BLOCKIO */
 975
 976static 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
 989static 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
1002static 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
1016static 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 */
1047const 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
1060static 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
1074static 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
1089static DEVICE_ATTR(ssb_sprom, 0600,
1090		   ssb_pci_attr_sprom_show,
1091		   ssb_pci_attr_sprom_store);
1092
1093void 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
1104int 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
1118out:
1119	return err;
1120}