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