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