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