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                loc[1] = SSB_SPROM3_ET0MAC;
 333                loc[2] = SSB_SPROM3_ET1MAC;
 334        } else {
 335                loc[0] = SSB_SPROM1_IL0MAC;
 336                loc[1] = SSB_SPROM1_ET0MAC;
 337                loc[2] = SSB_SPROM1_ET1MAC;
 338        }
 339        for (i = 0; i < 3; i++) {
 340                v = in[SPOFF(loc[0]) + i];
 341                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 342        }
 343        for (i = 0; i < 3; i++) {
 344                v = in[SPOFF(loc[1]) + i];
 345                *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
 346        }
 347        for (i = 0; i < 3; i++) {
 348                v = in[SPOFF(loc[2]) + i];
 349                *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
 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_r4(struct ssb_sprom *out, const u16 *in)
 403{
 404        int i;
 405        u16 v;
 406
 407        /* extract the equivalent of the r1 variables */
 408        for (i = 0; i < 3; i++) {
 409                v = in[SPOFF(SSB_SPROM4_IL0MAC) + i];
 410                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 411        }
 412        for (i = 0; i < 3; i++) {
 413                v = in[SPOFF(SSB_SPROM4_ET0MAC) + i];
 414                *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
 415        }
 416        for (i = 0; i < 3; i++) {
 417                v = in[SPOFF(SSB_SPROM4_ET1MAC) + i];
 418                *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
 419        }
 420        SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
 421        SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
 422             SSB_SPROM4_ETHPHY_ET1A_SHIFT);
 423        SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
 424        SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
 425        SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
 426        SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
 427             SSB_SPROM4_ANTAVAIL_A_SHIFT);
 428        SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
 429             SSB_SPROM4_ANTAVAIL_BG_SHIFT);
 430        SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
 431        SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
 432             SSB_SPROM4_ITSSI_BG_SHIFT);
 433        SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
 434        SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
 435             SSB_SPROM4_ITSSI_A_SHIFT);
 436        SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
 437        SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
 438             SSB_SPROM4_GPIOA_P1_SHIFT);
 439        SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
 440        SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
 441             SSB_SPROM4_GPIOB_P3_SHIFT);
 442
 443        /* Extract the antenna gain values. */
 444        SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
 445             SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
 446        SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
 447             SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
 448        SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
 449             SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
 450        SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
 451             SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
 452        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 453               sizeof(out->antenna_gain.ghz5));
 454
 455        /* TODO - get remaining rev 4 stuff needed */
 456}
 457
 458static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 459                         const u16 *in, u16 size)
 460{
 461        memset(out, 0, sizeof(*out));
 462
 463        out->revision = in[size - 1] & 0x00FF;
 464        ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
 465        if ((bus->chip_id & 0xFF00) == 0x4400) {
 466                /* Workaround: The BCM44XX chip has a stupid revision
 467                 * number stored in the SPROM.
 468                 * Always extract r1. */
 469                out->revision = 1;
 470                sprom_extract_r123(out, in);
 471        } else if (bus->chip_id == 0x4321) {
 472                /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
 473                out->revision = 4;
 474                sprom_extract_r4(out, in);
 475        } else {
 476                if (out->revision == 0)
 477                        goto unsupported;
 478                if (out->revision >= 1 && out->revision <= 3) {
 479                        sprom_extract_r123(out, in);
 480                }
 481                if (out->revision == 4)
 482                        sprom_extract_r4(out, in);
 483                if (out->revision >= 5)
 484                        goto unsupported;
 485        }
 486
 487        if (out->boardflags_lo == 0xFFFF)
 488                out->boardflags_lo = 0;  /* per specs */
 489        if (out->boardflags_hi == 0xFFFF)
 490                out->boardflags_hi = 0;  /* per specs */
 491
 492        return 0;
 493unsupported:
 494        ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
 495                   "detected. Will extract v1\n", out->revision);
 496        sprom_extract_r123(out, in);
 497        return 0;
 498}
 499
 500static int ssb_pci_sprom_get(struct ssb_bus *bus,
 501                             struct ssb_sprom *sprom)
 502{
 503        int err = -ENOMEM;
 504        u16 *buf;
 505
 506        buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 507        if (!buf)
 508                goto out;
 509        bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
 510        sprom_do_read(bus, buf);
 511        err = sprom_check_crc(buf, bus->sprom_size);
 512        if (err) {
 513                /* try for a 440 byte SPROM - revision 4 and higher */
 514                kfree(buf);
 515                buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
 516                              GFP_KERNEL);
 517                if (!buf)
 518                        goto out;
 519                bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
 520                sprom_do_read(bus, buf);
 521                err = sprom_check_crc(buf, bus->sprom_size);
 522                if (err)
 523                        ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
 524                                   " SPROM CRC (corrupt SPROM)\n");
 525        }
 526        err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 527
 528        kfree(buf);
 529out:
 530        return err;
 531}
 532
 533static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
 534                                  struct ssb_boardinfo *bi)
 535{
 536        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
 537                             &bi->vendor);
 538        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
 539                             &bi->type);
 540        pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
 541                             &bi->rev);
 542}
 543
 544int ssb_pci_get_invariants(struct ssb_bus *bus,
 545                           struct ssb_init_invariants *iv)
 546{
 547        int err;
 548
 549        err = ssb_pci_sprom_get(bus, &iv->sprom);
 550        if (err)
 551                goto out;
 552        ssb_pci_get_boardinfo(bus, &iv->boardinfo);
 553
 554out:
 555        return err;
 556}
 557
 558#ifdef CONFIG_SSB_DEBUG
 559static int ssb_pci_assert_buspower(struct ssb_bus *bus)
 560{
 561        if (likely(bus->powered_up))
 562                return 0;
 563
 564        printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
 565               "while accessing PCI MMIO space\n");
 566        if (bus->power_warn_count <= 10) {
 567                bus->power_warn_count++;
 568                dump_stack();
 569        }
 570
 571        return -ENODEV;
 572}
 573#else /* DEBUG */
 574static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
 575{
 576        return 0;
 577}
 578#endif /* DEBUG */
 579
 580static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
 581{
 582        struct ssb_bus *bus = dev->bus;
 583
 584        if (unlikely(ssb_pci_assert_buspower(bus)))
 585                return 0xFF;
 586        if (unlikely(bus->mapped_device != dev)) {
 587                if (unlikely(ssb_pci_switch_core(bus, dev)))
 588                        return 0xFF;
 589        }
 590        return ioread8(bus->mmio + offset);
 591}
 592
 593static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
 594{
 595        struct ssb_bus *bus = dev->bus;
 596
 597        if (unlikely(ssb_pci_assert_buspower(bus)))
 598                return 0xFFFF;
 599        if (unlikely(bus->mapped_device != dev)) {
 600                if (unlikely(ssb_pci_switch_core(bus, dev)))
 601                        return 0xFFFF;
 602        }
 603        return ioread16(bus->mmio + offset);
 604}
 605
 606static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
 607{
 608        struct ssb_bus *bus = dev->bus;
 609
 610        if (unlikely(ssb_pci_assert_buspower(bus)))
 611                return 0xFFFFFFFF;
 612        if (unlikely(bus->mapped_device != dev)) {
 613                if (unlikely(ssb_pci_switch_core(bus, dev)))
 614                        return 0xFFFFFFFF;
 615        }
 616        return ioread32(bus->mmio + offset);
 617}
 618
 619#ifdef CONFIG_SSB_BLOCKIO
 620static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
 621                               size_t count, u16 offset, u8 reg_width)
 622{
 623        struct ssb_bus *bus = dev->bus;
 624        void __iomem *addr = bus->mmio + offset;
 625
 626        if (unlikely(ssb_pci_assert_buspower(bus)))
 627                goto error;
 628        if (unlikely(bus->mapped_device != dev)) {
 629                if (unlikely(ssb_pci_switch_core(bus, dev)))
 630                        goto error;
 631        }
 632        switch (reg_width) {
 633        case sizeof(u8):
 634                ioread8_rep(addr, buffer, count);
 635                break;
 636        case sizeof(u16):
 637                SSB_WARN_ON(count & 1);
 638                ioread16_rep(addr, buffer, count >> 1);
 639                break;
 640        case sizeof(u32):
 641                SSB_WARN_ON(count & 3);
 642                ioread32_rep(addr, buffer, count >> 2);
 643                break;
 644        default:
 645                SSB_WARN_ON(1);
 646        }
 647
 648        return;
 649error:
 650        memset(buffer, 0xFF, count);
 651}
 652#endif /* CONFIG_SSB_BLOCKIO */
 653
 654static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
 655{
 656        struct ssb_bus *bus = dev->bus;
 657
 658        if (unlikely(ssb_pci_assert_buspower(bus)))
 659                return;
 660        if (unlikely(bus->mapped_device != dev)) {
 661                if (unlikely(ssb_pci_switch_core(bus, dev)))
 662                        return;
 663        }
 664        iowrite8(value, bus->mmio + offset);
 665}
 666
 667static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
 668{
 669        struct ssb_bus *bus = dev->bus;
 670
 671        if (unlikely(ssb_pci_assert_buspower(bus)))
 672                return;
 673        if (unlikely(bus->mapped_device != dev)) {
 674                if (unlikely(ssb_pci_switch_core(bus, dev)))
 675                        return;
 676        }
 677        iowrite16(value, bus->mmio + offset);
 678}
 679
 680static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
 681{
 682        struct ssb_bus *bus = dev->bus;
 683
 684        if (unlikely(ssb_pci_assert_buspower(bus)))
 685                return;
 686        if (unlikely(bus->mapped_device != dev)) {
 687                if (unlikely(ssb_pci_switch_core(bus, dev)))
 688                        return;
 689        }
 690        iowrite32(value, bus->mmio + offset);
 691}
 692
 693#ifdef CONFIG_SSB_BLOCKIO
 694static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
 695                                size_t count, u16 offset, u8 reg_width)
 696{
 697        struct ssb_bus *bus = dev->bus;
 698        void __iomem *addr = bus->mmio + offset;
 699
 700        if (unlikely(ssb_pci_assert_buspower(bus)))
 701                return;
 702        if (unlikely(bus->mapped_device != dev)) {
 703                if (unlikely(ssb_pci_switch_core(bus, dev)))
 704                        return;
 705        }
 706        switch (reg_width) {
 707        case sizeof(u8):
 708                iowrite8_rep(addr, buffer, count);
 709                break;
 710        case sizeof(u16):
 711                SSB_WARN_ON(count & 1);
 712                iowrite16_rep(addr, buffer, count >> 1);
 713                break;
 714        case sizeof(u32):
 715                SSB_WARN_ON(count & 3);
 716                iowrite32_rep(addr, buffer, count >> 2);
 717                break;
 718        default:
 719                SSB_WARN_ON(1);
 720        }
 721}
 722#endif /* CONFIG_SSB_BLOCKIO */
 723
 724/* Not "static", as it's used in main.c */
 725const struct ssb_bus_ops ssb_pci_ops = {
 726        .read8          = ssb_pci_read8,
 727        .read16         = ssb_pci_read16,
 728        .read32         = ssb_pci_read32,
 729        .write8         = ssb_pci_write8,
 730        .write16        = ssb_pci_write16,
 731        .write32        = ssb_pci_write32,
 732#ifdef CONFIG_SSB_BLOCKIO
 733        .block_read     = ssb_pci_block_read,
 734        .block_write    = ssb_pci_block_write,
 735#endif
 736};
 737
 738static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
 739                                       struct device_attribute *attr,
 740                                       char *buf)
 741{
 742        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
 743        struct ssb_bus *bus;
 744
 745        bus = ssb_pci_dev_to_bus(pdev);
 746        if (!bus)
 747                return -ENODEV;
 748
 749        return ssb_attr_sprom_show(bus, buf, sprom_do_read);
 750}
 751
 752static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
 753                                        struct device_attribute *attr,
 754                                        const char *buf, size_t count)
 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_store(bus, buf, count,
 764                                    sprom_check_crc, sprom_do_write);
 765}
 766
 767static DEVICE_ATTR(ssb_sprom, 0600,
 768                   ssb_pci_attr_sprom_show,
 769                   ssb_pci_attr_sprom_store);
 770
 771void ssb_pci_exit(struct ssb_bus *bus)
 772{
 773        struct pci_dev *pdev;
 774
 775        if (bus->bustype != SSB_BUSTYPE_PCI)
 776                return;
 777
 778        pdev = bus->host_pci;
 779        device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
 780}
 781
 782int ssb_pci_init(struct ssb_bus *bus)
 783{
 784        struct pci_dev *pdev;
 785        int err;
 786
 787        if (bus->bustype != SSB_BUSTYPE_PCI)
 788                return 0;
 789
 790        pdev = bus->host_pci;
 791        mutex_init(&bus->sprom_mutex);
 792        err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
 793        if (err)
 794                goto out;
 795
 796out:
 797        return err;
 798}
 799