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        } else {
 472                SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
 473                SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
 474                SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
 475        }
 476        SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
 477             SSB_SPROM4_ANTAVAIL_A_SHIFT);
 478        SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
 479             SSB_SPROM4_ANTAVAIL_BG_SHIFT);
 480        SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
 481        SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
 482             SSB_SPROM4_ITSSI_BG_SHIFT);
 483        SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
 484        SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
 485             SSB_SPROM4_ITSSI_A_SHIFT);
 486        if (out->revision == 4) {
 487                SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
 488                SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
 489                     SSB_SPROM4_GPIOA_P1_SHIFT);
 490                SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
 491                SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
 492                     SSB_SPROM4_GPIOB_P3_SHIFT);
 493        } else {
 494                SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
 495                SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
 496                     SSB_SPROM5_GPIOA_P1_SHIFT);
 497                SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
 498                SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
 499                     SSB_SPROM5_GPIOB_P3_SHIFT);
 500        }
 501
 502        /* Extract the antenna gain values. */
 503        SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
 504             SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
 505        SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
 506             SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
 507        SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
 508             SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
 509        SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
 510             SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
 511        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 512               sizeof(out->antenna_gain.ghz5));
 513
 514        sprom_extract_r458(out, in);
 515
 516        /* TODO - get remaining rev 4 stuff needed */
 517}
 518
 519static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
 520{
 521        int i;
 522        u16 v;
 523
 524        /* extract the MAC address */
 525        for (i = 0; i < 3; i++) {
 526                v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
 527                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 528        }
 529        SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
 530        SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
 531        SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
 532        SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
 533        SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
 534        SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
 535             SSB_SPROM8_ANTAVAIL_A_SHIFT);
 536        SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
 537             SSB_SPROM8_ANTAVAIL_BG_SHIFT);
 538        SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
 539        SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
 540             SSB_SPROM8_ITSSI_BG_SHIFT);
 541        SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
 542        SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
 543             SSB_SPROM8_ITSSI_A_SHIFT);
 544        SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
 545        SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
 546             SSB_SPROM8_MAXP_AL_SHIFT);
 547        SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
 548        SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
 549             SSB_SPROM8_GPIOA_P1_SHIFT);
 550        SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
 551        SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
 552             SSB_SPROM8_GPIOB_P3_SHIFT);
 553        SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
 554        SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
 555             SSB_SPROM8_TRI5G_SHIFT);
 556        SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
 557        SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
 558             SSB_SPROM8_TRI5GH_SHIFT);
 559        SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
 560        SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
 561             SSB_SPROM8_RXPO5G_SHIFT);
 562        SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
 563        SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
 564             SSB_SPROM8_RSSISMC2G_SHIFT);
 565        SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
 566             SSB_SPROM8_RSSISAV2G_SHIFT);
 567        SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
 568             SSB_SPROM8_BXA2G_SHIFT);
 569        SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
 570        SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
 571             SSB_SPROM8_RSSISMC5G_SHIFT);
 572        SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
 573             SSB_SPROM8_RSSISAV5G_SHIFT);
 574        SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
 575             SSB_SPROM8_BXA5G_SHIFT);
 576        SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
 577        SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
 578        SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
 579        SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
 580        SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
 581        SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
 582        SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
 583        SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
 584        SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
 585        SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
 586        SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
 587        SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
 588        SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
 589        SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
 590        SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
 591        SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
 592        SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
 593
 594        /* Extract the antenna gain values. */
 595        SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
 596             SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
 597        SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01,
 598             SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
 599        SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23,
 600             SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
 601        SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23,
 602             SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
 603        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 604               sizeof(out->antenna_gain.ghz5));
 605
 606        sprom_extract_r458(out, in);
 607
 608        /* TODO - get remaining rev 8 stuff needed */
 609}
 610
 611static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 612                         const u16 *in, u16 size)
 613{
 614        memset(out, 0, sizeof(*out));
 615
 616        out->revision = in[size - 1] & 0x00FF;
 617        ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
 618        memset(out->et0mac, 0xFF, 6);           /* preset et0 and et1 mac */
 619        memset(out->et1mac, 0xFF, 6);
 620
 621        if ((bus->chip_id & 0xFF00) == 0x4400) {
 622                /* Workaround: The BCM44XX chip has a stupid revision
 623                 * number stored in the SPROM.
 624                 * Always extract r1. */
 625                out->revision = 1;
 626                ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
 627        }
 628
 629        switch (out->revision) {
 630        case 1:
 631        case 2:
 632        case 3:
 633                sprom_extract_r123(out, in);
 634                break;
 635        case 4:
 636        case 5:
 637                sprom_extract_r45(out, in);
 638                break;
 639        case 8:
 640                sprom_extract_r8(out, in);
 641                break;
 642        default:
 643                ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
 644                           "  revision %d detected. Will extract"
 645                           " v1\n", out->revision);
 646                out->revision = 1;
 647                sprom_extract_r123(out, in);
 648        }
 649
 650        if (out->boardflags_lo == 0xFFFF)
 651                out->boardflags_lo = 0;  /* per specs */
 652        if (out->boardflags_hi == 0xFFFF)
 653                out->boardflags_hi = 0;  /* per specs */
 654
 655        return 0;
 656}
 657
 658static int ssb_pci_sprom_get(struct ssb_bus *bus,
 659                             struct ssb_sprom *sprom)
 660{
 661        const struct ssb_sprom *fallback;
 662        int err;
 663        u16 *buf;
 664
 665        if (!ssb_is_sprom_available(bus)) {
 666                ssb_printk(KERN_ERR PFX "No SPROM available!\n");
 667                return -ENODEV;
 668        }
 669        if (bus->chipco.dev) {  /* can be unavailible! */
 670                /*
 671                 * get SPROM offset: SSB_SPROM_BASE1 except for
 672                 * chipcommon rev >= 31 or chip ID is 0x4312 and
 673                 * chipcommon status & 3 == 2
 674                 */
 675                if (bus->chipco.dev->id.revision >= 31)
 676                        bus->sprom_offset = SSB_SPROM_BASE31;
 677                else if (bus->chip_id == 0x4312 &&
 678                         (bus->chipco.status & 0x03) == 2)
 679                        bus->sprom_offset = SSB_SPROM_BASE31;
 680                else
 681                        bus->sprom_offset = SSB_SPROM_BASE1;
 682        } else {
 683                bus->sprom_offset = SSB_SPROM_BASE1;
 684        }
 685        ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
 686
 687        buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 688        if (!buf)
 689                return -ENOMEM;
 690        bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
 691        sprom_do_read(bus, buf);
 692        err = sprom_check_crc(buf, bus->sprom_size);
 693        if (err) {
 694                /* try for a 440 byte SPROM - revision 4 and higher */
 695                kfree(buf);
 696                buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
 697                              GFP_KERNEL);
 698                if (!buf)
 699                        return -ENOMEM;
 700                bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
 701                sprom_do_read(bus, buf);
 702                err = sprom_check_crc(buf, bus->sprom_size);
 703                if (err) {
 704                        /* All CRC attempts failed.
 705                         * Maybe there is no SPROM on the device?
 706                         * If we have a fallback, use that. */
 707                        fallback = ssb_get_fallback_sprom();
 708                        if (fallback) {
 709                                memcpy(sprom, fallback, sizeof(*sprom));
 710                                err = 0;
 711                                goto out_free;
 712                        }
 713                        ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
 714                                   " SPROM CRC (corrupt SPROM)\n");
 715                }
 716        }
 717        err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 718
 719out_free:
 720        kfree(buf);
 721        return err;
 722}
 723
 724static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
 725                                  struct ssb_boardinfo *bi)
 726{
 727        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
 728                             &bi->vendor);
 729        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
 730                             &bi->type);
 731        pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
 732                             &bi->rev);
 733}
 734
 735int ssb_pci_get_invariants(struct ssb_bus *bus,
 736                           struct ssb_init_invariants *iv)
 737{
 738        int err;
 739
 740        err = ssb_pci_sprom_get(bus, &iv->sprom);
 741        if (err)
 742                goto out;
 743        ssb_pci_get_boardinfo(bus, &iv->boardinfo);
 744
 745out:
 746        return err;
 747}
 748
 749#ifdef CONFIG_SSB_DEBUG
 750static int ssb_pci_assert_buspower(struct ssb_bus *bus)
 751{
 752        if (likely(bus->powered_up))
 753                return 0;
 754
 755        printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
 756               "while accessing PCI MMIO space\n");
 757        if (bus->power_warn_count <= 10) {
 758                bus->power_warn_count++;
 759                dump_stack();
 760        }
 761
 762        return -ENODEV;
 763}
 764#else /* DEBUG */
 765static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
 766{
 767        return 0;
 768}
 769#endif /* DEBUG */
 770
 771static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
 772{
 773        struct ssb_bus *bus = dev->bus;
 774
 775        if (unlikely(ssb_pci_assert_buspower(bus)))
 776                return 0xFF;
 777        if (unlikely(bus->mapped_device != dev)) {
 778                if (unlikely(ssb_pci_switch_core(bus, dev)))
 779                        return 0xFF;
 780        }
 781        return ioread8(bus->mmio + offset);
 782}
 783
 784static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
 785{
 786        struct ssb_bus *bus = dev->bus;
 787
 788        if (unlikely(ssb_pci_assert_buspower(bus)))
 789                return 0xFFFF;
 790        if (unlikely(bus->mapped_device != dev)) {
 791                if (unlikely(ssb_pci_switch_core(bus, dev)))
 792                        return 0xFFFF;
 793        }
 794        return ioread16(bus->mmio + offset);
 795}
 796
 797static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
 798{
 799        struct ssb_bus *bus = dev->bus;
 800
 801        if (unlikely(ssb_pci_assert_buspower(bus)))
 802                return 0xFFFFFFFF;
 803        if (unlikely(bus->mapped_device != dev)) {
 804                if (unlikely(ssb_pci_switch_core(bus, dev)))
 805                        return 0xFFFFFFFF;
 806        }
 807        return ioread32(bus->mmio + offset);
 808}
 809
 810#ifdef CONFIG_SSB_BLOCKIO
 811static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
 812                               size_t count, u16 offset, u8 reg_width)
 813{
 814        struct ssb_bus *bus = dev->bus;
 815        void __iomem *addr = bus->mmio + offset;
 816
 817        if (unlikely(ssb_pci_assert_buspower(bus)))
 818                goto error;
 819        if (unlikely(bus->mapped_device != dev)) {
 820                if (unlikely(ssb_pci_switch_core(bus, dev)))
 821                        goto error;
 822        }
 823        switch (reg_width) {
 824        case sizeof(u8):
 825                ioread8_rep(addr, buffer, count);
 826                break;
 827        case sizeof(u16):
 828                SSB_WARN_ON(count & 1);
 829                ioread16_rep(addr, buffer, count >> 1);
 830                break;
 831        case sizeof(u32):
 832                SSB_WARN_ON(count & 3);
 833                ioread32_rep(addr, buffer, count >> 2);
 834                break;
 835        default:
 836                SSB_WARN_ON(1);
 837        }
 838
 839        return;
 840error:
 841        memset(buffer, 0xFF, count);
 842}
 843#endif /* CONFIG_SSB_BLOCKIO */
 844
 845static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
 846{
 847        struct ssb_bus *bus = dev->bus;
 848
 849        if (unlikely(ssb_pci_assert_buspower(bus)))
 850                return;
 851        if (unlikely(bus->mapped_device != dev)) {
 852                if (unlikely(ssb_pci_switch_core(bus, dev)))
 853                        return;
 854        }
 855        iowrite8(value, bus->mmio + offset);
 856}
 857
 858static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
 859{
 860        struct ssb_bus *bus = dev->bus;
 861
 862        if (unlikely(ssb_pci_assert_buspower(bus)))
 863                return;
 864        if (unlikely(bus->mapped_device != dev)) {
 865                if (unlikely(ssb_pci_switch_core(bus, dev)))
 866                        return;
 867        }
 868        iowrite16(value, bus->mmio + offset);
 869}
 870
 871static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
 872{
 873        struct ssb_bus *bus = dev->bus;
 874
 875        if (unlikely(ssb_pci_assert_buspower(bus)))
 876                return;
 877        if (unlikely(bus->mapped_device != dev)) {
 878                if (unlikely(ssb_pci_switch_core(bus, dev)))
 879                        return;
 880        }
 881        iowrite32(value, bus->mmio + offset);
 882}
 883
 884#ifdef CONFIG_SSB_BLOCKIO
 885static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
 886                                size_t count, u16 offset, u8 reg_width)
 887{
 888        struct ssb_bus *bus = dev->bus;
 889        void __iomem *addr = bus->mmio + offset;
 890
 891        if (unlikely(ssb_pci_assert_buspower(bus)))
 892                return;
 893        if (unlikely(bus->mapped_device != dev)) {
 894                if (unlikely(ssb_pci_switch_core(bus, dev)))
 895                        return;
 896        }
 897        switch (reg_width) {
 898        case sizeof(u8):
 899                iowrite8_rep(addr, buffer, count);
 900                break;
 901        case sizeof(u16):
 902                SSB_WARN_ON(count & 1);
 903                iowrite16_rep(addr, buffer, count >> 1);
 904                break;
 905        case sizeof(u32):
 906                SSB_WARN_ON(count & 3);
 907                iowrite32_rep(addr, buffer, count >> 2);
 908                break;
 909        default:
 910                SSB_WARN_ON(1);
 911        }
 912}
 913#endif /* CONFIG_SSB_BLOCKIO */
 914
 915/* Not "static", as it's used in main.c */
 916const struct ssb_bus_ops ssb_pci_ops = {
 917        .read8          = ssb_pci_read8,
 918        .read16         = ssb_pci_read16,
 919        .read32         = ssb_pci_read32,
 920        .write8         = ssb_pci_write8,
 921        .write16        = ssb_pci_write16,
 922        .write32        = ssb_pci_write32,
 923#ifdef CONFIG_SSB_BLOCKIO
 924        .block_read     = ssb_pci_block_read,
 925        .block_write    = ssb_pci_block_write,
 926#endif
 927};
 928
 929static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
 930                                       struct device_attribute *attr,
 931                                       char *buf)
 932{
 933        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
 934        struct ssb_bus *bus;
 935
 936        bus = ssb_pci_dev_to_bus(pdev);
 937        if (!bus)
 938                return -ENODEV;
 939
 940        return ssb_attr_sprom_show(bus, buf, sprom_do_read);
 941}
 942
 943static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
 944                                        struct device_attribute *attr,
 945                                        const char *buf, size_t count)
 946{
 947        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
 948        struct ssb_bus *bus;
 949
 950        bus = ssb_pci_dev_to_bus(pdev);
 951        if (!bus)
 952                return -ENODEV;
 953
 954        return ssb_attr_sprom_store(bus, buf, count,
 955                                    sprom_check_crc, sprom_do_write);
 956}
 957
 958static DEVICE_ATTR(ssb_sprom, 0600,
 959                   ssb_pci_attr_sprom_show,
 960                   ssb_pci_attr_sprom_store);
 961
 962void ssb_pci_exit(struct ssb_bus *bus)
 963{
 964        struct pci_dev *pdev;
 965
 966        if (bus->bustype != SSB_BUSTYPE_PCI)
 967                return;
 968
 969        pdev = bus->host_pci;
 970        device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
 971}
 972
 973int ssb_pci_init(struct ssb_bus *bus)
 974{
 975        struct pci_dev *pdev;
 976        int err;
 977
 978        if (bus->bustype != SSB_BUSTYPE_PCI)
 979                return 0;
 980
 981        pdev = bus->host_pci;
 982        mutex_init(&bus->sprom_mutex);
 983        err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
 984        if (err)
 985                goto out;
 986
 987out:
 988        return err;
 989}
 990