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