Linux Audio

Check our new training course

Loading...
v4.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_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			} else {
 913				ssb_dbg("Using SPROM revision %d provided by platform\n",
 914					sprom->revision);
 
 915				err = 0;
 916				goto out_free;
 917			}
 918			ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
 
 919		}
 920	}
 921	err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 922
 923out_free:
 924	kfree(buf);
 925	return err;
 926}
 927
 928static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
 929				  struct ssb_boardinfo *bi)
 930{
 931	bi->vendor = bus->host_pci->subsystem_vendor;
 932	bi->type = bus->host_pci->subsystem_device;
 
 933}
 934
 935int ssb_pci_get_invariants(struct ssb_bus *bus,
 936			   struct ssb_init_invariants *iv)
 937{
 938	int err;
 939
 940	err = ssb_pci_sprom_get(bus, &iv->sprom);
 941	if (err)
 942		goto out;
 943	ssb_pci_get_boardinfo(bus, &iv->boardinfo);
 944
 945out:
 946	return err;
 947}
 948
 949#ifdef CONFIG_SSB_DEBUG
 950static int ssb_pci_assert_buspower(struct ssb_bus *bus)
 951{
 952	if (likely(bus->powered_up))
 953		return 0;
 954
 955	printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
 956	       "while accessing PCI MMIO space\n");
 957	if (bus->power_warn_count <= 10) {
 958		bus->power_warn_count++;
 959		dump_stack();
 960	}
 961
 962	return -ENODEV;
 963}
 964#else /* DEBUG */
 965static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
 966{
 967	return 0;
 968}
 969#endif /* DEBUG */
 970
 971static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
 972{
 973	struct ssb_bus *bus = dev->bus;
 974
 975	if (unlikely(ssb_pci_assert_buspower(bus)))
 976		return 0xFF;
 977	if (unlikely(bus->mapped_device != dev)) {
 978		if (unlikely(ssb_pci_switch_core(bus, dev)))
 979			return 0xFF;
 980	}
 981	return ioread8(bus->mmio + offset);
 982}
 983
 984static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
 985{
 986	struct ssb_bus *bus = dev->bus;
 987
 988	if (unlikely(ssb_pci_assert_buspower(bus)))
 989		return 0xFFFF;
 990	if (unlikely(bus->mapped_device != dev)) {
 991		if (unlikely(ssb_pci_switch_core(bus, dev)))
 992			return 0xFFFF;
 993	}
 994	return ioread16(bus->mmio + offset);
 995}
 996
 997static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
 998{
 999	struct ssb_bus *bus = dev->bus;
1000
1001	if (unlikely(ssb_pci_assert_buspower(bus)))
1002		return 0xFFFFFFFF;
1003	if (unlikely(bus->mapped_device != dev)) {
1004		if (unlikely(ssb_pci_switch_core(bus, dev)))
1005			return 0xFFFFFFFF;
1006	}
1007	return ioread32(bus->mmio + offset);
1008}
1009
1010#ifdef CONFIG_SSB_BLOCKIO
1011static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
1012			       size_t count, u16 offset, u8 reg_width)
1013{
1014	struct ssb_bus *bus = dev->bus;
1015	void __iomem *addr = bus->mmio + offset;
1016
1017	if (unlikely(ssb_pci_assert_buspower(bus)))
1018		goto error;
1019	if (unlikely(bus->mapped_device != dev)) {
1020		if (unlikely(ssb_pci_switch_core(bus, dev)))
1021			goto error;
1022	}
1023	switch (reg_width) {
1024	case sizeof(u8):
1025		ioread8_rep(addr, buffer, count);
1026		break;
1027	case sizeof(u16):
1028		SSB_WARN_ON(count & 1);
1029		ioread16_rep(addr, buffer, count >> 1);
1030		break;
1031	case sizeof(u32):
1032		SSB_WARN_ON(count & 3);
1033		ioread32_rep(addr, buffer, count >> 2);
1034		break;
1035	default:
1036		SSB_WARN_ON(1);
1037	}
1038
1039	return;
1040error:
1041	memset(buffer, 0xFF, count);
1042}
1043#endif /* CONFIG_SSB_BLOCKIO */
1044
1045static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
1046{
1047	struct ssb_bus *bus = dev->bus;
1048
1049	if (unlikely(ssb_pci_assert_buspower(bus)))
1050		return;
1051	if (unlikely(bus->mapped_device != dev)) {
1052		if (unlikely(ssb_pci_switch_core(bus, dev)))
1053			return;
1054	}
1055	iowrite8(value, bus->mmio + offset);
1056}
1057
1058static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
1059{
1060	struct ssb_bus *bus = dev->bus;
1061
1062	if (unlikely(ssb_pci_assert_buspower(bus)))
1063		return;
1064	if (unlikely(bus->mapped_device != dev)) {
1065		if (unlikely(ssb_pci_switch_core(bus, dev)))
1066			return;
1067	}
1068	iowrite16(value, bus->mmio + offset);
1069}
1070
1071static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
1072{
1073	struct ssb_bus *bus = dev->bus;
1074
1075	if (unlikely(ssb_pci_assert_buspower(bus)))
1076		return;
1077	if (unlikely(bus->mapped_device != dev)) {
1078		if (unlikely(ssb_pci_switch_core(bus, dev)))
1079			return;
1080	}
1081	iowrite32(value, bus->mmio + offset);
1082}
1083
1084#ifdef CONFIG_SSB_BLOCKIO
1085static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1086				size_t count, u16 offset, u8 reg_width)
1087{
1088	struct ssb_bus *bus = dev->bus;
1089	void __iomem *addr = bus->mmio + offset;
1090
1091	if (unlikely(ssb_pci_assert_buspower(bus)))
1092		return;
1093	if (unlikely(bus->mapped_device != dev)) {
1094		if (unlikely(ssb_pci_switch_core(bus, dev)))
1095			return;
1096	}
1097	switch (reg_width) {
1098	case sizeof(u8):
1099		iowrite8_rep(addr, buffer, count);
1100		break;
1101	case sizeof(u16):
1102		SSB_WARN_ON(count & 1);
1103		iowrite16_rep(addr, buffer, count >> 1);
1104		break;
1105	case sizeof(u32):
1106		SSB_WARN_ON(count & 3);
1107		iowrite32_rep(addr, buffer, count >> 2);
1108		break;
1109	default:
1110		SSB_WARN_ON(1);
1111	}
1112}
1113#endif /* CONFIG_SSB_BLOCKIO */
1114
1115/* Not "static", as it's used in main.c */
1116const struct ssb_bus_ops ssb_pci_ops = {
1117	.read8		= ssb_pci_read8,
1118	.read16		= ssb_pci_read16,
1119	.read32		= ssb_pci_read32,
1120	.write8		= ssb_pci_write8,
1121	.write16	= ssb_pci_write16,
1122	.write32	= ssb_pci_write32,
1123#ifdef CONFIG_SSB_BLOCKIO
1124	.block_read	= ssb_pci_block_read,
1125	.block_write	= ssb_pci_block_write,
1126#endif
1127};
1128
1129static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
1130				       struct device_attribute *attr,
1131				       char *buf)
1132{
1133	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1134	struct ssb_bus *bus;
1135
1136	bus = ssb_pci_dev_to_bus(pdev);
1137	if (!bus)
1138		return -ENODEV;
1139
1140	return ssb_attr_sprom_show(bus, buf, sprom_do_read);
1141}
1142
1143static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
1144					struct device_attribute *attr,
1145					const char *buf, size_t count)
1146{
1147	struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1148	struct ssb_bus *bus;
1149
1150	bus = ssb_pci_dev_to_bus(pdev);
1151	if (!bus)
1152		return -ENODEV;
1153
1154	return ssb_attr_sprom_store(bus, buf, count,
1155				    sprom_check_crc, sprom_do_write);
1156}
1157
1158static DEVICE_ATTR(ssb_sprom, 0600,
1159		   ssb_pci_attr_sprom_show,
1160		   ssb_pci_attr_sprom_store);
1161
1162void ssb_pci_exit(struct ssb_bus *bus)
1163{
1164	struct pci_dev *pdev;
1165
1166	if (bus->bustype != SSB_BUSTYPE_PCI)
1167		return;
1168
1169	pdev = bus->host_pci;
1170	device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1171}
1172
1173int ssb_pci_init(struct ssb_bus *bus)
1174{
1175	struct pci_dev *pdev;
1176	int err;
1177
1178	if (bus->bustype != SSB_BUSTYPE_PCI)
1179		return 0;
1180
1181	pdev = bus->host_pci;
1182	mutex_init(&bus->sprom_mutex);
1183	err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1184	if (err)
1185		goto out;
1186
1187out:
1188	return err;
1189}
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}