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