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 r123_extract_antgain(u8 sprom_revision, const u16 *in,
 330                               u16 mask, u16 shift)
 331{
 332        u16 v;
 333        u8 gain;
 334
 335        v = in[SPOFF(SSB_SPROM1_AGAIN)];
 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 = r123_extract_antgain(out->revision, in,
 420                                                    SSB_SPROM1_AGAIN_BG,
 421                                                    SSB_SPROM1_AGAIN_BG_SHIFT);
 422        out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
 423                                                    SSB_SPROM1_AGAIN_A,
 424                                                    SSB_SPROM1_AGAIN_A_SHIFT);
 425        if (out->revision >= 2)
 426                sprom_extract_r23(out, in);
 427}
 428
 429/* Revs 4 5 and 8 have partially shared layout */
 430static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
 431{
 432        SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
 433             SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
 434        SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
 435             SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
 436        SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
 437             SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
 438        SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
 439             SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
 440
 441        SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
 442             SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
 443        SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
 444             SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
 445        SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
 446             SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
 447        SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
 448             SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
 449
 450        SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
 451             SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
 452        SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
 453             SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
 454        SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
 455             SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
 456        SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
 457             SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
 458
 459        SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
 460             SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
 461        SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
 462             SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
 463        SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
 464             SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
 465        SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
 466             SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
 467}
 468
 469static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
 470{
 471        u16 il0mac_offset;
 472
 473        if (out->revision == 4)
 474                il0mac_offset = SSB_SPROM4_IL0MAC;
 475        else
 476                il0mac_offset = SSB_SPROM5_IL0MAC;
 477
 478        sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
 479
 480        SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
 481        SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
 482             SSB_SPROM4_ETHPHY_ET1A_SHIFT);
 483        SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
 484        SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
 485        if (out->revision == 4) {
 486                SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
 487                SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
 488                SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
 489                SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
 490                SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
 491                SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
 492        } else {
 493                SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
 494                SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
 495                SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
 496                SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
 497                SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
 498                SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
 499        }
 500        SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
 501             SSB_SPROM4_ANTAVAIL_A_SHIFT);
 502        SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
 503             SSB_SPROM4_ANTAVAIL_BG_SHIFT);
 504        SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
 505        SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
 506             SSB_SPROM4_ITSSI_BG_SHIFT);
 507        SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
 508        SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
 509             SSB_SPROM4_ITSSI_A_SHIFT);
 510        if (out->revision == 4) {
 511                SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
 512                SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
 513                     SSB_SPROM4_GPIOA_P1_SHIFT);
 514                SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
 515                SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
 516                     SSB_SPROM4_GPIOB_P3_SHIFT);
 517        } else {
 518                SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
 519                SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
 520                     SSB_SPROM5_GPIOA_P1_SHIFT);
 521                SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
 522                SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
 523                     SSB_SPROM5_GPIOB_P3_SHIFT);
 524        }
 525
 526        /* Extract the antenna gain values. */
 527        SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
 528             SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
 529        SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
 530             SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
 531        SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
 532             SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
 533        SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
 534             SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
 535
 536        sprom_extract_r458(out, in);
 537
 538        /* TODO - get remaining rev 4 stuff needed */
 539}
 540
 541static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
 542{
 543        int i;
 544        u16 o;
 545        u16 pwr_info_offset[] = {
 546                SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
 547                SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
 548        };
 549        BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
 550                        ARRAY_SIZE(out->core_pwr_info));
 551
 552        /* extract the MAC address */
 553        sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
 554
 555        SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
 556        SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
 557        SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
 558        SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
 559        SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
 560        SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
 561        SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
 562        SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
 563        SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
 564             SSB_SPROM8_ANTAVAIL_A_SHIFT);
 565        SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
 566             SSB_SPROM8_ANTAVAIL_BG_SHIFT);
 567        SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
 568        SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
 569             SSB_SPROM8_ITSSI_BG_SHIFT);
 570        SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
 571        SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
 572             SSB_SPROM8_ITSSI_A_SHIFT);
 573        SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
 574        SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
 575             SSB_SPROM8_MAXP_AL_SHIFT);
 576        SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
 577        SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
 578             SSB_SPROM8_GPIOA_P1_SHIFT);
 579        SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
 580        SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
 581             SSB_SPROM8_GPIOB_P3_SHIFT);
 582        SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
 583        SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
 584             SSB_SPROM8_TRI5G_SHIFT);
 585        SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
 586        SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
 587             SSB_SPROM8_TRI5GH_SHIFT);
 588        SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
 589        SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
 590             SSB_SPROM8_RXPO5G_SHIFT);
 591        SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
 592        SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
 593             SSB_SPROM8_RSSISMC2G_SHIFT);
 594        SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
 595             SSB_SPROM8_RSSISAV2G_SHIFT);
 596        SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
 597             SSB_SPROM8_BXA2G_SHIFT);
 598        SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
 599        SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
 600             SSB_SPROM8_RSSISMC5G_SHIFT);
 601        SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
 602             SSB_SPROM8_RSSISAV5G_SHIFT);
 603        SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
 604             SSB_SPROM8_BXA5G_SHIFT);
 605        SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
 606        SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
 607        SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
 608        SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
 609        SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
 610        SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
 611        SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
 612        SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
 613        SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
 614        SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
 615        SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
 616        SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
 617        SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
 618        SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
 619        SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
 620        SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
 621        SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
 622
 623        /* Extract the antenna gain values. */
 624        SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
 625             SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
 626        SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
 627             SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
 628        SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
 629             SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
 630        SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
 631             SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
 632
 633        /* Extract cores power info info */
 634        for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
 635                o = pwr_info_offset[i];
 636                SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
 637                        SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
 638                SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
 639                        SSB_SPROM8_2G_MAXP, 0);
 640
 641                SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
 642                SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
 643                SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
 644
 645                SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
 646                        SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
 647                SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
 648                        SSB_SPROM8_5G_MAXP, 0);
 649                SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
 650                        SSB_SPROM8_5GH_MAXP, 0);
 651                SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
 652                        SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
 653
 654                SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
 655                SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
 656                SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
 657                SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
 658                SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
 659                SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
 660                SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
 661                SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
 662                SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
 663        }
 664
 665        /* Extract FEM info */
 666        SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
 667                SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
 668        SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
 669                SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
 670        SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
 671                SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
 672        SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
 673                SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
 674        SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
 675                SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
 676
 677        SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
 678                SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
 679        SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
 680                SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
 681        SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
 682                SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
 683        SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
 684                SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
 685        SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
 686                SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
 687
 688        SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
 689             SSB_SPROM8_LEDDC_ON_SHIFT);
 690        SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
 691             SSB_SPROM8_LEDDC_OFF_SHIFT);
 692
 693        SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
 694             SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
 695        SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
 696             SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
 697        SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
 698             SSB_SPROM8_TXRXC_SWITCH_SHIFT);
 699
 700        SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
 701
 702        SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
 703        SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
 704        SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
 705        SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
 706
 707        SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
 708             SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
 709        SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
 710             SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
 711        SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
 712             SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
 713             SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
 714        SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
 715             SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
 716        SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
 717             SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
 718             SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
 719        SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
 720             SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
 721             SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
 722        SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
 723             SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
 724             SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
 725        SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
 726             SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
 727
 728        SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
 729        SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
 730        SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
 731        SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
 732
 733        SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
 734             SSB_SPROM8_THERMAL_TRESH_SHIFT);
 735        SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
 736             SSB_SPROM8_THERMAL_OFFSET_SHIFT);
 737        SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
 738             SSB_SPROM8_TEMPDELTA_PHYCAL,
 739             SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
 740        SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
 741             SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
 742        SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
 743             SSB_SPROM8_TEMPDELTA_HYSTERESIS,
 744             SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
 745        sprom_extract_r458(out, in);
 746
 747        /* TODO - get remaining rev 8 stuff needed */
 748}
 749
 750static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 751                         const u16 *in, u16 size)
 752{
 753        memset(out, 0, sizeof(*out));
 754
 755        out->revision = in[size - 1] & 0x00FF;
 756        ssb_dbg("SPROM revision %d detected\n", out->revision);
 757        memset(out->et0mac, 0xFF, 6);           /* preset et0 and et1 mac */
 758        memset(out->et1mac, 0xFF, 6);
 759
 760        if ((bus->chip_id & 0xFF00) == 0x4400) {
 761                /* Workaround: The BCM44XX chip has a stupid revision
 762                 * number stored in the SPROM.
 763                 * Always extract r1. */
 764                out->revision = 1;
 765                ssb_dbg("SPROM treated as revision %d\n", out->revision);
 766        }
 767
 768        switch (out->revision) {
 769        case 1:
 770        case 2:
 771        case 3:
 772                sprom_extract_r123(out, in);
 773                break;
 774        case 4:
 775        case 5:
 776                sprom_extract_r45(out, in);
 777                break;
 778        case 8:
 779                sprom_extract_r8(out, in);
 780                break;
 781        default:
 782                ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
 783                         out->revision);
 784                out->revision = 1;
 785                sprom_extract_r123(out, in);
 786        }
 787
 788        if (out->boardflags_lo == 0xFFFF)
 789                out->boardflags_lo = 0;  /* per specs */
 790        if (out->boardflags_hi == 0xFFFF)
 791                out->boardflags_hi = 0;  /* per specs */
 792
 793        return 0;
 794}
 795
 796static int ssb_pci_sprom_get(struct ssb_bus *bus,
 797                             struct ssb_sprom *sprom)
 798{
 799        int err;
 800        u16 *buf;
 801
 802        if (!ssb_is_sprom_available(bus)) {
 803                ssb_err("No SPROM available!\n");
 804                return -ENODEV;
 805        }
 806        if (bus->chipco.dev) {  /* can be unavailable! */
 807                /*
 808                 * get SPROM offset: SSB_SPROM_BASE1 except for
 809                 * chipcommon rev >= 31 or chip ID is 0x4312 and
 810                 * chipcommon status & 3 == 2
 811                 */
 812                if (bus->chipco.dev->id.revision >= 31)
 813                        bus->sprom_offset = SSB_SPROM_BASE31;
 814                else if (bus->chip_id == 0x4312 &&
 815                         (bus->chipco.status & 0x03) == 2)
 816                        bus->sprom_offset = SSB_SPROM_BASE31;
 817                else
 818                        bus->sprom_offset = SSB_SPROM_BASE1;
 819        } else {
 820                bus->sprom_offset = SSB_SPROM_BASE1;
 821        }
 822        ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset);
 823
 824        buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 825        if (!buf)
 826                return -ENOMEM;
 827        bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
 828        sprom_do_read(bus, buf);
 829        err = sprom_check_crc(buf, bus->sprom_size);
 830        if (err) {
 831                /* try for a 440 byte SPROM - revision 4 and higher */
 832                kfree(buf);
 833                buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
 834                              GFP_KERNEL);
 835                if (!buf)
 836                        return -ENOMEM;
 837                bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
 838                sprom_do_read(bus, buf);
 839                err = sprom_check_crc(buf, bus->sprom_size);
 840                if (err) {
 841                        /* All CRC attempts failed.
 842                         * Maybe there is no SPROM on the device?
 843                         * Now we ask the arch code if there is some sprom
 844                         * available for this device in some other storage */
 845                        err = ssb_fill_sprom_with_fallback(bus, sprom);
 846                        if (err) {
 847                                ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n",
 848                                         err);
 849                        } else {
 850                                ssb_dbg("Using SPROM revision %d provided by platform\n",
 851                                        sprom->revision);
 852                                err = 0;
 853                                goto out_free;
 854                        }
 855                        ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
 856                }
 857        }
 858        err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 859
 860out_free:
 861        kfree(buf);
 862        return err;
 863}
 864
 865static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
 866                                  struct ssb_boardinfo *bi)
 867{
 868        bi->vendor = bus->host_pci->subsystem_vendor;
 869        bi->type = bus->host_pci->subsystem_device;
 870}
 871
 872int ssb_pci_get_invariants(struct ssb_bus *bus,
 873                           struct ssb_init_invariants *iv)
 874{
 875        int err;
 876
 877        err = ssb_pci_sprom_get(bus, &iv->sprom);
 878        if (err)
 879                goto out;
 880        ssb_pci_get_boardinfo(bus, &iv->boardinfo);
 881
 882out:
 883        return err;
 884}
 885
 886#ifdef CONFIG_SSB_DEBUG
 887static int ssb_pci_assert_buspower(struct ssb_bus *bus)
 888{
 889        if (likely(bus->powered_up))
 890                return 0;
 891
 892        printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
 893               "while accessing PCI MMIO space\n");
 894        if (bus->power_warn_count <= 10) {
 895                bus->power_warn_count++;
 896                dump_stack();
 897        }
 898
 899        return -ENODEV;
 900}
 901#else /* DEBUG */
 902static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
 903{
 904        return 0;
 905}
 906#endif /* DEBUG */
 907
 908static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
 909{
 910        struct ssb_bus *bus = dev->bus;
 911
 912        if (unlikely(ssb_pci_assert_buspower(bus)))
 913                return 0xFF;
 914        if (unlikely(bus->mapped_device != dev)) {
 915                if (unlikely(ssb_pci_switch_core(bus, dev)))
 916                        return 0xFF;
 917        }
 918        return ioread8(bus->mmio + offset);
 919}
 920
 921static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
 922{
 923        struct ssb_bus *bus = dev->bus;
 924
 925        if (unlikely(ssb_pci_assert_buspower(bus)))
 926                return 0xFFFF;
 927        if (unlikely(bus->mapped_device != dev)) {
 928                if (unlikely(ssb_pci_switch_core(bus, dev)))
 929                        return 0xFFFF;
 930        }
 931        return ioread16(bus->mmio + offset);
 932}
 933
 934static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
 935{
 936        struct ssb_bus *bus = dev->bus;
 937
 938        if (unlikely(ssb_pci_assert_buspower(bus)))
 939                return 0xFFFFFFFF;
 940        if (unlikely(bus->mapped_device != dev)) {
 941                if (unlikely(ssb_pci_switch_core(bus, dev)))
 942                        return 0xFFFFFFFF;
 943        }
 944        return ioread32(bus->mmio + offset);
 945}
 946
 947#ifdef CONFIG_SSB_BLOCKIO
 948static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
 949                               size_t count, u16 offset, u8 reg_width)
 950{
 951        struct ssb_bus *bus = dev->bus;
 952        void __iomem *addr = bus->mmio + offset;
 953
 954        if (unlikely(ssb_pci_assert_buspower(bus)))
 955                goto error;
 956        if (unlikely(bus->mapped_device != dev)) {
 957                if (unlikely(ssb_pci_switch_core(bus, dev)))
 958                        goto error;
 959        }
 960        switch (reg_width) {
 961        case sizeof(u8):
 962                ioread8_rep(addr, buffer, count);
 963                break;
 964        case sizeof(u16):
 965                SSB_WARN_ON(count & 1);
 966                ioread16_rep(addr, buffer, count >> 1);
 967                break;
 968        case sizeof(u32):
 969                SSB_WARN_ON(count & 3);
 970                ioread32_rep(addr, buffer, count >> 2);
 971                break;
 972        default:
 973                SSB_WARN_ON(1);
 974        }
 975
 976        return;
 977error:
 978        memset(buffer, 0xFF, count);
 979}
 980#endif /* CONFIG_SSB_BLOCKIO */
 981
 982static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
 983{
 984        struct ssb_bus *bus = dev->bus;
 985
 986        if (unlikely(ssb_pci_assert_buspower(bus)))
 987                return;
 988        if (unlikely(bus->mapped_device != dev)) {
 989                if (unlikely(ssb_pci_switch_core(bus, dev)))
 990                        return;
 991        }
 992        iowrite8(value, bus->mmio + offset);
 993}
 994
 995static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
 996{
 997        struct ssb_bus *bus = dev->bus;
 998
 999        if (unlikely(ssb_pci_assert_buspower(bus)))
1000                return;
1001        if (unlikely(bus->mapped_device != dev)) {
1002                if (unlikely(ssb_pci_switch_core(bus, dev)))
1003                        return;
1004        }
1005        iowrite16(value, bus->mmio + offset);
1006}
1007
1008static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
1009{
1010        struct ssb_bus *bus = dev->bus;
1011
1012        if (unlikely(ssb_pci_assert_buspower(bus)))
1013                return;
1014        if (unlikely(bus->mapped_device != dev)) {
1015                if (unlikely(ssb_pci_switch_core(bus, dev)))
1016                        return;
1017        }
1018        iowrite32(value, bus->mmio + offset);
1019}
1020
1021#ifdef CONFIG_SSB_BLOCKIO
1022static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1023                                size_t count, u16 offset, u8 reg_width)
1024{
1025        struct ssb_bus *bus = dev->bus;
1026        void __iomem *addr = bus->mmio + offset;
1027
1028        if (unlikely(ssb_pci_assert_buspower(bus)))
1029                return;
1030        if (unlikely(bus->mapped_device != dev)) {
1031                if (unlikely(ssb_pci_switch_core(bus, dev)))
1032                        return;
1033        }
1034        switch (reg_width) {
1035        case sizeof(u8):
1036                iowrite8_rep(addr, buffer, count);
1037                break;
1038        case sizeof(u16):
1039                SSB_WARN_ON(count & 1);
1040                iowrite16_rep(addr, buffer, count >> 1);
1041                break;
1042        case sizeof(u32):
1043                SSB_WARN_ON(count & 3);
1044                iowrite32_rep(addr, buffer, count >> 2);
1045                break;
1046        default:
1047                SSB_WARN_ON(1);
1048        }
1049}
1050#endif /* CONFIG_SSB_BLOCKIO */
1051
1052/* Not "static", as it's used in main.c */
1053const struct ssb_bus_ops ssb_pci_ops = {
1054        .read8          = ssb_pci_read8,
1055        .read16         = ssb_pci_read16,
1056        .read32         = ssb_pci_read32,
1057        .write8         = ssb_pci_write8,
1058        .write16        = ssb_pci_write16,
1059        .write32        = ssb_pci_write32,
1060#ifdef CONFIG_SSB_BLOCKIO
1061        .block_read     = ssb_pci_block_read,
1062        .block_write    = ssb_pci_block_write,
1063#endif
1064};
1065
1066static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
1067                                       struct device_attribute *attr,
1068                                       char *buf)
1069{
1070        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1071        struct ssb_bus *bus;
1072
1073        bus = ssb_pci_dev_to_bus(pdev);
1074        if (!bus)
1075                return -ENODEV;
1076
1077        return ssb_attr_sprom_show(bus, buf, sprom_do_read);
1078}
1079
1080static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
1081                                        struct device_attribute *attr,
1082                                        const char *buf, size_t count)
1083{
1084        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1085        struct ssb_bus *bus;
1086
1087        bus = ssb_pci_dev_to_bus(pdev);
1088        if (!bus)
1089                return -ENODEV;
1090
1091        return ssb_attr_sprom_store(bus, buf, count,
1092                                    sprom_check_crc, sprom_do_write);
1093}
1094
1095static DEVICE_ATTR(ssb_sprom, 0600,
1096                   ssb_pci_attr_sprom_show,
1097                   ssb_pci_attr_sprom_store);
1098
1099void ssb_pci_exit(struct ssb_bus *bus)
1100{
1101        struct pci_dev *pdev;
1102
1103        if (bus->bustype != SSB_BUSTYPE_PCI)
1104                return;
1105
1106        pdev = bus->host_pci;
1107        device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1108}
1109
1110int ssb_pci_init(struct ssb_bus *bus)
1111{
1112        struct pci_dev *pdev;
1113        int err;
1114
1115        if (bus->bustype != SSB_BUSTYPE_PCI)
1116                return 0;
1117
1118        pdev = bus->host_pci;
1119        mutex_init(&bus->sprom_mutex);
1120        err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1121        if (err)
1122                goto out;
1123
1124out:
1125        return err;
1126}
1127