linux/drivers/ssb/pci.c
<<
>>
Prefs
   1/*
   2 * Sonics Silicon Backplane PCI-Hostbus related functions.
   3 *
   4 * Copyright (C) 2005-2006 Michael Buesch <mb@bu3sch.de>
   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
 182static inline u8 ssb_crc8(u8 crc, u8 data)
 183{
 184        /* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
 185        static const u8 t[] = {
 186                0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
 187                0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
 188                0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
 189                0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
 190                0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
 191                0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
 192                0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
 193                0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
 194                0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
 195                0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
 196                0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
 197                0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
 198                0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
 199                0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
 200                0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
 201                0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
 202                0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
 203                0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
 204                0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
 205                0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
 206                0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
 207                0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
 208                0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
 209                0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
 210                0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
 211                0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
 212                0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
 213                0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
 214                0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
 215                0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
 216                0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
 217                0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
 218        };
 219        return t[crc ^ data];
 220}
 221
 222static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
 223{
 224        int word;
 225        u8 crc = 0xFF;
 226
 227        for (word = 0; word < size - 1; word++) {
 228                crc = ssb_crc8(crc, sprom[word] & 0x00FF);
 229                crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
 230        }
 231        crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
 232        crc ^= 0xFF;
 233
 234        return crc;
 235}
 236
 237static int sprom_check_crc(const u16 *sprom, size_t size)
 238{
 239        u8 crc;
 240        u8 expected_crc;
 241        u16 tmp;
 242
 243        crc = ssb_sprom_crc(sprom, size);
 244        tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
 245        expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
 246        if (crc != expected_crc)
 247                return -EPROTO;
 248
 249        return 0;
 250}
 251
 252static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
 253{
 254        int i;
 255
 256        for (i = 0; i < bus->sprom_size; i++)
 257                sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
 258
 259        return 0;
 260}
 261
 262static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
 263{
 264        struct pci_dev *pdev = bus->host_pci;
 265        int i, err;
 266        u32 spromctl;
 267        u16 size = bus->sprom_size;
 268
 269        ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
 270        err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
 271        if (err)
 272                goto err_ctlreg;
 273        spromctl |= SSB_SPROMCTL_WE;
 274        err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
 275        if (err)
 276                goto err_ctlreg;
 277        ssb_printk(KERN_NOTICE PFX "[ 0%%");
 278        msleep(500);
 279        for (i = 0; i < size; i++) {
 280                if (i == size / 4)
 281                        ssb_printk("25%%");
 282                else if (i == size / 2)
 283                        ssb_printk("50%%");
 284                else if (i == (size * 3) / 4)
 285                        ssb_printk("75%%");
 286                else if (i % 2)
 287                        ssb_printk(".");
 288                writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
 289                mmiowb();
 290                msleep(20);
 291        }
 292        err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
 293        if (err)
 294                goto err_ctlreg;
 295        spromctl &= ~SSB_SPROMCTL_WE;
 296        err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
 297        if (err)
 298                goto err_ctlreg;
 299        msleep(500);
 300        ssb_printk("100%% ]\n");
 301        ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
 302
 303        return 0;
 304err_ctlreg:
 305        ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
 306        return err;
 307}
 308
 309static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
 310                               u16 mask, u16 shift)
 311{
 312        u16 v;
 313        u8 gain;
 314
 315        v = in[SPOFF(SSB_SPROM1_AGAIN)];
 316        gain = (v & mask) >> shift;
 317        if (gain == 0xFF)
 318                gain = 2; /* If unset use 2dBm */
 319        if (sprom_revision == 1) {
 320                /* Convert to Q5.2 */
 321                gain <<= 2;
 322        } else {
 323                /* Q5.2 Fractional part is stored in 0xC0 */
 324                gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
 325        }
 326
 327        return (s8)gain;
 328}
 329
 330static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 331{
 332        int i;
 333        u16 v;
 334        s8 gain;
 335        u16 loc[3];
 336
 337        if (out->revision == 3)                 /* rev 3 moved MAC */
 338                loc[0] = SSB_SPROM3_IL0MAC;
 339        else {
 340                loc[0] = SSB_SPROM1_IL0MAC;
 341                loc[1] = SSB_SPROM1_ET0MAC;
 342                loc[2] = SSB_SPROM1_ET1MAC;
 343        }
 344        for (i = 0; i < 3; i++) {
 345                v = in[SPOFF(loc[0]) + i];
 346                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 347        }
 348        if (out->revision < 3) {        /* only rev 1-2 have et0, et1 */
 349                for (i = 0; i < 3; i++) {
 350                        v = in[SPOFF(loc[1]) + i];
 351                        *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
 352                }
 353                for (i = 0; i < 3; i++) {
 354                        v = in[SPOFF(loc[2]) + i];
 355                        *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
 356                }
 357        }
 358        SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
 359        SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
 360             SSB_SPROM1_ETHPHY_ET1A_SHIFT);
 361        SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
 362        SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
 363        SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
 364        SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
 365             SSB_SPROM1_BINF_CCODE_SHIFT);
 366        SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
 367             SSB_SPROM1_BINF_ANTA_SHIFT);
 368        SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
 369             SSB_SPROM1_BINF_ANTBG_SHIFT);
 370        SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
 371        SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
 372        SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
 373        SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
 374        SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
 375        SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
 376        SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
 377        SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
 378             SSB_SPROM1_GPIOA_P1_SHIFT);
 379        SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
 380        SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
 381             SSB_SPROM1_GPIOB_P3_SHIFT);
 382        SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
 383             SSB_SPROM1_MAXPWR_A_SHIFT);
 384        SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
 385        SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
 386             SSB_SPROM1_ITSSI_A_SHIFT);
 387        SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
 388        SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
 389        if (out->revision >= 2)
 390                SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
 391
 392        /* Extract the antenna gain values. */
 393        gain = r123_extract_antgain(out->revision, in,
 394                                    SSB_SPROM1_AGAIN_BG,
 395                                    SSB_SPROM1_AGAIN_BG_SHIFT);
 396        out->antenna_gain.ghz24.a0 = gain;
 397        out->antenna_gain.ghz24.a1 = gain;
 398        out->antenna_gain.ghz24.a2 = gain;
 399        out->antenna_gain.ghz24.a3 = gain;
 400        gain = r123_extract_antgain(out->revision, in,
 401                                    SSB_SPROM1_AGAIN_A,
 402                                    SSB_SPROM1_AGAIN_A_SHIFT);
 403        out->antenna_gain.ghz5.a0 = gain;
 404        out->antenna_gain.ghz5.a1 = gain;
 405        out->antenna_gain.ghz5.a2 = gain;
 406        out->antenna_gain.ghz5.a3 = gain;
 407}
 408
 409/* Revs 4 5 and 8 have partially shared layout */
 410static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
 411{
 412        SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
 413             SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
 414        SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
 415             SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
 416        SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
 417             SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
 418        SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
 419             SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
 420
 421        SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
 422             SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
 423        SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
 424             SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
 425        SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
 426             SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
 427        SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
 428             SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
 429
 430        SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
 431             SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
 432        SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
 433             SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
 434        SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
 435             SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
 436        SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
 437             SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
 438
 439        SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
 440             SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
 441        SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
 442             SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
 443        SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
 444             SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
 445        SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
 446             SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
 447}
 448
 449static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
 450{
 451        int i;
 452        u16 v;
 453        u16 il0mac_offset;
 454
 455        if (out->revision == 4)
 456                il0mac_offset = SSB_SPROM4_IL0MAC;
 457        else
 458                il0mac_offset = SSB_SPROM5_IL0MAC;
 459        /* extract the MAC address */
 460        for (i = 0; i < 3; i++) {
 461                v = in[SPOFF(il0mac_offset) + i];
 462                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 463        }
 464        SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
 465        SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
 466             SSB_SPROM4_ETHPHY_ET1A_SHIFT);
 467        if (out->revision == 4) {
 468                SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
 469                SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
 470                SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
 471                SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
 472                SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
 473        } else {
 474                SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
 475                SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
 476                SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
 477                SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
 478                SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
 479        }
 480        SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
 481             SSB_SPROM4_ANTAVAIL_A_SHIFT);
 482        SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
 483             SSB_SPROM4_ANTAVAIL_BG_SHIFT);
 484        SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
 485        SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
 486             SSB_SPROM4_ITSSI_BG_SHIFT);
 487        SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
 488        SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
 489             SSB_SPROM4_ITSSI_A_SHIFT);
 490        if (out->revision == 4) {
 491                SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
 492                SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
 493                     SSB_SPROM4_GPIOA_P1_SHIFT);
 494                SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
 495                SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
 496                     SSB_SPROM4_GPIOB_P3_SHIFT);
 497        } else {
 498                SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
 499                SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
 500                     SSB_SPROM5_GPIOA_P1_SHIFT);
 501                SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
 502                SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
 503                     SSB_SPROM5_GPIOB_P3_SHIFT);
 504        }
 505
 506        /* Extract the antenna gain values. */
 507        SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
 508             SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
 509        SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
 510             SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
 511        SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
 512             SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
 513        SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
 514             SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
 515        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 516               sizeof(out->antenna_gain.ghz5));
 517
 518        sprom_extract_r458(out, in);
 519
 520        /* TODO - get remaining rev 4 stuff needed */
 521}
 522
 523static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
 524{
 525        int i;
 526        u16 v;
 527
 528        /* extract the MAC address */
 529        for (i = 0; i < 3; i++) {
 530                v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
 531                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 532        }
 533        SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
 534        SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
 535        SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
 536        SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
 537        SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
 538        SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
 539             SSB_SPROM8_ANTAVAIL_A_SHIFT);
 540        SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
 541             SSB_SPROM8_ANTAVAIL_BG_SHIFT);
 542        SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
 543        SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
 544             SSB_SPROM8_ITSSI_BG_SHIFT);
 545        SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
 546        SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
 547             SSB_SPROM8_ITSSI_A_SHIFT);
 548        SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
 549        SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
 550             SSB_SPROM8_MAXP_AL_SHIFT);
 551        SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
 552        SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
 553             SSB_SPROM8_GPIOA_P1_SHIFT);
 554        SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
 555        SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
 556             SSB_SPROM8_GPIOB_P3_SHIFT);
 557        SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
 558        SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
 559             SSB_SPROM8_TRI5G_SHIFT);
 560        SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
 561        SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
 562             SSB_SPROM8_TRI5GH_SHIFT);
 563        SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
 564        SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
 565             SSB_SPROM8_RXPO5G_SHIFT);
 566        SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
 567        SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
 568             SSB_SPROM8_RSSISMC2G_SHIFT);
 569        SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
 570             SSB_SPROM8_RSSISAV2G_SHIFT);
 571        SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
 572             SSB_SPROM8_BXA2G_SHIFT);
 573        SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
 574        SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
 575             SSB_SPROM8_RSSISMC5G_SHIFT);
 576        SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
 577             SSB_SPROM8_RSSISAV5G_SHIFT);
 578        SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
 579             SSB_SPROM8_BXA5G_SHIFT);
 580        SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
 581        SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
 582        SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
 583        SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
 584        SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
 585        SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
 586        SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
 587        SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
 588        SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
 589        SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
 590        SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
 591        SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
 592        SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
 593        SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
 594        SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
 595        SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
 596        SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
 597
 598        /* Extract the antenna gain values. */
 599        SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
 600             SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
 601        SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01,
 602             SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
 603        SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23,
 604             SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
 605        SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23,
 606             SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
 607        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 608               sizeof(out->antenna_gain.ghz5));
 609
 610        sprom_extract_r458(out, in);
 611
 612        /* TODO - get remaining rev 8 stuff needed */
 613}
 614
 615static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 616                         const u16 *in, u16 size)
 617{
 618        memset(out, 0, sizeof(*out));
 619
 620        out->revision = in[size - 1] & 0x00FF;
 621        ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
 622        memset(out->et0mac, 0xFF, 6);           /* preset et0 and et1 mac */
 623        memset(out->et1mac, 0xFF, 6);
 624
 625        if ((bus->chip_id & 0xFF00) == 0x4400) {
 626                /* Workaround: The BCM44XX chip has a stupid revision
 627                 * number stored in the SPROM.
 628                 * Always extract r1. */
 629                out->revision = 1;
 630                ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
 631        }
 632
 633        switch (out->revision) {
 634        case 1:
 635        case 2:
 636        case 3:
 637                sprom_extract_r123(out, in);
 638                break;
 639        case 4:
 640        case 5:
 641                sprom_extract_r45(out, in);
 642                break;
 643        case 8:
 644                sprom_extract_r8(out, in);
 645                break;
 646        default:
 647                ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
 648                           " revision %d detected. Will extract"
 649                           " v1\n", out->revision);
 650                out->revision = 1;
 651                sprom_extract_r123(out, in);
 652        }
 653
 654        if (out->boardflags_lo == 0xFFFF)
 655                out->boardflags_lo = 0;  /* per specs */
 656        if (out->boardflags_hi == 0xFFFF)
 657                out->boardflags_hi = 0;  /* per specs */
 658
 659        return 0;
 660}
 661
 662static int ssb_pci_sprom_get(struct ssb_bus *bus,
 663                             struct ssb_sprom *sprom)
 664{
 665        const struct ssb_sprom *fallback;
 666        int err;
 667        u16 *buf;
 668
 669        if (!ssb_is_sprom_available(bus)) {
 670                ssb_printk(KERN_ERR PFX "No SPROM available!\n");
 671                return -ENODEV;
 672        }
 673        if (bus->chipco.dev) {  /* can be unavailable! */
 674                /*
 675                 * get SPROM offset: SSB_SPROM_BASE1 except for
 676                 * chipcommon rev >= 31 or chip ID is 0x4312 and
 677                 * chipcommon status & 3 == 2
 678                 */
 679                if (bus->chipco.dev->id.revision >= 31)
 680                        bus->sprom_offset = SSB_SPROM_BASE31;
 681                else if (bus->chip_id == 0x4312 &&
 682                         (bus->chipco.status & 0x03) == 2)
 683                        bus->sprom_offset = SSB_SPROM_BASE31;
 684                else
 685                        bus->sprom_offset = SSB_SPROM_BASE1;
 686        } else {
 687                bus->sprom_offset = SSB_SPROM_BASE1;
 688        }
 689        ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
 690
 691        buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 692        if (!buf)
 693                return -ENOMEM;
 694        bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
 695        sprom_do_read(bus, buf);
 696        err = sprom_check_crc(buf, bus->sprom_size);
 697        if (err) {
 698                /* try for a 440 byte SPROM - revision 4 and higher */
 699                kfree(buf);
 700                buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
 701                              GFP_KERNEL);
 702                if (!buf)
 703                        return -ENOMEM;
 704                bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
 705                sprom_do_read(bus, buf);
 706                err = sprom_check_crc(buf, bus->sprom_size);
 707                if (err) {
 708                        /* All CRC attempts failed.
 709                         * Maybe there is no SPROM on the device?
 710                         * If we have a fallback, use that. */
 711                        fallback = ssb_get_fallback_sprom();
 712                        if (fallback) {
 713                                memcpy(sprom, fallback, sizeof(*sprom));
 714                                err = 0;
 715                                goto out_free;
 716                        }
 717                        ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
 718                                   " SPROM CRC (corrupt SPROM)\n");
 719                }
 720        }
 721        err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 722
 723out_free:
 724        kfree(buf);
 725        return err;
 726}
 727
 728static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
 729                                  struct ssb_boardinfo *bi)
 730{
 731        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
 732                             &bi->vendor);
 733        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
 734                             &bi->type);
 735        pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
 736                             &bi->rev);
 737}
 738
 739int ssb_pci_get_invariants(struct ssb_bus *bus,
 740                           struct ssb_init_invariants *iv)
 741{
 742        int err;
 743
 744        err = ssb_pci_sprom_get(bus, &iv->sprom);
 745        if (err)
 746                goto out;
 747        ssb_pci_get_boardinfo(bus, &iv->boardinfo);
 748
 749out:
 750        return err;
 751}
 752
 753#ifdef CONFIG_SSB_DEBUG
 754static int ssb_pci_assert_buspower(struct ssb_bus *bus)
 755{
 756        if (likely(bus->powered_up))
 757                return 0;
 758
 759        printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
 760               "while accessing PCI MMIO space\n");
 761        if (bus->power_warn_count <= 10) {
 762                bus->power_warn_count++;
 763                dump_stack();
 764        }
 765
 766        return -ENODEV;
 767}
 768#else /* DEBUG */
 769static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
 770{
 771        return 0;
 772}
 773#endif /* DEBUG */
 774
 775static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
 776{
 777        struct ssb_bus *bus = dev->bus;
 778
 779        if (unlikely(ssb_pci_assert_buspower(bus)))
 780                return 0xFF;
 781        if (unlikely(bus->mapped_device != dev)) {
 782                if (unlikely(ssb_pci_switch_core(bus, dev)))
 783                        return 0xFF;
 784        }
 785        return ioread8(bus->mmio + offset);
 786}
 787
 788static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
 789{
 790        struct ssb_bus *bus = dev->bus;
 791
 792        if (unlikely(ssb_pci_assert_buspower(bus)))
 793                return 0xFFFF;
 794        if (unlikely(bus->mapped_device != dev)) {
 795                if (unlikely(ssb_pci_switch_core(bus, dev)))
 796                        return 0xFFFF;
 797        }
 798        return ioread16(bus->mmio + offset);
 799}
 800
 801static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
 802{
 803        struct ssb_bus *bus = dev->bus;
 804
 805        if (unlikely(ssb_pci_assert_buspower(bus)))
 806                return 0xFFFFFFFF;
 807        if (unlikely(bus->mapped_device != dev)) {
 808                if (unlikely(ssb_pci_switch_core(bus, dev)))
 809                        return 0xFFFFFFFF;
 810        }
 811        return ioread32(bus->mmio + offset);
 812}
 813
 814#ifdef CONFIG_SSB_BLOCKIO
 815static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
 816                               size_t count, u16 offset, u8 reg_width)
 817{
 818        struct ssb_bus *bus = dev->bus;
 819        void __iomem *addr = bus->mmio + offset;
 820
 821        if (unlikely(ssb_pci_assert_buspower(bus)))
 822                goto error;
 823        if (unlikely(bus->mapped_device != dev)) {
 824                if (unlikely(ssb_pci_switch_core(bus, dev)))
 825                        goto error;
 826        }
 827        switch (reg_width) {
 828        case sizeof(u8):
 829                ioread8_rep(addr, buffer, count);
 830                break;
 831        case sizeof(u16):
 832                SSB_WARN_ON(count & 1);
 833                ioread16_rep(addr, buffer, count >> 1);
 834                break;
 835        case sizeof(u32):
 836                SSB_WARN_ON(count & 3);
 837                ioread32_rep(addr, buffer, count >> 2);
 838                break;
 839        default:
 840                SSB_WARN_ON(1);
 841        }
 842
 843        return;
 844error:
 845        memset(buffer, 0xFF, count);
 846}
 847#endif /* CONFIG_SSB_BLOCKIO */
 848
 849static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
 850{
 851        struct ssb_bus *bus = dev->bus;
 852
 853        if (unlikely(ssb_pci_assert_buspower(bus)))
 854                return;
 855        if (unlikely(bus->mapped_device != dev)) {
 856                if (unlikely(ssb_pci_switch_core(bus, dev)))
 857                        return;
 858        }
 859        iowrite8(value, bus->mmio + offset);
 860}
 861
 862static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
 863{
 864        struct ssb_bus *bus = dev->bus;
 865
 866        if (unlikely(ssb_pci_assert_buspower(bus)))
 867                return;
 868        if (unlikely(bus->mapped_device != dev)) {
 869                if (unlikely(ssb_pci_switch_core(bus, dev)))
 870                        return;
 871        }
 872        iowrite16(value, bus->mmio + offset);
 873}
 874
 875static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
 876{
 877        struct ssb_bus *bus = dev->bus;
 878
 879        if (unlikely(ssb_pci_assert_buspower(bus)))
 880                return;
 881        if (unlikely(bus->mapped_device != dev)) {
 882                if (unlikely(ssb_pci_switch_core(bus, dev)))
 883                        return;
 884        }
 885        iowrite32(value, bus->mmio + offset);
 886}
 887
 888#ifdef CONFIG_SSB_BLOCKIO
 889static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
 890                                size_t count, u16 offset, u8 reg_width)
 891{
 892        struct ssb_bus *bus = dev->bus;
 893        void __iomem *addr = bus->mmio + offset;
 894
 895        if (unlikely(ssb_pci_assert_buspower(bus)))
 896                return;
 897        if (unlikely(bus->mapped_device != dev)) {
 898                if (unlikely(ssb_pci_switch_core(bus, dev)))
 899                        return;
 900        }
 901        switch (reg_width) {
 902        case sizeof(u8):
 903                iowrite8_rep(addr, buffer, count);
 904                break;
 905        case sizeof(u16):
 906                SSB_WARN_ON(count & 1);
 907                iowrite16_rep(addr, buffer, count >> 1);
 908                break;
 909        case sizeof(u32):
 910                SSB_WARN_ON(count & 3);
 911                iowrite32_rep(addr, buffer, count >> 2);
 912                break;
 913        default:
 914                SSB_WARN_ON(1);
 915        }
 916}
 917#endif /* CONFIG_SSB_BLOCKIO */
 918
 919/* Not "static", as it's used in main.c */
 920const struct ssb_bus_ops ssb_pci_ops = {
 921        .read8          = ssb_pci_read8,
 922        .read16         = ssb_pci_read16,
 923        .read32         = ssb_pci_read32,
 924        .write8         = ssb_pci_write8,
 925        .write16        = ssb_pci_write16,
 926        .write32        = ssb_pci_write32,
 927#ifdef CONFIG_SSB_BLOCKIO
 928        .block_read     = ssb_pci_block_read,
 929        .block_write    = ssb_pci_block_write,
 930#endif
 931};
 932
 933static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
 934                                       struct device_attribute *attr,
 935                                       char *buf)
 936{
 937        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
 938        struct ssb_bus *bus;
 939
 940        bus = ssb_pci_dev_to_bus(pdev);
 941        if (!bus)
 942                return -ENODEV;
 943
 944        return ssb_attr_sprom_show(bus, buf, sprom_do_read);
 945}
 946
 947static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
 948                                        struct device_attribute *attr,
 949                                        const char *buf, size_t count)
 950{
 951        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
 952        struct ssb_bus *bus;
 953
 954        bus = ssb_pci_dev_to_bus(pdev);
 955        if (!bus)
 956                return -ENODEV;
 957
 958        return ssb_attr_sprom_store(bus, buf, count,
 959                                    sprom_check_crc, sprom_do_write);
 960}
 961
 962static DEVICE_ATTR(ssb_sprom, 0600,
 963                   ssb_pci_attr_sprom_show,
 964                   ssb_pci_attr_sprom_store);
 965
 966void ssb_pci_exit(struct ssb_bus *bus)
 967{
 968        struct pci_dev *pdev;
 969
 970        if (bus->bustype != SSB_BUSTYPE_PCI)
 971                return;
 972
 973        pdev = bus->host_pci;
 974        device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
 975}
 976
 977int ssb_pci_init(struct ssb_bus *bus)
 978{
 979        struct pci_dev *pdev;
 980        int err;
 981
 982        if (bus->bustype != SSB_BUSTYPE_PCI)
 983                return 0;
 984
 985        pdev = bus->host_pci;
 986        mutex_init(&bus->sprom_mutex);
 987        err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
 988        if (err)
 989                goto out;
 990
 991out:
 992        return err;
 993}
 994