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