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 SPEX(_outvar, _offset, _mask, _shift)   \
 173        out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
 174
 175static inline u8 ssb_crc8(u8 crc, u8 data)
 176{
 177        /* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
 178        static const u8 t[] = {
 179                0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
 180                0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
 181                0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
 182                0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
 183                0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
 184                0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
 185                0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
 186                0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
 187                0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
 188                0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
 189                0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
 190                0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
 191                0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
 192                0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
 193                0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
 194                0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
 195                0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
 196                0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
 197                0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
 198                0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
 199                0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
 200                0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
 201                0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
 202                0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
 203                0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
 204                0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
 205                0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
 206                0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
 207                0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
 208                0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
 209                0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
 210                0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
 211        };
 212        return t[crc ^ data];
 213}
 214
 215static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
 216{
 217        int word;
 218        u8 crc = 0xFF;
 219
 220        for (word = 0; word < size - 1; word++) {
 221                crc = ssb_crc8(crc, sprom[word] & 0x00FF);
 222                crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
 223        }
 224        crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
 225        crc ^= 0xFF;
 226
 227        return crc;
 228}
 229
 230static int sprom_check_crc(const u16 *sprom, size_t size)
 231{
 232        u8 crc;
 233        u8 expected_crc;
 234        u16 tmp;
 235
 236        crc = ssb_sprom_crc(sprom, size);
 237        tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
 238        expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
 239        if (crc != expected_crc)
 240                return -EPROTO;
 241
 242        return 0;
 243}
 244
 245static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
 246{
 247        int i;
 248
 249        for (i = 0; i < bus->sprom_size; i++)
 250                sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
 251
 252        return 0;
 253}
 254
 255static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
 256{
 257        struct pci_dev *pdev = bus->host_pci;
 258        int i, err;
 259        u32 spromctl;
 260        u16 size = bus->sprom_size;
 261
 262        ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
 263        err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
 264        if (err)
 265                goto err_ctlreg;
 266        spromctl |= SSB_SPROMCTL_WE;
 267        err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
 268        if (err)
 269                goto err_ctlreg;
 270        ssb_printk(KERN_NOTICE PFX "[ 0%%");
 271        msleep(500);
 272        for (i = 0; i < size; i++) {
 273                if (i == size / 4)
 274                        ssb_printk("25%%");
 275                else if (i == size / 2)
 276                        ssb_printk("50%%");
 277                else if (i == (size * 3) / 4)
 278                        ssb_printk("75%%");
 279                else if (i % 2)
 280                        ssb_printk(".");
 281                writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2));
 282                mmiowb();
 283                msleep(20);
 284        }
 285        err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
 286        if (err)
 287                goto err_ctlreg;
 288        spromctl &= ~SSB_SPROMCTL_WE;
 289        err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
 290        if (err)
 291                goto err_ctlreg;
 292        msleep(500);
 293        ssb_printk("100%% ]\n");
 294        ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
 295
 296        return 0;
 297err_ctlreg:
 298        ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
 299        return err;
 300}
 301
 302static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
 303                               u16 mask, u16 shift)
 304{
 305        u16 v;
 306        u8 gain;
 307
 308        v = in[SPOFF(SSB_SPROM1_AGAIN)];
 309        gain = (v & mask) >> shift;
 310        if (gain == 0xFF)
 311                gain = 2; /* If unset use 2dBm */
 312        if (sprom_revision == 1) {
 313                /* Convert to Q5.2 */
 314                gain <<= 2;
 315        } else {
 316                /* Q5.2 Fractional part is stored in 0xC0 */
 317                gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
 318        }
 319
 320        return (s8)gain;
 321}
 322
 323static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 324{
 325        int i;
 326        u16 v;
 327        s8 gain;
 328        u16 loc[3];
 329
 330        if (out->revision == 3)                 /* rev 3 moved MAC */
 331                loc[0] = SSB_SPROM3_IL0MAC;
 332        else {
 333                loc[0] = SSB_SPROM1_IL0MAC;
 334                loc[1] = SSB_SPROM1_ET0MAC;
 335                loc[2] = SSB_SPROM1_ET1MAC;
 336        }
 337        for (i = 0; i < 3; i++) {
 338                v = in[SPOFF(loc[0]) + i];
 339                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 340        }
 341        if (out->revision < 3) {        /* only rev 1-2 have et0, et1 */
 342                for (i = 0; i < 3; i++) {
 343                        v = in[SPOFF(loc[1]) + i];
 344                        *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
 345                }
 346                for (i = 0; i < 3; i++) {
 347                        v = in[SPOFF(loc[2]) + i];
 348                        *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
 349                }
 350        }
 351        SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
 352        SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
 353             SSB_SPROM1_ETHPHY_ET1A_SHIFT);
 354        SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
 355        SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
 356        SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
 357        SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
 358             SSB_SPROM1_BINF_CCODE_SHIFT);
 359        SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
 360             SSB_SPROM1_BINF_ANTA_SHIFT);
 361        SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
 362             SSB_SPROM1_BINF_ANTBG_SHIFT);
 363        SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
 364        SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
 365        SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
 366        SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
 367        SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
 368        SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
 369        SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
 370        SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
 371             SSB_SPROM1_GPIOA_P1_SHIFT);
 372        SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
 373        SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
 374             SSB_SPROM1_GPIOB_P3_SHIFT);
 375        SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
 376             SSB_SPROM1_MAXPWR_A_SHIFT);
 377        SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
 378        SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
 379             SSB_SPROM1_ITSSI_A_SHIFT);
 380        SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
 381        SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
 382        if (out->revision >= 2)
 383                SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
 384
 385        /* Extract the antenna gain values. */
 386        gain = r123_extract_antgain(out->revision, in,
 387                                    SSB_SPROM1_AGAIN_BG,
 388                                    SSB_SPROM1_AGAIN_BG_SHIFT);
 389        out->antenna_gain.ghz24.a0 = gain;
 390        out->antenna_gain.ghz24.a1 = gain;
 391        out->antenna_gain.ghz24.a2 = gain;
 392        out->antenna_gain.ghz24.a3 = gain;
 393        gain = r123_extract_antgain(out->revision, in,
 394                                    SSB_SPROM1_AGAIN_A,
 395                                    SSB_SPROM1_AGAIN_A_SHIFT);
 396        out->antenna_gain.ghz5.a0 = gain;
 397        out->antenna_gain.ghz5.a1 = gain;
 398        out->antenna_gain.ghz5.a2 = gain;
 399        out->antenna_gain.ghz5.a3 = gain;
 400}
 401
 402static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
 403{
 404        int i;
 405        u16 v;
 406        u16 il0mac_offset;
 407
 408        if (out->revision == 4)
 409                il0mac_offset = SSB_SPROM4_IL0MAC;
 410        else
 411                il0mac_offset = SSB_SPROM5_IL0MAC;
 412        /* extract the MAC address */
 413        for (i = 0; i < 3; i++) {
 414                v = in[SPOFF(il0mac_offset) + i];
 415                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 416        }
 417        SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
 418        SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
 419             SSB_SPROM4_ETHPHY_ET1A_SHIFT);
 420        if (out->revision == 4) {
 421                SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
 422                SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
 423                SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
 424        } else {
 425                SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
 426                SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
 427                SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
 428        }
 429        SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
 430             SSB_SPROM4_ANTAVAIL_A_SHIFT);
 431        SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
 432             SSB_SPROM4_ANTAVAIL_BG_SHIFT);
 433        SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
 434        SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
 435             SSB_SPROM4_ITSSI_BG_SHIFT);
 436        SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
 437        SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
 438             SSB_SPROM4_ITSSI_A_SHIFT);
 439        if (out->revision == 4) {
 440                SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
 441                SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
 442                     SSB_SPROM4_GPIOA_P1_SHIFT);
 443                SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
 444                SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
 445                     SSB_SPROM4_GPIOB_P3_SHIFT);
 446        } else {
 447                SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
 448                SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
 449                     SSB_SPROM5_GPIOA_P1_SHIFT);
 450                SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
 451                SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
 452                     SSB_SPROM5_GPIOB_P3_SHIFT);
 453        }
 454
 455        /* Extract the antenna gain values. */
 456        SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
 457             SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
 458        SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
 459             SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
 460        SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
 461             SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
 462        SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
 463             SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
 464        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 465               sizeof(out->antenna_gain.ghz5));
 466
 467        /* TODO - get remaining rev 4 stuff needed */
 468}
 469
 470static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 471                         const u16 *in, u16 size)
 472{
 473        memset(out, 0, sizeof(*out));
 474
 475        out->revision = in[size - 1] & 0x00FF;
 476        ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
 477        memset(out->et0mac, 0xFF, 6);           /* preset et0 and et1 mac */
 478        memset(out->et1mac, 0xFF, 6);
 479        if ((bus->chip_id & 0xFF00) == 0x4400) {
 480                /* Workaround: The BCM44XX chip has a stupid revision
 481                 * number stored in the SPROM.
 482                 * Always extract r1. */
 483                out->revision = 1;
 484                sprom_extract_r123(out, in);
 485        } else if (bus->chip_id == 0x4321) {
 486                /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
 487                out->revision = 4;
 488                sprom_extract_r45(out, in);
 489        } else {
 490                if (out->revision == 0)
 491                        goto unsupported;
 492                if (out->revision >= 1 && out->revision <= 3) {
 493                        sprom_extract_r123(out, in);
 494                }
 495                if (out->revision == 4 || out->revision == 5)
 496                        sprom_extract_r45(out, in);
 497                if (out->revision > 5)
 498                        goto unsupported;
 499        }
 500
 501        if (out->boardflags_lo == 0xFFFF)
 502                out->boardflags_lo = 0;  /* per specs */
 503        if (out->boardflags_hi == 0xFFFF)
 504                out->boardflags_hi = 0;  /* per specs */
 505
 506        return 0;
 507unsupported:
 508        ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
 509                   "detected. Will extract v1\n", out->revision);
 510        sprom_extract_r123(out, in);
 511        return 0;
 512}
 513
 514static int ssb_pci_sprom_get(struct ssb_bus *bus,
 515                             struct ssb_sprom *sprom)
 516{
 517        int err = -ENOMEM;
 518        u16 *buf;
 519
 520        buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 521        if (!buf)
 522                goto out;
 523        bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
 524        sprom_do_read(bus, buf);
 525        err = sprom_check_crc(buf, bus->sprom_size);
 526        if (err) {
 527                /* try for a 440 byte SPROM - revision 4 and higher */
 528                kfree(buf);
 529                buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
 530                              GFP_KERNEL);
 531                if (!buf)
 532                        goto out;
 533                bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
 534                sprom_do_read(bus, buf);
 535                err = sprom_check_crc(buf, bus->sprom_size);
 536                if (err)
 537                        ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
 538                                   " SPROM CRC (corrupt SPROM)\n");
 539        }
 540        err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 541
 542        kfree(buf);
 543out:
 544        return err;
 545}
 546
 547static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
 548                                  struct ssb_boardinfo *bi)
 549{
 550        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
 551                             &bi->vendor);
 552        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
 553                             &bi->type);
 554        pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
 555                             &bi->rev);
 556}
 557
 558int ssb_pci_get_invariants(struct ssb_bus *bus,
 559                           struct ssb_init_invariants *iv)
 560{
 561        int err;
 562
 563        err = ssb_pci_sprom_get(bus, &iv->sprom);
 564        if (err)
 565                goto out;
 566        ssb_pci_get_boardinfo(bus, &iv->boardinfo);
 567
 568out:
 569        return err;
 570}
 571
 572#ifdef CONFIG_SSB_DEBUG
 573static int ssb_pci_assert_buspower(struct ssb_bus *bus)
 574{
 575        if (likely(bus->powered_up))
 576                return 0;
 577
 578        printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
 579               "while accessing PCI MMIO space\n");
 580        if (bus->power_warn_count <= 10) {
 581                bus->power_warn_count++;
 582                dump_stack();
 583        }
 584
 585        return -ENODEV;
 586}
 587#else /* DEBUG */
 588static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
 589{
 590        return 0;
 591}
 592#endif /* DEBUG */
 593
 594static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
 595{
 596        struct ssb_bus *bus = dev->bus;
 597
 598        if (unlikely(ssb_pci_assert_buspower(bus)))
 599                return 0xFF;
 600        if (unlikely(bus->mapped_device != dev)) {
 601                if (unlikely(ssb_pci_switch_core(bus, dev)))
 602                        return 0xFF;
 603        }
 604        return ioread8(bus->mmio + offset);
 605}
 606
 607static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
 608{
 609        struct ssb_bus *bus = dev->bus;
 610
 611        if (unlikely(ssb_pci_assert_buspower(bus)))
 612                return 0xFFFF;
 613        if (unlikely(bus->mapped_device != dev)) {
 614                if (unlikely(ssb_pci_switch_core(bus, dev)))
 615                        return 0xFFFF;
 616        }
 617        return ioread16(bus->mmio + offset);
 618}
 619
 620static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
 621{
 622        struct ssb_bus *bus = dev->bus;
 623
 624        if (unlikely(ssb_pci_assert_buspower(bus)))
 625                return 0xFFFFFFFF;
 626        if (unlikely(bus->mapped_device != dev)) {
 627                if (unlikely(ssb_pci_switch_core(bus, dev)))
 628                        return 0xFFFFFFFF;
 629        }
 630        return ioread32(bus->mmio + offset);
 631}
 632
 633#ifdef CONFIG_SSB_BLOCKIO
 634static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
 635                               size_t count, u16 offset, u8 reg_width)
 636{
 637        struct ssb_bus *bus = dev->bus;
 638        void __iomem *addr = bus->mmio + offset;
 639
 640        if (unlikely(ssb_pci_assert_buspower(bus)))
 641                goto error;
 642        if (unlikely(bus->mapped_device != dev)) {
 643                if (unlikely(ssb_pci_switch_core(bus, dev)))
 644                        goto error;
 645        }
 646        switch (reg_width) {
 647        case sizeof(u8):
 648                ioread8_rep(addr, buffer, count);
 649                break;
 650        case sizeof(u16):
 651                SSB_WARN_ON(count & 1);
 652                ioread16_rep(addr, buffer, count >> 1);
 653                break;
 654        case sizeof(u32):
 655                SSB_WARN_ON(count & 3);
 656                ioread32_rep(addr, buffer, count >> 2);
 657                break;
 658        default:
 659                SSB_WARN_ON(1);
 660        }
 661
 662        return;
 663error:
 664        memset(buffer, 0xFF, count);
 665}
 666#endif /* CONFIG_SSB_BLOCKIO */
 667
 668static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
 669{
 670        struct ssb_bus *bus = dev->bus;
 671
 672        if (unlikely(ssb_pci_assert_buspower(bus)))
 673                return;
 674        if (unlikely(bus->mapped_device != dev)) {
 675                if (unlikely(ssb_pci_switch_core(bus, dev)))
 676                        return;
 677        }
 678        iowrite8(value, bus->mmio + offset);
 679}
 680
 681static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
 682{
 683        struct ssb_bus *bus = dev->bus;
 684
 685        if (unlikely(ssb_pci_assert_buspower(bus)))
 686                return;
 687        if (unlikely(bus->mapped_device != dev)) {
 688                if (unlikely(ssb_pci_switch_core(bus, dev)))
 689                        return;
 690        }
 691        iowrite16(value, bus->mmio + offset);
 692}
 693
 694static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
 695{
 696        struct ssb_bus *bus = dev->bus;
 697
 698        if (unlikely(ssb_pci_assert_buspower(bus)))
 699                return;
 700        if (unlikely(bus->mapped_device != dev)) {
 701                if (unlikely(ssb_pci_switch_core(bus, dev)))
 702                        return;
 703        }
 704        iowrite32(value, bus->mmio + offset);
 705}
 706
 707#ifdef CONFIG_SSB_BLOCKIO
 708static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
 709                                size_t count, u16 offset, u8 reg_width)
 710{
 711        struct ssb_bus *bus = dev->bus;
 712        void __iomem *addr = bus->mmio + offset;
 713
 714        if (unlikely(ssb_pci_assert_buspower(bus)))
 715                return;
 716        if (unlikely(bus->mapped_device != dev)) {
 717                if (unlikely(ssb_pci_switch_core(bus, dev)))
 718                        return;
 719        }
 720        switch (reg_width) {
 721        case sizeof(u8):
 722                iowrite8_rep(addr, buffer, count);
 723                break;
 724        case sizeof(u16):
 725                SSB_WARN_ON(count & 1);
 726                iowrite16_rep(addr, buffer, count >> 1);
 727                break;
 728        case sizeof(u32):
 729                SSB_WARN_ON(count & 3);
 730                iowrite32_rep(addr, buffer, count >> 2);
 731                break;
 732        default:
 733                SSB_WARN_ON(1);
 734        }
 735}
 736#endif /* CONFIG_SSB_BLOCKIO */
 737
 738/* Not "static", as it's used in main.c */
 739const struct ssb_bus_ops ssb_pci_ops = {
 740        .read8          = ssb_pci_read8,
 741        .read16         = ssb_pci_read16,
 742        .read32         = ssb_pci_read32,
 743        .write8         = ssb_pci_write8,
 744        .write16        = ssb_pci_write16,
 745        .write32        = ssb_pci_write32,
 746#ifdef CONFIG_SSB_BLOCKIO
 747        .block_read     = ssb_pci_block_read,
 748        .block_write    = ssb_pci_block_write,
 749#endif
 750};
 751
 752static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
 753                                       struct device_attribute *attr,
 754                                       char *buf)
 755{
 756        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
 757        struct ssb_bus *bus;
 758
 759        bus = ssb_pci_dev_to_bus(pdev);
 760        if (!bus)
 761                return -ENODEV;
 762
 763        return ssb_attr_sprom_show(bus, buf, sprom_do_read);
 764}
 765
 766static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
 767                                        struct device_attribute *attr,
 768                                        const char *buf, size_t count)
 769{
 770        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
 771        struct ssb_bus *bus;
 772
 773        bus = ssb_pci_dev_to_bus(pdev);
 774        if (!bus)
 775                return -ENODEV;
 776
 777        return ssb_attr_sprom_store(bus, buf, count,
 778                                    sprom_check_crc, sprom_do_write);
 779}
 780
 781static DEVICE_ATTR(ssb_sprom, 0600,
 782                   ssb_pci_attr_sprom_show,
 783                   ssb_pci_attr_sprom_store);
 784
 785void ssb_pci_exit(struct ssb_bus *bus)
 786{
 787        struct pci_dev *pdev;
 788
 789        if (bus->bustype != SSB_BUSTYPE_PCI)
 790                return;
 791
 792        pdev = bus->host_pci;
 793        device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
 794}
 795
 796int ssb_pci_init(struct ssb_bus *bus)
 797{
 798        struct pci_dev *pdev;
 799        int err;
 800
 801        if (bus->bustype != SSB_BUSTYPE_PCI)
 802                return 0;
 803
 804        pdev = bus->host_pci;
 805        mutex_init(&bus->sprom_mutex);
 806        err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
 807        if (err)
 808                goto out;
 809
 810out:
 811        return err;
 812}
 813