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 void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
 471{
 472        int i;
 473        u16 v;
 474
 475        /* extract the MAC address */
 476        for (i = 0; i < 3; i++) {
 477                v = in[SPOFF(SSB_SPROM1_IL0MAC) + i];
 478                *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 479        }
 480        SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
 481        SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
 482        SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
 483        SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
 484             SSB_SPROM8_ANTAVAIL_A_SHIFT);
 485        SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
 486             SSB_SPROM8_ANTAVAIL_BG_SHIFT);
 487        SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
 488        SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
 489             SSB_SPROM8_ITSSI_BG_SHIFT);
 490        SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
 491        SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
 492             SSB_SPROM8_ITSSI_A_SHIFT);
 493        SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
 494        SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
 495             SSB_SPROM8_GPIOA_P1_SHIFT);
 496        SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
 497        SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
 498             SSB_SPROM8_GPIOB_P3_SHIFT);
 499
 500        /* Extract the antenna gain values. */
 501        SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
 502             SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
 503        SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01,
 504             SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
 505        SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23,
 506             SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
 507        SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23,
 508             SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
 509        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
 510               sizeof(out->antenna_gain.ghz5));
 511
 512        /* TODO - get remaining rev 8 stuff needed */
 513}
 514
 515static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 516                         const u16 *in, u16 size)
 517{
 518        memset(out, 0, sizeof(*out));
 519
 520        out->revision = in[size - 1] & 0x00FF;
 521        ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
 522        memset(out->et0mac, 0xFF, 6);           /* preset et0 and et1 mac */
 523        memset(out->et1mac, 0xFF, 6);
 524        if ((bus->chip_id & 0xFF00) == 0x4400) {
 525                /* Workaround: The BCM44XX chip has a stupid revision
 526                 * number stored in the SPROM.
 527                 * Always extract r1. */
 528                out->revision = 1;
 529                sprom_extract_r123(out, in);
 530        } else if (bus->chip_id == 0x4321) {
 531                /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
 532                out->revision = 4;
 533                sprom_extract_r45(out, in);
 534        } else {
 535                switch (out->revision) {
 536                case 1:
 537                case 2:
 538                case 3:
 539                        sprom_extract_r123(out, in);
 540                        break;
 541                case 4:
 542                case 5:
 543                        sprom_extract_r45(out, in);
 544                        break;
 545                case 8:
 546                        sprom_extract_r8(out, in);
 547                        break;
 548                default:
 549                        ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
 550                                   "  revision %d detected. Will extract"
 551                                   " v1\n", out->revision);
 552                        sprom_extract_r123(out, in);
 553                }
 554        }
 555
 556        if (out->boardflags_lo == 0xFFFF)
 557                out->boardflags_lo = 0;  /* per specs */
 558        if (out->boardflags_hi == 0xFFFF)
 559                out->boardflags_hi = 0;  /* per specs */
 560
 561        return 0;
 562}
 563
 564static int ssb_pci_sprom_get(struct ssb_bus *bus,
 565                             struct ssb_sprom *sprom)
 566{
 567        const struct ssb_sprom *fallback;
 568        int err = -ENOMEM;
 569        u16 *buf;
 570
 571        buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 572        if (!buf)
 573                goto out;
 574        bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
 575        sprom_do_read(bus, buf);
 576        err = sprom_check_crc(buf, bus->sprom_size);
 577        if (err) {
 578                /* try for a 440 byte SPROM - revision 4 and higher */
 579                kfree(buf);
 580                buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
 581                              GFP_KERNEL);
 582                if (!buf)
 583                        goto out;
 584                bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
 585                sprom_do_read(bus, buf);
 586                err = sprom_check_crc(buf, bus->sprom_size);
 587                if (err) {
 588                        /* All CRC attempts failed.
 589                         * Maybe there is no SPROM on the device?
 590                         * If we have a fallback, use that. */
 591                        fallback = ssb_get_fallback_sprom();
 592                        if (fallback) {
 593                                memcpy(sprom, fallback, sizeof(*sprom));
 594                                err = 0;
 595                                goto out_free;
 596                        }
 597                        ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
 598                                   " SPROM CRC (corrupt SPROM)\n");
 599                }
 600        }
 601        err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 602
 603out_free:
 604        kfree(buf);
 605out:
 606        return err;
 607}
 608
 609static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
 610                                  struct ssb_boardinfo *bi)
 611{
 612        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_VENDOR_ID,
 613                             &bi->vendor);
 614        pci_read_config_word(bus->host_pci, PCI_SUBSYSTEM_ID,
 615                             &bi->type);
 616        pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
 617                             &bi->rev);
 618}
 619
 620int ssb_pci_get_invariants(struct ssb_bus *bus,
 621                           struct ssb_init_invariants *iv)
 622{
 623        int err;
 624
 625        err = ssb_pci_sprom_get(bus, &iv->sprom);
 626        if (err)
 627                goto out;
 628        ssb_pci_get_boardinfo(bus, &iv->boardinfo);
 629
 630out:
 631        return err;
 632}
 633
 634#ifdef CONFIG_SSB_DEBUG
 635static int ssb_pci_assert_buspower(struct ssb_bus *bus)
 636{
 637        if (likely(bus->powered_up))
 638                return 0;
 639
 640        printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
 641               "while accessing PCI MMIO space\n");
 642        if (bus->power_warn_count <= 10) {
 643                bus->power_warn_count++;
 644                dump_stack();
 645        }
 646
 647        return -ENODEV;
 648}
 649#else /* DEBUG */
 650static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
 651{
 652        return 0;
 653}
 654#endif /* DEBUG */
 655
 656static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
 657{
 658        struct ssb_bus *bus = dev->bus;
 659
 660        if (unlikely(ssb_pci_assert_buspower(bus)))
 661                return 0xFF;
 662        if (unlikely(bus->mapped_device != dev)) {
 663                if (unlikely(ssb_pci_switch_core(bus, dev)))
 664                        return 0xFF;
 665        }
 666        return ioread8(bus->mmio + offset);
 667}
 668
 669static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
 670{
 671        struct ssb_bus *bus = dev->bus;
 672
 673        if (unlikely(ssb_pci_assert_buspower(bus)))
 674                return 0xFFFF;
 675        if (unlikely(bus->mapped_device != dev)) {
 676                if (unlikely(ssb_pci_switch_core(bus, dev)))
 677                        return 0xFFFF;
 678        }
 679        return ioread16(bus->mmio + offset);
 680}
 681
 682static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
 683{
 684        struct ssb_bus *bus = dev->bus;
 685
 686        if (unlikely(ssb_pci_assert_buspower(bus)))
 687                return 0xFFFFFFFF;
 688        if (unlikely(bus->mapped_device != dev)) {
 689                if (unlikely(ssb_pci_switch_core(bus, dev)))
 690                        return 0xFFFFFFFF;
 691        }
 692        return ioread32(bus->mmio + offset);
 693}
 694
 695#ifdef CONFIG_SSB_BLOCKIO
 696static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
 697                               size_t count, u16 offset, u8 reg_width)
 698{
 699        struct ssb_bus *bus = dev->bus;
 700        void __iomem *addr = bus->mmio + offset;
 701
 702        if (unlikely(ssb_pci_assert_buspower(bus)))
 703                goto error;
 704        if (unlikely(bus->mapped_device != dev)) {
 705                if (unlikely(ssb_pci_switch_core(bus, dev)))
 706                        goto error;
 707        }
 708        switch (reg_width) {
 709        case sizeof(u8):
 710                ioread8_rep(addr, buffer, count);
 711                break;
 712        case sizeof(u16):
 713                SSB_WARN_ON(count & 1);
 714                ioread16_rep(addr, buffer, count >> 1);
 715                break;
 716        case sizeof(u32):
 717                SSB_WARN_ON(count & 3);
 718                ioread32_rep(addr, buffer, count >> 2);
 719                break;
 720        default:
 721                SSB_WARN_ON(1);
 722        }
 723
 724        return;
 725error:
 726        memset(buffer, 0xFF, count);
 727}
 728#endif /* CONFIG_SSB_BLOCKIO */
 729
 730static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
 731{
 732        struct ssb_bus *bus = dev->bus;
 733
 734        if (unlikely(ssb_pci_assert_buspower(bus)))
 735                return;
 736        if (unlikely(bus->mapped_device != dev)) {
 737                if (unlikely(ssb_pci_switch_core(bus, dev)))
 738                        return;
 739        }
 740        iowrite8(value, bus->mmio + offset);
 741}
 742
 743static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
 744{
 745        struct ssb_bus *bus = dev->bus;
 746
 747        if (unlikely(ssb_pci_assert_buspower(bus)))
 748                return;
 749        if (unlikely(bus->mapped_device != dev)) {
 750                if (unlikely(ssb_pci_switch_core(bus, dev)))
 751                        return;
 752        }
 753        iowrite16(value, bus->mmio + offset);
 754}
 755
 756static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
 757{
 758        struct ssb_bus *bus = dev->bus;
 759
 760        if (unlikely(ssb_pci_assert_buspower(bus)))
 761                return;
 762        if (unlikely(bus->mapped_device != dev)) {
 763                if (unlikely(ssb_pci_switch_core(bus, dev)))
 764                        return;
 765        }
 766        iowrite32(value, bus->mmio + offset);
 767}
 768
 769#ifdef CONFIG_SSB_BLOCKIO
 770static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
 771                                size_t count, u16 offset, u8 reg_width)
 772{
 773        struct ssb_bus *bus = dev->bus;
 774        void __iomem *addr = bus->mmio + offset;
 775
 776        if (unlikely(ssb_pci_assert_buspower(bus)))
 777                return;
 778        if (unlikely(bus->mapped_device != dev)) {
 779                if (unlikely(ssb_pci_switch_core(bus, dev)))
 780                        return;
 781        }
 782        switch (reg_width) {
 783        case sizeof(u8):
 784                iowrite8_rep(addr, buffer, count);
 785                break;
 786        case sizeof(u16):
 787                SSB_WARN_ON(count & 1);
 788                iowrite16_rep(addr, buffer, count >> 1);
 789                break;
 790        case sizeof(u32):
 791                SSB_WARN_ON(count & 3);
 792                iowrite32_rep(addr, buffer, count >> 2);
 793                break;
 794        default:
 795                SSB_WARN_ON(1);
 796        }
 797}
 798#endif /* CONFIG_SSB_BLOCKIO */
 799
 800/* Not "static", as it's used in main.c */
 801const struct ssb_bus_ops ssb_pci_ops = {
 802        .read8          = ssb_pci_read8,
 803        .read16         = ssb_pci_read16,
 804        .read32         = ssb_pci_read32,
 805        .write8         = ssb_pci_write8,
 806        .write16        = ssb_pci_write16,
 807        .write32        = ssb_pci_write32,
 808#ifdef CONFIG_SSB_BLOCKIO
 809        .block_read     = ssb_pci_block_read,
 810        .block_write    = ssb_pci_block_write,
 811#endif
 812};
 813
 814static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
 815                                       struct device_attribute *attr,
 816                                       char *buf)
 817{
 818        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
 819        struct ssb_bus *bus;
 820
 821        bus = ssb_pci_dev_to_bus(pdev);
 822        if (!bus)
 823                return -ENODEV;
 824
 825        return ssb_attr_sprom_show(bus, buf, sprom_do_read);
 826}
 827
 828static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
 829                                        struct device_attribute *attr,
 830                                        const char *buf, size_t count)
 831{
 832        struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
 833        struct ssb_bus *bus;
 834
 835        bus = ssb_pci_dev_to_bus(pdev);
 836        if (!bus)
 837                return -ENODEV;
 838
 839        return ssb_attr_sprom_store(bus, buf, count,
 840                                    sprom_check_crc, sprom_do_write);
 841}
 842
 843static DEVICE_ATTR(ssb_sprom, 0600,
 844                   ssb_pci_attr_sprom_show,
 845                   ssb_pci_attr_sprom_store);
 846
 847void ssb_pci_exit(struct ssb_bus *bus)
 848{
 849        struct pci_dev *pdev;
 850
 851        if (bus->bustype != SSB_BUSTYPE_PCI)
 852                return;
 853
 854        pdev = bus->host_pci;
 855        device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
 856}
 857
 858int ssb_pci_init(struct ssb_bus *bus)
 859{
 860        struct pci_dev *pdev;
 861        int err;
 862
 863        if (bus->bustype != SSB_BUSTYPE_PCI)
 864                return 0;
 865
 866        pdev = bus->host_pci;
 867        mutex_init(&bus->sprom_mutex);
 868        err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
 869        if (err)
 870                goto out;
 871
 872out:
 873        return err;
 874}
 875