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/pci.h>
  21#include <linux/delay.h>
  22
  23#include "ssb_private.h"
  24
  25
  26/* Define the following to 1 to enable a printk on each coreswitch. */
  27#define SSB_VERBOSE_PCICORESWITCH_DEBUG         0
  28
  29
  30/* Lowlevel coreswitching */
  31int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
  32{
  33        int err;
  34        int attempts = 0;
  35        u32 cur_core;
  36
  37        while (1) {
  38                err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
  39                                             (coreidx * SSB_CORE_SIZE)
  40                                             + SSB_ENUM_BASE);
  41                if (err)
  42                        goto error;
  43                err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
  44                                            &cur_core);
  45                if (err)
  46                        goto error;
  47                cur_core = (cur_core - SSB_ENUM_BASE)
  48                           / SSB_CORE_SIZE;
  49                if (cur_core == coreidx)
  50                        break;
  51
  52                if (attempts++ > SSB_BAR0_MAX_RETRIES)
  53                        goto error;
  54                udelay(10);
  55        }
  56        return 0;
  57error:
  58        ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
  59        return -ENODEV;
  60}
  61
  62int ssb_pci_switch_core(struct ssb_bus *bus,
  63                        struct ssb_device *dev)
  64{
  65        int err;
  66        unsigned long flags;
  67
  68#if SSB_VERBOSE_PCICORESWITCH_DEBUG
  69        ssb_printk(KERN_INFO PFX
  70                   "Switching to %s core, index %d\n",
  71                   ssb_core_name(dev->id.coreid),
  72                   dev->core_index);
  73#endif
  74
  75        spin_lock_irqsave(&bus->bar_lock, flags);
  76        err = ssb_pci_switch_coreidx(bus, dev->core_index);
  77        if (!err)
  78                bus->mapped_device = dev;
  79        spin_unlock_irqrestore(&bus->bar_lock, flags);
  80
  81        return err;
  82}
  83
  84/* Enable/disable the on board crystal oscillator and/or PLL. */
  85int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
  86{
  87        int err;
  88        u32 in, out, outenable;
  89        u16 pci_status;
  90
  91        if (bus->bustype != SSB_BUSTYPE_PCI)
  92                return 0;
  93
  94        err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
  95        if (err)
  96                goto err_pci;
  97        err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
  98        if (err)
  99                goto err_pci;
 100        err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
 101        if (err)
 102                goto err_pci;
 103
 104        outenable |= what;
 105
 106        if (turn_on) {
 107                /* Avoid glitching the clock if GPRS is already using it.
 108                 * We can't actually read the state of the PLLPD so we infer it
 109                 * by the value of XTAL_PU which *is* readable via gpioin.
 110                 */
 111                if (!(in & SSB_GPIO_XTAL)) {
 112                        if (what & SSB_GPIO_XTAL) {
 113                                /* Turn the crystal on */
 114                                out |= SSB_GPIO_XTAL;
 115                                if (what & SSB_GPIO_PLL)
 116                                        out |= SSB_GPIO_PLL;
 117                                err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
 118                                if (err)
 119                                        goto err_pci;
 120                                err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
 121                                                             outenable);
 122                                if (err)
 123                                        goto err_pci;
 124                                msleep(1);
 125                        }
 126                        if (what & SSB_GPIO_PLL) {
 127                                /* Turn the PLL on */
 128                                out &= ~SSB_GPIO_PLL;
 129                                err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
 130                                if (err)
 131                                        goto err_pci;
 132                                msleep(5);
 133                        }
 134                }
 135
 136                err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
 137                if (err)
 138                        goto err_pci;
 139                pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
 140                err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
 141                if (err)
 142                        goto err_pci;
 143        } else {
 144                if (what & SSB_GPIO_XTAL) {
 145                        /* Turn the crystal off */
 146                        out &= ~SSB_GPIO_XTAL;
 147                }
 148                if (what & SSB_GPIO_PLL) {
 149                        /* Turn the PLL off */
 150                        out |= SSB_GPIO_PLL;
 151                }
 152                err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
 153                if (err)
 154                        goto err_pci;
 155                err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
 156                if (err)
 157                        goto err_pci;
 158        }
 159
 160out:
 161        return err;
 162
 163err_pci:
 164        printk(KERN_ERR PFX "Error: ssb_pci_xtal() could not access PCI config space!\n");
 165        err = -EBUSY;
 166        goto out;
 167}
 168
 169/* Get the word-offset for a SSB_SPROM_XXX define. */
 170#define SPOFF(offset)   (((offset) - SSB_SPROM_BASE) / sizeof(u16))
 171/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
 172#define SPEX16(_outvar, _offset, _mask, _shift) \
 173        out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
 174#define SPEX32(_outvar, _offset, _mask, _shift) \
 175        out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
 176                           in[SPOFF(_offset)]) & (_mask)) >> (_shift))
 177#define SPEX(_outvar, _offset, _mask, _shift) \
 178        SPEX16(_outvar, _offset, _mask, _shift)
 179
 180
 181static inline u8 ssb_crc8(u8 crc, u8 data)
 182{
 183        /* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
 184        static const u8 t[] = {
 185                0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
 186                0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
 187                0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
 188                0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
 189                0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
 190                0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
 191                0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
 192                0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
 193                0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
 194                0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
 195                0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
 196                0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
 197                0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
 198                0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
 199                0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
 200                0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
 201                0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
 202                0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
 203                0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
 204                0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
 205                0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
 206                0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
 207                0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
 208                0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
 209                0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
 210                0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
 211                0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
 212                0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
 213                0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
 214                0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
 215                0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
 216                0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
 217        };
 218        return t[crc ^ data];
 219}
 220
 221static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
 222{
 223        int word;
 224        u8 crc = 0xFF;
 225
 226        for (word = 0; word < size - 1; word++) {
 227                crc = ssb_crc8(crc, sprom[word] & 0x00FF);
 228                crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
 229        }
 230        crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
 231        crc ^= 0xFF;
 232
 233        return crc;
 234}
 235
 236static int sprom_check_crc(const u16 *sprom, size_t size)
 237{
 238        u8 crc;
 239        u8 expected_crc;
 240        u16 tmp;
 241
 242        crc = ssb_sprom_crc(sprom, size);
 243        tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
 244        expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
 245        if (crc != expected_crc)
 246                return -EPROTO;
 247
 248        return 0;
 249}
 250
 251static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
 252{
 253        int i;
 254
 255        for (i = 0; i < bus->sprom_size; i++)
 256                sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
 257
 258        return 0;
 259}
 260
 261static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
 262{
 263        struct pci_dev *pdev = bus->host_pci;
 264        int i, err;
 265        u32 spromctl;
 266        u16 size = bus->sprom_size;
 267
 268        ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
 269        err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
 270        if (err)
 271                goto err_ctlreg;
 272        spromctl |= SSB_SPROMCTL_WE;
 273        err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
 274        if (err)
 275                goto err_ctlreg;
 276        ssb_printk(KERN_NOTICE PFX "[ 0%%");
 277        msleep(500);
 278        for (i = 0; i < size; i++) {
 279                if (i == size / 4)
 280                        ssb_printk("25%%");
 281                else if (i == size / 2)
 282                        ssb_printk("50%%");
 283                else if (i == (size * 3) / 4)
 284                        ssb_printk("75%%");
 285                else if (i % 2)
 286                        ssb_printk(".");
 287                writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2));
 288                mmiowb();
 289                msleep(20);
 290        }
 291        err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
 292        if (err)
 293                goto err_ctlreg;
 294        spromctl &= ~SSB_SPROMCTL_WE;
 295        err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
 296        if (err)
 297                goto err_ctlreg;
 298        msleep(500);
 299        ssb_printk("100%% ]\n");
 300        ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
 301
 302        return 0;
 303err_ctlreg:
 304        ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
 305        return err;
 306}
 307
 308static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
 309                               u16 mask, u16 shift)
 310{
 311        u16 v;
 312        u8 gain;
 313
 314        v = in[SPOFF(SSB_SPROM1_AGAIN)];
 315        gain = (v & mask) >> shift;
 316        if (gain == 0xFF)
 317                gain = 2; /* If unset use 2dBm */
 318        if (sprom_revision == 1) {
 319                /* Convert to Q5.2 */
 320                gain <<= 2;
 321        } else {
 322                /* Q5.2 Fractional part is stored in 0xC0 */
 323                gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
 324        }
 325
 326        return (s8)gain;
 327}
 328
 329static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 330{
 331        int i;
 332        u16 v;
 333        s8 gain;
 334        u16 loc[3];
 335
 336        if (out->revision == 3)                 /* rev 3 moved MAC */
 337                loc[0] = SSB_SPROM3_IL0MAC;
 338        else {
 339                loc[0] = SSB_SPROM1_IL0MAC;
 340                loc[1] = SSB_SPROM1_ET0MAC;
 341                loc[2] = SSB_SPROM1_ET1MAC;
 342        }
 343        for (i = 0; i < 3; i++) {
 344                v = in[SPOFF(loc[0]) + i];
 345                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 346        }
 347        if (out->revision < 3) {        /* only rev 1-2 have et0, et1 */
 348                for (i = 0; i < 3; i++) {
 349                        v = in[SPOFF(loc[1]) + i];
 350                        *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
 351                }
 352                for (i = 0; i < 3; i++) {
 353                        v = in[SPOFF(loc[2]) + i];
 354                        *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
 355                }
 356        }
 357        SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
 358        SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
 359             SSB_SPROM1_ETHPHY_ET1A_SHIFT);
 360        SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
 361        SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
 362        SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
 363        SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
 364             SSB_SPROM1_BINF_CCODE_SHIFT);
 365        SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
 366             SSB_SPROM1_BINF_ANTA_SHIFT);
 367        SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
 368             SSB_SPROM1_BINF_ANTBG_SHIFT);
 369        SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
 370        SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
 371        SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
 372        SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
 373        SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
 374        SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
 375        SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
 376        SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
 377             SSB_SPROM1_GPIOA_P1_SHIFT);
 378        SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
 379        SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
 380             SSB_SPROM1_GPIOB_P3_SHIFT);
 381        SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
 382             SSB_SPROM1_MAXPWR_A_SHIFT);
 383        SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
 384        SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
 385             SSB_SPROM1_ITSSI_A_SHIFT);
 386        SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
 387        SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
 388        if (out->revision >= 2)
 389                SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
 390
 391        /* Extract the antenna gain values. */
 392        gain = r123_extract_antgain(out->revision, in,
 393                                    SSB_SPROM1_AGAIN_BG,
 394                                    SSB_SPROM1_AGAIN_BG_SHIFT);
 395        out->antenna_gain.ghz24.a0 = gain;
 396        out->antenna_gain.ghz24.a1 = gain;
 397        out->antenna_gain.ghz24.a2 = gain;
 398        out->antenna_gain.ghz24.a3 = gain;
 399        gain = r123_extract_antgain(out->revision, in,
 400                                    SSB_SPROM1_AGAIN_A,
 401                                    SSB_SPROM1_AGAIN_A_SHIFT);
 402        out->antenna_gain.ghz5.a0 = gain;
 403        out->antenna_gain.ghz5.a1 = gain;
 404        out->antenna_gain.ghz5.a2 = gain;
 405        out->antenna_gain.ghz5.a3 = gain;
 406}
 407
 408static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
 409{
 410        int i;
 411        u16 v;
 412        u16 il0mac_offset;
 413
 414        if (out->revision == 4)
 415                il0mac_offset = SSB_SPROM4_IL0MAC;
 416        else
 417                il0mac_offset = SSB_SPROM5_IL0MAC;
 418        /* extract the MAC address */
 419        for (i = 0; i < 3; i++) {
 420                v = in[SPOFF(il0mac_offset) + i];
 421                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 422        }
 423        SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
 424        SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
 425             SSB_SPROM4_ETHPHY_ET1A_SHIFT);
 426        if (out->revision == 4) {
 427                SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
 428                SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
 429                SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
 430        } else {
 431                SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
 432                SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
 433                SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
 434        }
 435        SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
 436             SSB_SPROM4_ANTAVAIL_A_SHIFT);
 437        SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
 438             SSB_SPROM4_ANTAVAIL_BG_SHIFT);
 439        SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
 440        SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
 441             SSB_SPROM4_ITSSI_BG_SHIFT);
 442        SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
 443        SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
 444             SSB_SPROM4_ITSSI_A_SHIFT);
 445        if (out->revision == 4) {
 446                SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
 447                SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
 448                     SSB_SPROM4_GPIOA_P1_SHIFT);
 449                SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
 450                SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
 451                     SSB_SPROM4_GPIOB_P3_SHIFT);
 452        } else {
 453                SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
 454                SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
 455                     SSB_SPROM5_GPIOA_P1_SHIFT);
 456                SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
 457                SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
 458                     SSB_SPROM5_GPIOB_P3_SHIFT);
 459        }
 460
 461        /* Extract the antenna gain values. */
 462        SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
 463             SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
 464        SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
 465             SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
 466        SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
 467             SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
 468        SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
 469             SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
 470        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 471               sizeof(out->antenna_gain.ghz5));
 472
 473        /* TODO - get remaining rev 4 stuff needed */
 474}
 475
 476static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
 477{
 478        int i;
 479        u16 v;
 480
 481        /* extract the MAC address */
 482        for (i = 0; i < 3; i++) {
 483                v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
 484                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 485        }
 486        SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
 487        SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
 488        SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
 489        SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
 490        SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
 491        SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
 492             SSB_SPROM8_ANTAVAIL_A_SHIFT);
 493        SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
 494             SSB_SPROM8_ANTAVAIL_BG_SHIFT);
 495        SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
 496        SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
 497             SSB_SPROM8_ITSSI_BG_SHIFT);
 498        SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
 499        SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
 500             SSB_SPROM8_ITSSI_A_SHIFT);
 501        SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
 502        SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
 503             SSB_SPROM8_MAXP_AL_SHIFT);
 504        SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
 505        SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
 506             SSB_SPROM8_GPIOA_P1_SHIFT);
 507        SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
 508        SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
 509             SSB_SPROM8_GPIOB_P3_SHIFT);
 510        SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
 511        SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
 512             SSB_SPROM8_TRI5G_SHIFT);
 513        SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
 514        SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
 515             SSB_SPROM8_TRI5GH_SHIFT);
 516        SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
 517        SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
 518             SSB_SPROM8_RXPO5G_SHIFT);
 519        SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
 520        SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
 521             SSB_SPROM8_RSSISMC2G_SHIFT);
 522        SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
 523             SSB_SPROM8_RSSISAV2G_SHIFT);
 524        SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
 525             SSB_SPROM8_BXA2G_SHIFT);
 526        SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
 527        SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
 528             SSB_SPROM8_RSSISMC5G_SHIFT);
 529        SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
 530             SSB_SPROM8_RSSISAV5G_SHIFT);
 531        SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
 532             SSB_SPROM8_BXA5G_SHIFT);
 533        SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
 534        SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
 535        SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
 536        SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
 537        SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
 538        SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
 539        SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
 540        SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
 541        SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
 542        SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
 543        SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
 544        SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
 545        SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
 546        SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
 547        SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
 548        SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
 549        SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
 550
 551        /* Extract the antenna gain values. */
 552        SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
 553             SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
 554        SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01,
 555             SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
 556        SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23,
 557             SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
 558        SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23,
 559             SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
 560        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 561               sizeof(out->antenna_gain.ghz5));
 562
 563        /* TODO - get remaining rev 8 stuff needed */
 564}
 565
 566static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 567                         const u16 *in, u16 size)
 568{
 569        memset(out, 0, sizeof(*out));
 570
 571        out->revision = in[size - 1] & 0x00FF;
 572        ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
 573        memset(out->et0mac, 0xFF, 6);           /* preset et0 and et1 mac */
 574        memset(out->et1mac, 0xFF, 6);
 575        if ((bus->chip_id & 0xFF00) == 0x4400) {
 576                /* Workaround: The BCM44XX chip has a stupid revision
 577                 * number stored in the SPROM.
 578                 * Always extract r1. */
 579                out->revision = 1;
 580                sprom_extract_r123(out, in);
 581        } else if (bus->chip_id == 0x4321) {
 582                /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
 583                out->revision = 4;
 584                sprom_extract_r45(out, in);
 585        } else {
 586                switch (out->revision) {
 587                case 1:
 588                case 2:
 589                case 3:
 590                        sprom_extract_r123(out, in);
 591                        break;
 592                case 4:
 593                case 5:
 594                        sprom_extract_r45(out, in);
 595                        break;
 596                case 8:
 597                        sprom_extract_r8(out, in);
 598                        break;
 599                default:
 600                        ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
 601                                   "  revision %d detected. Will extract"
 602                                   " v1\n", out->revision);
 603                        out->revision = 1;
 604                        sprom_extract_r123(out, in);
 605                }
 606        }
 607
 608        if (out->boardflags_lo == 0xFFFF)
 609                out->boardflags_lo = 0;  /* per specs */
 610        if (out->boardflags_hi == 0xFFFF)
 611                out->boardflags_hi = 0;  /* per specs */
 612
 613        return 0;
 614}
 615
 616static int ssb_pci_sprom_get(struct ssb_bus *bus,
 617                             struct ssb_sprom *sprom)
 618{
 619        const struct ssb_sprom *fallback;
 620        int err = -ENOMEM;
 621        u16 *buf;
 622
 623        buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 624        if (!buf)
 625                goto out;
 626        bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
 627        sprom_do_read(bus, buf);
 628        err = sprom_check_crc(buf, bus->sprom_size);
 629        if (err) {
 630                /* try for a 440 byte SPROM - revision 4 and higher */
 631                kfree(buf);
 632                buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
 633                              GFP_KERNEL);
 634                if (!buf)
 635                        goto out;
 636                bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
 637                sprom_do_read(bus, buf);
 638                err = sprom_check_crc(buf, bus->sprom_size);
 639                if (err) {
 640                        /* All CRC attempts failed.
 641                         * Maybe there is no SPROM on the device?
 642                         * If we have a fallback, use that. */
 643                        fallback = ssb_get_fallback_sprom();
 644                        if (fallback) {
 645                                memcpy(sprom, fallback, sizeof(*sprom));
 646                                err = 0;
 647                                goto out_free;
 648                        }
 649                        ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
 650                                   " SPROM CRC (corrupt SPROM)\n");
 651                }
 652        }
 653        err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 654
 655out_free:
 656        kfree(buf);
 657out:
 658        return err;
 659}
 660
 661static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
 662                                  struct ssb_boardinfo *bi)
 663{
 664        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
 665                             &bi->vendor);
 666        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
 667                             &bi->type);
 668        pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
 669                             &bi->rev);
 670}
 671
 672int ssb_pci_get_invariants(struct ssb_bus *bus,
 673                           struct ssb_init_invariants *iv)
 674{
 675        int err;
 676
 677        err = ssb_pci_sprom_get(bus, &iv->sprom);
 678        if (err)
 679                goto out;
 680        ssb_pci_get_boardinfo(bus, &iv->boardinfo);
 681
 682out:
 683        return err;
 684}
 685
 686#ifdef CONFIG_SSB_DEBUG
 687static int ssb_pci_assert_buspower(struct ssb_bus *bus)
 688{
 689        if (likely(bus->powered_up))
 690                return 0;
 691
 692        printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
 693               "while accessing PCI MMIO space\n");
 694        if (bus->power_warn_count <= 10) {
 695                bus->power_warn_count++;
 696                dump_stack();
 697        }
 698
 699        return -ENODEV;
 700}
 701#else /* DEBUG */
 702static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
 703{
 704        return 0;
 705}
 706#endif /* DEBUG */
 707
 708static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
 709{
 710        struct ssb_bus *bus = dev->bus;
 711
 712        if (unlikely(ssb_pci_assert_buspower(bus)))
 713                return 0xFF;
 714        if (unlikely(bus->mapped_device != dev)) {
 715                if (unlikely(ssb_pci_switch_core(bus, dev)))
 716                        return 0xFF;
 717        }
 718        return ioread8(bus->mmio + offset);
 719}
 720
 721static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
 722{
 723        struct ssb_bus *bus = dev->bus;
 724
 725        if (unlikely(ssb_pci_assert_buspower(bus)))
 726                return 0xFFFF;
 727        if (unlikely(bus->mapped_device != dev)) {
 728                if (unlikely(ssb_pci_switch_core(bus, dev)))
 729                        return 0xFFFF;
 730        }
 731        return ioread16(bus->mmio + offset);
 732}
 733
 734static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
 735{
 736        struct ssb_bus *bus = dev->bus;
 737
 738        if (unlikely(ssb_pci_assert_buspower(bus)))
 739                return 0xFFFFFFFF;
 740        if (unlikely(bus->mapped_device != dev)) {
 741                if (unlikely(ssb_pci_switch_core(bus, dev)))
 742                        return 0xFFFFFFFF;
 743        }
 744        return ioread32(bus->mmio + offset);
 745}
 746
 747#ifdef CONFIG_SSB_BLOCKIO
 748static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
 749                               size_t count, u16 offset, u8 reg_width)
 750{
 751        struct ssb_bus *bus = dev->bus;
 752        void __iomem *addr = bus->mmio + offset;
 753
 754        if (unlikely(ssb_pci_assert_buspower(bus)))
 755                goto error;
 756        if (unlikely(bus->mapped_device != dev)) {
 757                if (unlikely(ssb_pci_switch_core(bus, dev)))
 758                        goto error;
 759        }
 760        switch (reg_width) {
 761        case sizeof(u8):
 762                ioread8_rep(addr, buffer, count);
 763                break;
 764        case sizeof(u16):
 765                SSB_WARN_ON(count & 1);
 766                ioread16_rep(addr, buffer, count >> 1);
 767                break;
 768        case sizeof(u32):
 769                SSB_WARN_ON(count & 3);
 770                ioread32_rep(addr, buffer, count >> 2);
 771                break;
 772        default:
 773                SSB_WARN_ON(1);
 774        }
 775
 776        return;
 777error:
 778        memset(buffer, 0xFF, count);
 779}
 780#endif /* CONFIG_SSB_BLOCKIO */
 781
 782static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
 783{
 784        struct ssb_bus *bus = dev->bus;
 785
 786        if (unlikely(ssb_pci_assert_buspower(bus)))
 787                return;
 788        if (unlikely(bus->mapped_device != dev)) {
 789                if (unlikely(ssb_pci_switch_core(bus, dev)))
 790                        return;
 791        }
 792        iowrite8(value, bus->mmio + offset);
 793}
 794
 795static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
 796{
 797        struct ssb_bus *bus = dev->bus;
 798
 799        if (unlikely(ssb_pci_assert_buspower(bus)))
 800                return;
 801        if (unlikely(bus->mapped_device != dev)) {
 802                if (unlikely(ssb_pci_switch_core(bus, dev)))
 803                        return;
 804        }
 805        iowrite16(value, bus->mmio + offset);
 806}
 807
 808static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
 809{
 810        struct ssb_bus *bus = dev->bus;
 811
 812        if (unlikely(ssb_pci_assert_buspower(bus)))
 813                return;
 814        if (unlikely(bus->mapped_device != dev)) {
 815                if (unlikely(ssb_pci_switch_core(bus, dev)))
 816                        return;
 817        }
 818        iowrite32(value, bus->mmio + offset);
 819}
 820
 821#ifdef CONFIG_SSB_BLOCKIO
 822static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
 823                                size_t count, u16 offset, u8 reg_width)
 824{
 825        struct ssb_bus *bus = dev->bus;
 826        void __iomem *addr = bus->mmio + offset;
 827
 828        if (unlikely(ssb_pci_assert_buspower(bus)))
 829                return;
 830        if (unlikely(bus->mapped_device != dev)) {
 831                if (unlikely(ssb_pci_switch_core(bus, dev)))
 832                        return;
 833        }
 834        switch (reg_width) {
 835        case sizeof(u8):
 836                iowrite8_rep(addr, buffer, count);
 837                break;
 838        case sizeof(u16):
 839                SSB_WARN_ON(count & 1);
 840                iowrite16_rep(addr, buffer, count >> 1);
 841                break;
 842        case sizeof(u32):
 843                SSB_WARN_ON(count & 3);
 844                iowrite32_rep(addr, buffer, count >> 2);
 845                break;
 846        default:
 847                SSB_WARN_ON(1);
 848        }
 849}
 850#endif /* CONFIG_SSB_BLOCKIO */
 851
 852/* Not "static", as it's used in main.c */
 853const struct ssb_bus_ops ssb_pci_ops = {
 854        .read8          = ssb_pci_read8,
 855        .read16         = ssb_pci_read16,
 856        .read32         = ssb_pci_read32,
 857        .write8         = ssb_pci_write8,
 858        .write16        = ssb_pci_write16,
 859        .write32        = ssb_pci_write32,
 860#ifdef CONFIG_SSB_BLOCKIO
 861        .block_read     = ssb_pci_block_read,
 862        .block_write    = ssb_pci_block_write,
 863#endif
 864};
 865
 866static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
 867                                       struct device_attribute *attr,
 868                                       char *buf)
 869{
 870        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
 871        struct ssb_bus *bus;
 872
 873        bus = ssb_pci_dev_to_bus(pdev);
 874        if (!bus)
 875                return -ENODEV;
 876
 877        return ssb_attr_sprom_show(bus, buf, sprom_do_read);
 878}
 879
 880static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
 881                                        struct device_attribute *attr,
 882                                        const char *buf, size_t count)
 883{
 884        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
 885        struct ssb_bus *bus;
 886
 887        bus = ssb_pci_dev_to_bus(pdev);
 888        if (!bus)
 889                return -ENODEV;
 890
 891        return ssb_attr_sprom_store(bus, buf, count,
 892                                    sprom_check_crc, sprom_do_write);
 893}
 894
 895static DEVICE_ATTR(ssb_sprom, 0600,
 896                   ssb_pci_attr_sprom_show,
 897                   ssb_pci_attr_sprom_store);
 898
 899void ssb_pci_exit(struct ssb_bus *bus)
 900{
 901        struct pci_dev *pdev;
 902
 903        if (bus->bustype != SSB_BUSTYPE_PCI)
 904                return;
 905
 906        pdev = bus->host_pci;
 907        device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
 908}
 909
 910int ssb_pci_init(struct ssb_bus *bus)
 911{
 912        struct pci_dev *pdev;
 913        int err;
 914
 915        if (bus->bustype != SSB_BUSTYPE_PCI)
 916                return 0;
 917
 918        pdev = bus->host_pci;
 919        mutex_init(&bus->sprom_mutex);
 920        err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
 921        if (err)
 922                goto out;
 923
 924out:
 925        return err;
 926}
 927