Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Sonics Silicon Backplane PCI-Hostbus related functions.
0003  *
0004  * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
0005  * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
0006  * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
0007  * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
0008  * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
0009  *
0010  * Derived from the Broadcom 4400 device driver.
0011  * Copyright (C) 2002 David S. Miller (davem@redhat.com)
0012  * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
0013  * Copyright (C) 2006 Broadcom Corporation.
0014  *
0015  * Licensed under the GNU/GPL. See COPYING for details.
0016  */
0017 
0018 #include "ssb_private.h"
0019 
0020 #include <linux/ssb/ssb.h>
0021 #include <linux/ssb/ssb_regs.h>
0022 #include <linux/slab.h>
0023 #include <linux/pci.h>
0024 #include <linux/delay.h>
0025 
0026 
0027 /* Define the following to 1 to enable a printk on each coreswitch. */
0028 #define SSB_VERBOSE_PCICORESWITCH_DEBUG     0
0029 
0030 
0031 /* Lowlevel coreswitching */
0032 int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
0033 {
0034     int err;
0035     int attempts = 0;
0036     u32 cur_core;
0037 
0038     while (1) {
0039         err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
0040                          (coreidx * SSB_CORE_SIZE)
0041                          + SSB_ENUM_BASE);
0042         if (err)
0043             goto error;
0044         err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
0045                         &cur_core);
0046         if (err)
0047             goto error;
0048         cur_core = (cur_core - SSB_ENUM_BASE)
0049                / SSB_CORE_SIZE;
0050         if (cur_core == coreidx)
0051             break;
0052 
0053         if (attempts++ > SSB_BAR0_MAX_RETRIES)
0054             goto error;
0055         udelay(10);
0056     }
0057     return 0;
0058 error:
0059     pr_err("Failed to switch to core %u\n", coreidx);
0060     return -ENODEV;
0061 }
0062 
0063 int ssb_pci_switch_core(struct ssb_bus *bus,
0064             struct ssb_device *dev)
0065 {
0066     int err;
0067     unsigned long flags;
0068 
0069 #if SSB_VERBOSE_PCICORESWITCH_DEBUG
0070     pr_info("Switching to %s core, index %d\n",
0071         ssb_core_name(dev->id.coreid), dev->core_index);
0072 #endif
0073 
0074     spin_lock_irqsave(&bus->bar_lock, flags);
0075     err = ssb_pci_switch_coreidx(bus, dev->core_index);
0076     if (!err)
0077         bus->mapped_device = dev;
0078     spin_unlock_irqrestore(&bus->bar_lock, flags);
0079 
0080     return err;
0081 }
0082 
0083 /* Enable/disable the on board crystal oscillator and/or PLL. */
0084 int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
0085 {
0086     int err;
0087     u32 in, out, outenable;
0088     u16 pci_status;
0089 
0090     if (bus->bustype != SSB_BUSTYPE_PCI)
0091         return 0;
0092 
0093     err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
0094     if (err)
0095         goto err_pci;
0096     err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
0097     if (err)
0098         goto err_pci;
0099     err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
0100     if (err)
0101         goto err_pci;
0102 
0103     outenable |= what;
0104 
0105     if (turn_on) {
0106         /* Avoid glitching the clock if GPRS is already using it.
0107          * We can't actually read the state of the PLLPD so we infer it
0108          * by the value of XTAL_PU which *is* readable via gpioin.
0109          */
0110         if (!(in & SSB_GPIO_XTAL)) {
0111             if (what & SSB_GPIO_XTAL) {
0112                 /* Turn the crystal on */
0113                 out |= SSB_GPIO_XTAL;
0114                 if (what & SSB_GPIO_PLL)
0115                     out |= SSB_GPIO_PLL;
0116                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
0117                 if (err)
0118                     goto err_pci;
0119                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
0120                                  outenable);
0121                 if (err)
0122                     goto err_pci;
0123                 msleep(1);
0124             }
0125             if (what & SSB_GPIO_PLL) {
0126                 /* Turn the PLL on */
0127                 out &= ~SSB_GPIO_PLL;
0128                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
0129                 if (err)
0130                     goto err_pci;
0131                 msleep(5);
0132             }
0133         }
0134 
0135         err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
0136         if (err)
0137             goto err_pci;
0138         pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
0139         err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
0140         if (err)
0141             goto err_pci;
0142     } else {
0143         if (what & SSB_GPIO_XTAL) {
0144             /* Turn the crystal off */
0145             out &= ~SSB_GPIO_XTAL;
0146         }
0147         if (what & SSB_GPIO_PLL) {
0148             /* Turn the PLL off */
0149             out |= SSB_GPIO_PLL;
0150         }
0151         err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
0152         if (err)
0153             goto err_pci;
0154         err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
0155         if (err)
0156             goto err_pci;
0157     }
0158 
0159 out:
0160     return err;
0161 
0162 err_pci:
0163     pr_err("Error: ssb_pci_xtal() could not access PCI config space!\n");
0164     err = -EBUSY;
0165     goto out;
0166 }
0167 
0168 /* Get the word-offset for a SSB_SPROM_XXX define. */
0169 #define SPOFF(offset)   ((offset) / sizeof(u16))
0170 /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
0171 #define SPEX16(_outvar, _offset, _mask, _shift) \
0172     out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
0173 #define SPEX32(_outvar, _offset, _mask, _shift) \
0174     out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
0175                in[SPOFF(_offset)]) & (_mask)) >> (_shift))
0176 #define SPEX(_outvar, _offset, _mask, _shift) \
0177     SPEX16(_outvar, _offset, _mask, _shift)
0178 
0179 #define SPEX_ARRAY8(_field, _offset, _mask, _shift) \
0180     do {    \
0181         SPEX(_field[0], _offset +  0, _mask, _shift);   \
0182         SPEX(_field[1], _offset +  2, _mask, _shift);   \
0183         SPEX(_field[2], _offset +  4, _mask, _shift);   \
0184         SPEX(_field[3], _offset +  6, _mask, _shift);   \
0185         SPEX(_field[4], _offset +  8, _mask, _shift);   \
0186         SPEX(_field[5], _offset + 10, _mask, _shift);   \
0187         SPEX(_field[6], _offset + 12, _mask, _shift);   \
0188         SPEX(_field[7], _offset + 14, _mask, _shift);   \
0189     } while (0)
0190 
0191 
0192 static inline u8 ssb_crc8(u8 crc, u8 data)
0193 {
0194     /* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
0195     static const u8 t[] = {
0196         0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
0197         0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
0198         0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
0199         0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
0200         0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
0201         0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
0202         0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
0203         0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
0204         0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
0205         0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
0206         0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
0207         0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
0208         0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
0209         0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
0210         0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
0211         0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
0212         0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
0213         0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
0214         0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
0215         0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
0216         0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
0217         0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
0218         0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
0219         0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
0220         0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
0221         0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
0222         0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
0223         0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
0224         0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
0225         0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
0226         0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
0227         0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
0228     };
0229     return t[crc ^ data];
0230 }
0231 
0232 static void sprom_get_mac(char *mac, const u16 *in)
0233 {
0234     int i;
0235     for (i = 0; i < 3; i++) {
0236         *mac++ = in[i] >> 8;
0237         *mac++ = in[i];
0238     }
0239 }
0240 
0241 static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
0242 {
0243     int word;
0244     u8 crc = 0xFF;
0245 
0246     for (word = 0; word < size - 1; word++) {
0247         crc = ssb_crc8(crc, sprom[word] & 0x00FF);
0248         crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
0249     }
0250     crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
0251     crc ^= 0xFF;
0252 
0253     return crc;
0254 }
0255 
0256 static int sprom_check_crc(const u16 *sprom, size_t size)
0257 {
0258     u8 crc;
0259     u8 expected_crc;
0260     u16 tmp;
0261 
0262     crc = ssb_sprom_crc(sprom, size);
0263     tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
0264     expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
0265     if (crc != expected_crc)
0266         return -EPROTO;
0267 
0268     return 0;
0269 }
0270 
0271 static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
0272 {
0273     int i;
0274 
0275     for (i = 0; i < bus->sprom_size; i++)
0276         sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
0277 
0278     return 0;
0279 }
0280 
0281 static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
0282 {
0283     struct pci_dev *pdev = bus->host_pci;
0284     int i, err;
0285     u32 spromctl;
0286     u16 size = bus->sprom_size;
0287 
0288     pr_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
0289     err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
0290     if (err)
0291         goto err_ctlreg;
0292     spromctl |= SSB_SPROMCTL_WE;
0293     err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
0294     if (err)
0295         goto err_ctlreg;
0296     pr_notice("[ 0%%");
0297     msleep(500);
0298     for (i = 0; i < size; i++) {
0299         if (i == size / 4)
0300             pr_cont("25%%");
0301         else if (i == size / 2)
0302             pr_cont("50%%");
0303         else if (i == (size * 3) / 4)
0304             pr_cont("75%%");
0305         else if (i % 2)
0306             pr_cont(".");
0307         writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
0308         msleep(20);
0309     }
0310     err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
0311     if (err)
0312         goto err_ctlreg;
0313     spromctl &= ~SSB_SPROMCTL_WE;
0314     err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
0315     if (err)
0316         goto err_ctlreg;
0317     msleep(500);
0318     pr_cont("100%% ]\n");
0319     pr_notice("SPROM written\n");
0320 
0321     return 0;
0322 err_ctlreg:
0323     pr_err("Could not access SPROM control register.\n");
0324     return err;
0325 }
0326 
0327 static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset,
0328                 u16 mask, u16 shift)
0329 {
0330     u16 v;
0331     u8 gain;
0332 
0333     v = in[SPOFF(offset)];
0334     gain = (v & mask) >> shift;
0335     if (gain == 0xFF)
0336         gain = 2; /* If unset use 2dBm */
0337     if (sprom_revision == 1) {
0338         /* Convert to Q5.2 */
0339         gain <<= 2;
0340     } else {
0341         /* Q5.2 Fractional part is stored in 0xC0 */
0342         gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
0343     }
0344 
0345     return (s8)gain;
0346 }
0347 
0348 static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in)
0349 {
0350     SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
0351     SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
0352     SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
0353     SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
0354     SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
0355     SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
0356     SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
0357     SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
0358     SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
0359     SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
0360          SSB_SPROM2_MAXP_A_LO_SHIFT);
0361 }
0362 
0363 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
0364 {
0365     u16 loc[3];
0366 
0367     if (out->revision == 3)         /* rev 3 moved MAC */
0368         loc[0] = SSB_SPROM3_IL0MAC;
0369     else {
0370         loc[0] = SSB_SPROM1_IL0MAC;
0371         loc[1] = SSB_SPROM1_ET0MAC;
0372         loc[2] = SSB_SPROM1_ET1MAC;
0373     }
0374     sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
0375     if (out->revision < 3) {    /* only rev 1-2 have et0, et1 */
0376         sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
0377         sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
0378     }
0379     SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
0380     SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
0381          SSB_SPROM1_ETHPHY_ET1A_SHIFT);
0382     SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
0383     SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
0384     SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
0385     SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
0386     if (out->revision == 1)
0387         SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
0388              SSB_SPROM1_BINF_CCODE_SHIFT);
0389     SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
0390          SSB_SPROM1_BINF_ANTA_SHIFT);
0391     SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
0392          SSB_SPROM1_BINF_ANTBG_SHIFT);
0393     SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
0394     SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
0395     SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
0396     SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
0397     SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
0398     SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
0399     SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
0400     SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
0401          SSB_SPROM1_GPIOA_P1_SHIFT);
0402     SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
0403     SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
0404          SSB_SPROM1_GPIOB_P3_SHIFT);
0405     SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
0406          SSB_SPROM1_MAXPWR_A_SHIFT);
0407     SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
0408     SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
0409          SSB_SPROM1_ITSSI_A_SHIFT);
0410     SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
0411     SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
0412 
0413     SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
0414     SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
0415 
0416     /* Extract the antenna gain values. */
0417     out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
0418                              SSB_SPROM1_AGAIN,
0419                              SSB_SPROM1_AGAIN_BG,
0420                              SSB_SPROM1_AGAIN_BG_SHIFT);
0421     out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
0422                              SSB_SPROM1_AGAIN,
0423                              SSB_SPROM1_AGAIN_A,
0424                              SSB_SPROM1_AGAIN_A_SHIFT);
0425     if (out->revision >= 2)
0426         sprom_extract_r23(out, in);
0427 }
0428 
0429 /* Revs 4 5 and 8 have partially shared layout */
0430 static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
0431 {
0432     SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
0433          SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
0434     SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
0435          SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
0436     SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
0437          SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
0438     SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
0439          SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
0440 
0441     SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
0442          SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
0443     SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
0444          SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
0445     SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
0446          SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
0447     SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
0448          SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
0449 
0450     SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
0451          SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
0452     SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
0453          SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
0454     SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
0455          SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
0456     SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
0457          SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
0458 
0459     SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
0460          SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
0461     SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
0462          SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
0463     SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
0464          SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
0465     SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
0466          SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
0467 }
0468 
0469 static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
0470 {
0471     static const u16 pwr_info_offset[] = {
0472         SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1,
0473         SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3
0474     };
0475     u16 il0mac_offset;
0476     int i;
0477 
0478     BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
0479              ARRAY_SIZE(out->core_pwr_info));
0480 
0481     if (out->revision == 4)
0482         il0mac_offset = SSB_SPROM4_IL0MAC;
0483     else
0484         il0mac_offset = SSB_SPROM5_IL0MAC;
0485 
0486     sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
0487 
0488     SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
0489     SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
0490          SSB_SPROM4_ETHPHY_ET1A_SHIFT);
0491     SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
0492     SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
0493     if (out->revision == 4) {
0494         SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
0495         SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
0496         SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
0497         SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
0498         SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
0499         SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
0500     } else {
0501         SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
0502         SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
0503         SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
0504         SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
0505         SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
0506         SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
0507     }
0508     SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
0509          SSB_SPROM4_ANTAVAIL_A_SHIFT);
0510     SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
0511          SSB_SPROM4_ANTAVAIL_BG_SHIFT);
0512     SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
0513     SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
0514          SSB_SPROM4_ITSSI_BG_SHIFT);
0515     SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
0516     SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
0517          SSB_SPROM4_ITSSI_A_SHIFT);
0518     if (out->revision == 4) {
0519         SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
0520         SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
0521              SSB_SPROM4_GPIOA_P1_SHIFT);
0522         SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
0523         SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
0524              SSB_SPROM4_GPIOB_P3_SHIFT);
0525     } else {
0526         SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
0527         SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
0528              SSB_SPROM5_GPIOA_P1_SHIFT);
0529         SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
0530         SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
0531              SSB_SPROM5_GPIOB_P3_SHIFT);
0532     }
0533 
0534     /* Extract the antenna gain values. */
0535     out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
0536                              SSB_SPROM4_AGAIN01,
0537                              SSB_SPROM4_AGAIN0,
0538                              SSB_SPROM4_AGAIN0_SHIFT);
0539     out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
0540                              SSB_SPROM4_AGAIN01,
0541                              SSB_SPROM4_AGAIN1,
0542                              SSB_SPROM4_AGAIN1_SHIFT);
0543     out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
0544                              SSB_SPROM4_AGAIN23,
0545                              SSB_SPROM4_AGAIN2,
0546                              SSB_SPROM4_AGAIN2_SHIFT);
0547     out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
0548                              SSB_SPROM4_AGAIN23,
0549                              SSB_SPROM4_AGAIN3,
0550                              SSB_SPROM4_AGAIN3_SHIFT);
0551 
0552     /* Extract cores power info info */
0553     for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
0554         u16 o = pwr_info_offset[i];
0555 
0556         SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
0557             SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT);
0558         SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
0559             SSB_SPROM4_2G_MAXP, 0);
0560 
0561         SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0);
0562         SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0);
0563         SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0);
0564         SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0);
0565 
0566         SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
0567             SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT);
0568         SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
0569             SSB_SPROM4_5G_MAXP, 0);
0570         SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP,
0571             SSB_SPROM4_5GH_MAXP, 0);
0572         SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP,
0573             SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT);
0574 
0575         SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0);
0576         SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0);
0577         SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0);
0578         SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0);
0579         SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0);
0580         SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0);
0581         SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0);
0582         SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0);
0583         SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0);
0584         SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0);
0585         SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0);
0586         SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0);
0587     }
0588 
0589     sprom_extract_r458(out, in);
0590 
0591     /* TODO - get remaining rev 4 stuff needed */
0592 }
0593 
0594 static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
0595 {
0596     int i;
0597     u16 o;
0598     static const u16 pwr_info_offset[] = {
0599         SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
0600         SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
0601     };
0602     BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
0603             ARRAY_SIZE(out->core_pwr_info));
0604 
0605     /* extract the MAC address */
0606     sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
0607 
0608     SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
0609     SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
0610     SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
0611     SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
0612     SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
0613     SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
0614     SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
0615     SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
0616     SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
0617          SSB_SPROM8_ANTAVAIL_A_SHIFT);
0618     SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
0619          SSB_SPROM8_ANTAVAIL_BG_SHIFT);
0620     SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
0621     SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
0622          SSB_SPROM8_ITSSI_BG_SHIFT);
0623     SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
0624     SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
0625          SSB_SPROM8_ITSSI_A_SHIFT);
0626     SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
0627     SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
0628          SSB_SPROM8_MAXP_AL_SHIFT);
0629     SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
0630     SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
0631          SSB_SPROM8_GPIOA_P1_SHIFT);
0632     SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
0633     SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
0634          SSB_SPROM8_GPIOB_P3_SHIFT);
0635     SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
0636     SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
0637          SSB_SPROM8_TRI5G_SHIFT);
0638     SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
0639     SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
0640          SSB_SPROM8_TRI5GH_SHIFT);
0641     SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
0642     SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
0643          SSB_SPROM8_RXPO5G_SHIFT);
0644     SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
0645     SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
0646          SSB_SPROM8_RSSISMC2G_SHIFT);
0647     SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
0648          SSB_SPROM8_RSSISAV2G_SHIFT);
0649     SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
0650          SSB_SPROM8_BXA2G_SHIFT);
0651     SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
0652     SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
0653          SSB_SPROM8_RSSISMC5G_SHIFT);
0654     SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
0655          SSB_SPROM8_RSSISAV5G_SHIFT);
0656     SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
0657          SSB_SPROM8_BXA5G_SHIFT);
0658     SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
0659     SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
0660     SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
0661     SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
0662     SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
0663     SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
0664     SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
0665     SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
0666     SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
0667     SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
0668     SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
0669     SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
0670     SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
0671     SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
0672     SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
0673     SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
0674     SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
0675 
0676     /* Extract the antenna gain values. */
0677     out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
0678                              SSB_SPROM8_AGAIN01,
0679                              SSB_SPROM8_AGAIN0,
0680                              SSB_SPROM8_AGAIN0_SHIFT);
0681     out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
0682                              SSB_SPROM8_AGAIN01,
0683                              SSB_SPROM8_AGAIN1,
0684                              SSB_SPROM8_AGAIN1_SHIFT);
0685     out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
0686                              SSB_SPROM8_AGAIN23,
0687                              SSB_SPROM8_AGAIN2,
0688                              SSB_SPROM8_AGAIN2_SHIFT);
0689     out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
0690                              SSB_SPROM8_AGAIN23,
0691                              SSB_SPROM8_AGAIN3,
0692                              SSB_SPROM8_AGAIN3_SHIFT);
0693 
0694     /* Extract cores power info info */
0695     for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
0696         o = pwr_info_offset[i];
0697         SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
0698             SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
0699         SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
0700             SSB_SPROM8_2G_MAXP, 0);
0701 
0702         SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
0703         SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
0704         SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
0705 
0706         SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
0707             SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
0708         SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
0709             SSB_SPROM8_5G_MAXP, 0);
0710         SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
0711             SSB_SPROM8_5GH_MAXP, 0);
0712         SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
0713             SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
0714 
0715         SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
0716         SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
0717         SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
0718         SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
0719         SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
0720         SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
0721         SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
0722         SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
0723         SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
0724     }
0725 
0726     /* Extract FEM info */
0727     SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
0728         SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
0729     SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
0730         SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
0731     SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
0732         SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
0733     SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
0734         SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
0735     SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
0736         SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
0737 
0738     SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
0739         SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
0740     SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
0741         SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
0742     SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
0743         SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
0744     SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
0745         SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
0746     SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
0747         SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
0748 
0749     SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
0750          SSB_SPROM8_LEDDC_ON_SHIFT);
0751     SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
0752          SSB_SPROM8_LEDDC_OFF_SHIFT);
0753 
0754     SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
0755          SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
0756     SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
0757          SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
0758     SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
0759          SSB_SPROM8_TXRXC_SWITCH_SHIFT);
0760 
0761     SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
0762 
0763     SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
0764     SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
0765     SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
0766     SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
0767 
0768     SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
0769          SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
0770     SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
0771          SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
0772     SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
0773          SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
0774          SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
0775     SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
0776          SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
0777     SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
0778          SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
0779          SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
0780     SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
0781          SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
0782          SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
0783     SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
0784          SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
0785          SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
0786     SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
0787          SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
0788 
0789     SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
0790     SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
0791     SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
0792     SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
0793 
0794     SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
0795          SSB_SPROM8_THERMAL_TRESH_SHIFT);
0796     SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
0797          SSB_SPROM8_THERMAL_OFFSET_SHIFT);
0798     SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
0799          SSB_SPROM8_TEMPDELTA_PHYCAL,
0800          SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
0801     SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
0802          SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
0803     SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
0804          SSB_SPROM8_TEMPDELTA_HYSTERESIS,
0805          SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
0806     sprom_extract_r458(out, in);
0807 
0808     /* TODO - get remaining rev 8 stuff needed */
0809 }
0810 
0811 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
0812              const u16 *in, u16 size)
0813 {
0814     memset(out, 0, sizeof(*out));
0815 
0816     out->revision = in[size - 1] & 0x00FF;
0817     pr_debug("SPROM revision %d detected\n", out->revision);
0818     memset(out->et0mac, 0xFF, 6);       /* preset et0 and et1 mac */
0819     memset(out->et1mac, 0xFF, 6);
0820 
0821     if ((bus->chip_id & 0xFF00) == 0x4400) {
0822         /* Workaround: The BCM44XX chip has a stupid revision
0823          * number stored in the SPROM.
0824          * Always extract r1. */
0825         out->revision = 1;
0826         pr_debug("SPROM treated as revision %d\n", out->revision);
0827     }
0828 
0829     switch (out->revision) {
0830     case 1:
0831     case 2:
0832     case 3:
0833         sprom_extract_r123(out, in);
0834         break;
0835     case 4:
0836     case 5:
0837         sprom_extract_r45(out, in);
0838         break;
0839     case 8:
0840         sprom_extract_r8(out, in);
0841         break;
0842     default:
0843         pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
0844             out->revision);
0845         out->revision = 1;
0846         sprom_extract_r123(out, in);
0847     }
0848 
0849     if (out->boardflags_lo == 0xFFFF)
0850         out->boardflags_lo = 0;  /* per specs */
0851     if (out->boardflags_hi == 0xFFFF)
0852         out->boardflags_hi = 0;  /* per specs */
0853 
0854     return 0;
0855 }
0856 
0857 static int ssb_pci_sprom_get(struct ssb_bus *bus,
0858                  struct ssb_sprom *sprom)
0859 {
0860     int err;
0861     u16 *buf;
0862 
0863     if (!ssb_is_sprom_available(bus)) {
0864         pr_err("No SPROM available!\n");
0865         return -ENODEV;
0866     }
0867     if (bus->chipco.dev) {  /* can be unavailable! */
0868         /*
0869          * get SPROM offset: SSB_SPROM_BASE1 except for
0870          * chipcommon rev >= 31 or chip ID is 0x4312 and
0871          * chipcommon status & 3 == 2
0872          */
0873         if (bus->chipco.dev->id.revision >= 31)
0874             bus->sprom_offset = SSB_SPROM_BASE31;
0875         else if (bus->chip_id == 0x4312 &&
0876              (bus->chipco.status & 0x03) == 2)
0877             bus->sprom_offset = SSB_SPROM_BASE31;
0878         else
0879             bus->sprom_offset = SSB_SPROM_BASE1;
0880     } else {
0881         bus->sprom_offset = SSB_SPROM_BASE1;
0882     }
0883     pr_debug("SPROM offset is 0x%x\n", bus->sprom_offset);
0884 
0885     buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
0886     if (!buf)
0887         return -ENOMEM;
0888     bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
0889     sprom_do_read(bus, buf);
0890     err = sprom_check_crc(buf, bus->sprom_size);
0891     if (err) {
0892         /* try for a 440 byte SPROM - revision 4 and higher */
0893         kfree(buf);
0894         buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
0895                   GFP_KERNEL);
0896         if (!buf)
0897             return -ENOMEM;
0898         bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
0899         sprom_do_read(bus, buf);
0900         err = sprom_check_crc(buf, bus->sprom_size);
0901         if (err) {
0902             /* All CRC attempts failed.
0903              * Maybe there is no SPROM on the device?
0904              * Now we ask the arch code if there is some sprom
0905              * available for this device in some other storage */
0906             err = ssb_fill_sprom_with_fallback(bus, sprom);
0907             if (err) {
0908                 pr_warn("WARNING: Using fallback SPROM failed (err %d)\n",
0909                     err);
0910                 goto out_free;
0911             } else {
0912                 pr_debug("Using SPROM revision %d provided by platform\n",
0913                      sprom->revision);
0914                 err = 0;
0915                 goto out_free;
0916             }
0917         }
0918     }
0919     err = sprom_extract(bus, sprom, buf, bus->sprom_size);
0920 
0921 out_free:
0922     kfree(buf);
0923     return err;
0924 }
0925 
0926 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
0927                   struct ssb_boardinfo *bi)
0928 {
0929     bi->vendor = bus->host_pci->subsystem_vendor;
0930     bi->type = bus->host_pci->subsystem_device;
0931 }
0932 
0933 int ssb_pci_get_invariants(struct ssb_bus *bus,
0934                struct ssb_init_invariants *iv)
0935 {
0936     int err;
0937 
0938     err = ssb_pci_sprom_get(bus, &iv->sprom);
0939     if (err)
0940         goto out;
0941     ssb_pci_get_boardinfo(bus, &iv->boardinfo);
0942 
0943 out:
0944     return err;
0945 }
0946 
0947 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
0948 {
0949     if (likely(bus->powered_up))
0950         return 0;
0951 
0952     pr_err("FATAL ERROR: Bus powered down while accessing PCI MMIO space\n");
0953     if (bus->power_warn_count <= 10) {
0954         bus->power_warn_count++;
0955         dump_stack();
0956     }
0957 
0958     return -ENODEV;
0959 }
0960 
0961 static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
0962 {
0963     struct ssb_bus *bus = dev->bus;
0964 
0965     if (unlikely(ssb_pci_assert_buspower(bus)))
0966         return 0xFF;
0967     if (unlikely(bus->mapped_device != dev)) {
0968         if (unlikely(ssb_pci_switch_core(bus, dev)))
0969             return 0xFF;
0970     }
0971     return ioread8(bus->mmio + offset);
0972 }
0973 
0974 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
0975 {
0976     struct ssb_bus *bus = dev->bus;
0977 
0978     if (unlikely(ssb_pci_assert_buspower(bus)))
0979         return 0xFFFF;
0980     if (unlikely(bus->mapped_device != dev)) {
0981         if (unlikely(ssb_pci_switch_core(bus, dev)))
0982             return 0xFFFF;
0983     }
0984     return ioread16(bus->mmio + offset);
0985 }
0986 
0987 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
0988 {
0989     struct ssb_bus *bus = dev->bus;
0990 
0991     if (unlikely(ssb_pci_assert_buspower(bus)))
0992         return 0xFFFFFFFF;
0993     if (unlikely(bus->mapped_device != dev)) {
0994         if (unlikely(ssb_pci_switch_core(bus, dev)))
0995             return 0xFFFFFFFF;
0996     }
0997     return ioread32(bus->mmio + offset);
0998 }
0999 
1000 #ifdef CONFIG_SSB_BLOCKIO
1001 static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
1002                    size_t count, u16 offset, u8 reg_width)
1003 {
1004     struct ssb_bus *bus = dev->bus;
1005     void __iomem *addr = bus->mmio + offset;
1006 
1007     if (unlikely(ssb_pci_assert_buspower(bus)))
1008         goto error;
1009     if (unlikely(bus->mapped_device != dev)) {
1010         if (unlikely(ssb_pci_switch_core(bus, dev)))
1011             goto error;
1012     }
1013     switch (reg_width) {
1014     case sizeof(u8):
1015         ioread8_rep(addr, buffer, count);
1016         break;
1017     case sizeof(u16):
1018         WARN_ON(count & 1);
1019         ioread16_rep(addr, buffer, count >> 1);
1020         break;
1021     case sizeof(u32):
1022         WARN_ON(count & 3);
1023         ioread32_rep(addr, buffer, count >> 2);
1024         break;
1025     default:
1026         WARN_ON(1);
1027     }
1028 
1029     return;
1030 error:
1031     memset(buffer, 0xFF, count);
1032 }
1033 #endif /* CONFIG_SSB_BLOCKIO */
1034 
1035 static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
1036 {
1037     struct ssb_bus *bus = dev->bus;
1038 
1039     if (unlikely(ssb_pci_assert_buspower(bus)))
1040         return;
1041     if (unlikely(bus->mapped_device != dev)) {
1042         if (unlikely(ssb_pci_switch_core(bus, dev)))
1043             return;
1044     }
1045     iowrite8(value, bus->mmio + offset);
1046 }
1047 
1048 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
1049 {
1050     struct ssb_bus *bus = dev->bus;
1051 
1052     if (unlikely(ssb_pci_assert_buspower(bus)))
1053         return;
1054     if (unlikely(bus->mapped_device != dev)) {
1055         if (unlikely(ssb_pci_switch_core(bus, dev)))
1056             return;
1057     }
1058     iowrite16(value, bus->mmio + offset);
1059 }
1060 
1061 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
1062 {
1063     struct ssb_bus *bus = dev->bus;
1064 
1065     if (unlikely(ssb_pci_assert_buspower(bus)))
1066         return;
1067     if (unlikely(bus->mapped_device != dev)) {
1068         if (unlikely(ssb_pci_switch_core(bus, dev)))
1069             return;
1070     }
1071     iowrite32(value, bus->mmio + offset);
1072 }
1073 
1074 #ifdef CONFIG_SSB_BLOCKIO
1075 static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1076                 size_t count, u16 offset, u8 reg_width)
1077 {
1078     struct ssb_bus *bus = dev->bus;
1079     void __iomem *addr = bus->mmio + offset;
1080 
1081     if (unlikely(ssb_pci_assert_buspower(bus)))
1082         return;
1083     if (unlikely(bus->mapped_device != dev)) {
1084         if (unlikely(ssb_pci_switch_core(bus, dev)))
1085             return;
1086     }
1087     switch (reg_width) {
1088     case sizeof(u8):
1089         iowrite8_rep(addr, buffer, count);
1090         break;
1091     case sizeof(u16):
1092         WARN_ON(count & 1);
1093         iowrite16_rep(addr, buffer, count >> 1);
1094         break;
1095     case sizeof(u32):
1096         WARN_ON(count & 3);
1097         iowrite32_rep(addr, buffer, count >> 2);
1098         break;
1099     default:
1100         WARN_ON(1);
1101     }
1102 }
1103 #endif /* CONFIG_SSB_BLOCKIO */
1104 
1105 /* Not "static", as it's used in main.c */
1106 const struct ssb_bus_ops ssb_pci_ops = {
1107     .read8      = ssb_pci_read8,
1108     .read16     = ssb_pci_read16,
1109     .read32     = ssb_pci_read32,
1110     .write8     = ssb_pci_write8,
1111     .write16    = ssb_pci_write16,
1112     .write32    = ssb_pci_write32,
1113 #ifdef CONFIG_SSB_BLOCKIO
1114     .block_read = ssb_pci_block_read,
1115     .block_write    = ssb_pci_block_write,
1116 #endif
1117 };
1118 
1119 static ssize_t ssb_sprom_show(struct device *pcidev,
1120                   struct device_attribute *attr,
1121                   char *buf)
1122 {
1123     struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1124     struct ssb_bus *bus;
1125 
1126     bus = ssb_pci_dev_to_bus(pdev);
1127     if (!bus)
1128         return -ENODEV;
1129 
1130     return ssb_attr_sprom_show(bus, buf, sprom_do_read);
1131 }
1132 
1133 static ssize_t ssb_sprom_store(struct device *pcidev,
1134                    struct device_attribute *attr,
1135                    const char *buf, size_t count)
1136 {
1137     struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1138     struct ssb_bus *bus;
1139 
1140     bus = ssb_pci_dev_to_bus(pdev);
1141     if (!bus)
1142         return -ENODEV;
1143 
1144     return ssb_attr_sprom_store(bus, buf, count,
1145                     sprom_check_crc, sprom_do_write);
1146 }
1147 
1148 static DEVICE_ATTR_ADMIN_RW(ssb_sprom);
1149 
1150 void ssb_pci_exit(struct ssb_bus *bus)
1151 {
1152     struct pci_dev *pdev;
1153 
1154     if (bus->bustype != SSB_BUSTYPE_PCI)
1155         return;
1156 
1157     pdev = bus->host_pci;
1158     device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1159 }
1160 
1161 int ssb_pci_init(struct ssb_bus *bus)
1162 {
1163     struct pci_dev *pdev;
1164 
1165     if (bus->bustype != SSB_BUSTYPE_PCI)
1166         return 0;
1167 
1168     pdev = bus->host_pci;
1169     mutex_init(&bus->sprom_mutex);
1170 
1171     return device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1172 }