Linux Audio

Check our new training course

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