root/drivers/ssb/pci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ssb_pci_switch_coreidx
  2. ssb_pci_switch_core
  3. ssb_pci_xtal
  4. ssb_crc8
  5. sprom_get_mac
  6. ssb_sprom_crc
  7. sprom_check_crc
  8. sprom_do_read
  9. sprom_do_write
  10. sprom_extract_antgain
  11. sprom_extract_r23
  12. sprom_extract_r123
  13. sprom_extract_r458
  14. sprom_extract_r45
  15. sprom_extract_r8
  16. sprom_extract
  17. ssb_pci_sprom_get
  18. ssb_pci_get_boardinfo
  19. ssb_pci_get_invariants
  20. ssb_pci_assert_buspower
  21. ssb_pci_read8
  22. ssb_pci_read16
  23. ssb_pci_read32
  24. ssb_pci_block_read
  25. ssb_pci_write8
  26. ssb_pci_write16
  27. ssb_pci_write32
  28. ssb_pci_block_write
  29. ssb_pci_attr_sprom_show
  30. ssb_pci_attr_sprom_store
  31. ssb_pci_exit
  32. ssb_pci_init

   1 /*
   2  * Sonics Silicon Backplane PCI-Hostbus related functions.
   3  *
   4  * Copyright (C) 2005-2006 Michael Buesch <m@bues.ch>
   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 "ssb_private.h"
  19 
  20 #include <linux/ssb/ssb.h>
  21 #include <linux/ssb/ssb_regs.h>
  22 #include <linux/slab.h>
  23 #include <linux/pci.h>
  24 #include <linux/delay.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 */
  32 int 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;
  58 error:
  59         pr_err("Failed to switch to core %u\n", coreidx);
  60         return -ENODEV;
  61 }
  62 
  63 int 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         pr_info("Switching to %s core, index %d\n",
  71                 ssb_core_name(dev->id.coreid), dev->core_index);
  72 #endif
  73 
  74         spin_lock_irqsave(&bus->bar_lock, flags);
  75         err = ssb_pci_switch_coreidx(bus, dev->core_index);
  76         if (!err)
  77                 bus->mapped_device = dev;
  78         spin_unlock_irqrestore(&bus->bar_lock, flags);
  79 
  80         return err;
  81 }
  82 
  83 /* Enable/disable the on board crystal oscillator and/or PLL. */
  84 int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
  85 {
  86         int err;
  87         u32 in, out, outenable;
  88         u16 pci_status;
  89 
  90         if (bus->bustype != SSB_BUSTYPE_PCI)
  91                 return 0;
  92 
  93         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
  94         if (err)
  95                 goto err_pci;
  96         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
  97         if (err)
  98                 goto err_pci;
  99         err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
 100         if (err)
 101                 goto err_pci;
 102 
 103         outenable |= what;
 104 
 105         if (turn_on) {
 106                 /* Avoid glitching the clock if GPRS is already using it.
 107                  * We can't actually read the state of the PLLPD so we infer it
 108                  * by the value of XTAL_PU which *is* readable via gpioin.
 109                  */
 110                 if (!(in & SSB_GPIO_XTAL)) {
 111                         if (what & SSB_GPIO_XTAL) {
 112                                 /* Turn the crystal on */
 113                                 out |= SSB_GPIO_XTAL;
 114                                 if (what & SSB_GPIO_PLL)
 115                                         out |= SSB_GPIO_PLL;
 116                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
 117                                 if (err)
 118                                         goto err_pci;
 119                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
 120                                                              outenable);
 121                                 if (err)
 122                                         goto err_pci;
 123                                 msleep(1);
 124                         }
 125                         if (what & SSB_GPIO_PLL) {
 126                                 /* Turn the PLL on */
 127                                 out &= ~SSB_GPIO_PLL;
 128                                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
 129                                 if (err)
 130                                         goto err_pci;
 131                                 msleep(5);
 132                         }
 133                 }
 134 
 135                 err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
 136                 if (err)
 137                         goto err_pci;
 138                 pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
 139                 err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
 140                 if (err)
 141                         goto err_pci;
 142         } else {
 143                 if (what & SSB_GPIO_XTAL) {
 144                         /* Turn the crystal off */
 145                         out &= ~SSB_GPIO_XTAL;
 146                 }
 147                 if (what & SSB_GPIO_PLL) {
 148                         /* Turn the PLL off */
 149                         out |= SSB_GPIO_PLL;
 150                 }
 151                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
 152                 if (err)
 153                         goto err_pci;
 154                 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
 155                 if (err)
 156                         goto err_pci;
 157         }
 158 
 159 out:
 160         return err;
 161 
 162 err_pci:
 163         pr_err("Error: ssb_pci_xtal() could not access PCI config space!\n");
 164         err = -EBUSY;
 165         goto out;
 166 }
 167 
 168 /* Get the word-offset for a SSB_SPROM_XXX define. */
 169 #define SPOFF(offset)   ((offset) / sizeof(u16))
 170 /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
 171 #define SPEX16(_outvar, _offset, _mask, _shift) \
 172         out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
 173 #define SPEX32(_outvar, _offset, _mask, _shift) \
 174         out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
 175                            in[SPOFF(_offset)]) & (_mask)) >> (_shift))
 176 #define SPEX(_outvar, _offset, _mask, _shift) \
 177         SPEX16(_outvar, _offset, _mask, _shift)
 178 
 179 #define SPEX_ARRAY8(_field, _offset, _mask, _shift)     \
 180         do {    \
 181                 SPEX(_field[0], _offset +  0, _mask, _shift);   \
 182                 SPEX(_field[1], _offset +  2, _mask, _shift);   \
 183                 SPEX(_field[2], _offset +  4, _mask, _shift);   \
 184                 SPEX(_field[3], _offset +  6, _mask, _shift);   \
 185                 SPEX(_field[4], _offset +  8, _mask, _shift);   \
 186                 SPEX(_field[5], _offset + 10, _mask, _shift);   \
 187                 SPEX(_field[6], _offset + 12, _mask, _shift);   \
 188                 SPEX(_field[7], _offset + 14, _mask, _shift);   \
 189         } while (0)
 190 
 191 
 192 static inline u8 ssb_crc8(u8 crc, u8 data)
 193 {
 194         /* Polynomial:   x^8 + x^7 + x^6 + x^4 + x^2 + 1   */
 195         static const u8 t[] = {
 196                 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
 197                 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
 198                 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
 199                 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
 200                 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
 201                 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
 202                 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
 203                 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
 204                 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
 205                 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
 206                 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
 207                 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
 208                 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
 209                 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
 210                 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
 211                 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
 212                 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
 213                 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
 214                 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
 215                 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
 216                 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
 217                 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
 218                 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
 219                 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
 220                 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
 221                 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
 222                 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
 223                 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
 224                 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
 225                 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
 226                 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
 227                 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
 228         };
 229         return t[crc ^ data];
 230 }
 231 
 232 static void sprom_get_mac(char *mac, const u16 *in)
 233 {
 234         int i;
 235         for (i = 0; i < 3; i++) {
 236                 *mac++ = in[i] >> 8;
 237                 *mac++ = in[i];
 238         }
 239 }
 240 
 241 static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
 242 {
 243         int word;
 244         u8 crc = 0xFF;
 245 
 246         for (word = 0; word < size - 1; word++) {
 247                 crc = ssb_crc8(crc, sprom[word] & 0x00FF);
 248                 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
 249         }
 250         crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
 251         crc ^= 0xFF;
 252 
 253         return crc;
 254 }
 255 
 256 static int sprom_check_crc(const u16 *sprom, size_t size)
 257 {
 258         u8 crc;
 259         u8 expected_crc;
 260         u16 tmp;
 261 
 262         crc = ssb_sprom_crc(sprom, size);
 263         tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
 264         expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
 265         if (crc != expected_crc)
 266                 return -EPROTO;
 267 
 268         return 0;
 269 }
 270 
 271 static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
 272 {
 273         int i;
 274 
 275         for (i = 0; i < bus->sprom_size; i++)
 276                 sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
 277 
 278         return 0;
 279 }
 280 
 281 static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
 282 {
 283         struct pci_dev *pdev = bus->host_pci;
 284         int i, err;
 285         u32 spromctl;
 286         u16 size = bus->sprom_size;
 287 
 288         pr_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
 289         err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
 290         if (err)
 291                 goto err_ctlreg;
 292         spromctl |= SSB_SPROMCTL_WE;
 293         err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
 294         if (err)
 295                 goto err_ctlreg;
 296         pr_notice("[ 0%%");
 297         msleep(500);
 298         for (i = 0; i < size; i++) {
 299                 if (i == size / 4)
 300                         pr_cont("25%%");
 301                 else if (i == size / 2)
 302                         pr_cont("50%%");
 303                 else if (i == (size * 3) / 4)
 304                         pr_cont("75%%");
 305                 else if (i % 2)
 306                         pr_cont(".");
 307                 writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
 308                 msleep(20);
 309         }
 310         err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
 311         if (err)
 312                 goto err_ctlreg;
 313         spromctl &= ~SSB_SPROMCTL_WE;
 314         err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
 315         if (err)
 316                 goto err_ctlreg;
 317         msleep(500);
 318         pr_cont("100%% ]\n");
 319         pr_notice("SPROM written\n");
 320 
 321         return 0;
 322 err_ctlreg:
 323         pr_err("Could not access SPROM control register.\n");
 324         return err;
 325 }
 326 
 327 static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset,
 328                                 u16 mask, u16 shift)
 329 {
 330         u16 v;
 331         u8 gain;
 332 
 333         v = in[SPOFF(offset)];
 334         gain = (v & mask) >> shift;
 335         if (gain == 0xFF)
 336                 gain = 2; /* If unset use 2dBm */
 337         if (sprom_revision == 1) {
 338                 /* Convert to Q5.2 */
 339                 gain <<= 2;
 340         } else {
 341                 /* Q5.2 Fractional part is stored in 0xC0 */
 342                 gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
 343         }
 344 
 345         return (s8)gain;
 346 }
 347 
 348 static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in)
 349 {
 350         SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
 351         SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
 352         SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
 353         SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
 354         SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
 355         SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
 356         SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
 357         SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
 358         SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
 359         SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
 360              SSB_SPROM2_MAXP_A_LO_SHIFT);
 361 }
 362 
 363 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
 364 {
 365         u16 loc[3];
 366 
 367         if (out->revision == 3)                 /* rev 3 moved MAC */
 368                 loc[0] = SSB_SPROM3_IL0MAC;
 369         else {
 370                 loc[0] = SSB_SPROM1_IL0MAC;
 371                 loc[1] = SSB_SPROM1_ET0MAC;
 372                 loc[2] = SSB_SPROM1_ET1MAC;
 373         }
 374         sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
 375         if (out->revision < 3) {        /* only rev 1-2 have et0, et1 */
 376                 sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
 377                 sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
 378         }
 379         SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
 380         SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
 381              SSB_SPROM1_ETHPHY_ET1A_SHIFT);
 382         SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
 383         SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
 384         SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
 385         SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
 386         if (out->revision == 1)
 387                 SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
 388                      SSB_SPROM1_BINF_CCODE_SHIFT);
 389         SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
 390              SSB_SPROM1_BINF_ANTA_SHIFT);
 391         SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
 392              SSB_SPROM1_BINF_ANTBG_SHIFT);
 393         SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
 394         SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
 395         SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
 396         SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
 397         SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
 398         SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
 399         SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
 400         SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
 401              SSB_SPROM1_GPIOA_P1_SHIFT);
 402         SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
 403         SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
 404              SSB_SPROM1_GPIOB_P3_SHIFT);
 405         SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
 406              SSB_SPROM1_MAXPWR_A_SHIFT);
 407         SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
 408         SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
 409              SSB_SPROM1_ITSSI_A_SHIFT);
 410         SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
 411         SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
 412 
 413         SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
 414         SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
 415 
 416         /* Extract the antenna gain values. */
 417         out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
 418                                                      SSB_SPROM1_AGAIN,
 419                                                      SSB_SPROM1_AGAIN_BG,
 420                                                      SSB_SPROM1_AGAIN_BG_SHIFT);
 421         out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
 422                                                      SSB_SPROM1_AGAIN,
 423                                                      SSB_SPROM1_AGAIN_A,
 424                                                      SSB_SPROM1_AGAIN_A_SHIFT);
 425         if (out->revision >= 2)
 426                 sprom_extract_r23(out, in);
 427 }
 428 
 429 /* Revs 4 5 and 8 have partially shared layout */
 430 static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
 431 {
 432         SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
 433              SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
 434         SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
 435              SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
 436         SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
 437              SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
 438         SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
 439              SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
 440 
 441         SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
 442              SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
 443         SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
 444              SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
 445         SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
 446              SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
 447         SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
 448              SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
 449 
 450         SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
 451              SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
 452         SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
 453              SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
 454         SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
 455              SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
 456         SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
 457              SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
 458 
 459         SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
 460              SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
 461         SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
 462              SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
 463         SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
 464              SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
 465         SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
 466              SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
 467 }
 468 
 469 static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
 470 {
 471         static const u16 pwr_info_offset[] = {
 472                 SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1,
 473                 SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3
 474         };
 475         u16 il0mac_offset;
 476         int i;
 477 
 478         BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
 479                      ARRAY_SIZE(out->core_pwr_info));
 480 
 481         if (out->revision == 4)
 482                 il0mac_offset = SSB_SPROM4_IL0MAC;
 483         else
 484                 il0mac_offset = SSB_SPROM5_IL0MAC;
 485 
 486         sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
 487 
 488         SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
 489         SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
 490              SSB_SPROM4_ETHPHY_ET1A_SHIFT);
 491         SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
 492         SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
 493         if (out->revision == 4) {
 494                 SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
 495                 SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
 496                 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
 497                 SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
 498                 SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
 499                 SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
 500         } else {
 501                 SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
 502                 SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
 503                 SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
 504                 SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
 505                 SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
 506                 SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
 507         }
 508         SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
 509              SSB_SPROM4_ANTAVAIL_A_SHIFT);
 510         SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
 511              SSB_SPROM4_ANTAVAIL_BG_SHIFT);
 512         SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
 513         SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
 514              SSB_SPROM4_ITSSI_BG_SHIFT);
 515         SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
 516         SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
 517              SSB_SPROM4_ITSSI_A_SHIFT);
 518         if (out->revision == 4) {
 519                 SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
 520                 SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
 521                      SSB_SPROM4_GPIOA_P1_SHIFT);
 522                 SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
 523                 SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
 524                      SSB_SPROM4_GPIOB_P3_SHIFT);
 525         } else {
 526                 SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
 527                 SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
 528                      SSB_SPROM5_GPIOA_P1_SHIFT);
 529                 SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
 530                 SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
 531                      SSB_SPROM5_GPIOB_P3_SHIFT);
 532         }
 533 
 534         /* Extract the antenna gain values. */
 535         out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
 536                                                      SSB_SPROM4_AGAIN01,
 537                                                      SSB_SPROM4_AGAIN0,
 538                                                      SSB_SPROM4_AGAIN0_SHIFT);
 539         out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
 540                                                      SSB_SPROM4_AGAIN01,
 541                                                      SSB_SPROM4_AGAIN1,
 542                                                      SSB_SPROM4_AGAIN1_SHIFT);
 543         out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
 544                                                      SSB_SPROM4_AGAIN23,
 545                                                      SSB_SPROM4_AGAIN2,
 546                                                      SSB_SPROM4_AGAIN2_SHIFT);
 547         out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
 548                                                      SSB_SPROM4_AGAIN23,
 549                                                      SSB_SPROM4_AGAIN3,
 550                                                      SSB_SPROM4_AGAIN3_SHIFT);
 551 
 552         /* Extract cores power info info */
 553         for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
 554                 u16 o = pwr_info_offset[i];
 555 
 556                 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
 557                         SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT);
 558                 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
 559                         SSB_SPROM4_2G_MAXP, 0);
 560 
 561                 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0);
 562                 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0);
 563                 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0);
 564                 SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0);
 565 
 566                 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
 567                         SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT);
 568                 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
 569                         SSB_SPROM4_5G_MAXP, 0);
 570                 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP,
 571                         SSB_SPROM4_5GH_MAXP, 0);
 572                 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP,
 573                         SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT);
 574 
 575                 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0);
 576                 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0);
 577                 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0);
 578                 SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0);
 579                 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0);
 580                 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0);
 581                 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0);
 582                 SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0);
 583                 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0);
 584                 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0);
 585                 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0);
 586                 SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0);
 587         }
 588 
 589         sprom_extract_r458(out, in);
 590 
 591         /* TODO - get remaining rev 4 stuff needed */
 592 }
 593 
 594 static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
 595 {
 596         int i;
 597         u16 o;
 598         static const u16 pwr_info_offset[] = {
 599                 SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
 600                 SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
 601         };
 602         BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
 603                         ARRAY_SIZE(out->core_pwr_info));
 604 
 605         /* extract the MAC address */
 606         sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
 607 
 608         SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
 609         SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
 610         SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
 611         SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
 612         SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
 613         SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
 614         SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
 615         SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
 616         SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
 617              SSB_SPROM8_ANTAVAIL_A_SHIFT);
 618         SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
 619              SSB_SPROM8_ANTAVAIL_BG_SHIFT);
 620         SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
 621         SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
 622              SSB_SPROM8_ITSSI_BG_SHIFT);
 623         SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
 624         SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
 625              SSB_SPROM8_ITSSI_A_SHIFT);
 626         SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
 627         SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
 628              SSB_SPROM8_MAXP_AL_SHIFT);
 629         SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
 630         SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
 631              SSB_SPROM8_GPIOA_P1_SHIFT);
 632         SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
 633         SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
 634              SSB_SPROM8_GPIOB_P3_SHIFT);
 635         SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
 636         SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
 637              SSB_SPROM8_TRI5G_SHIFT);
 638         SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
 639         SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
 640              SSB_SPROM8_TRI5GH_SHIFT);
 641         SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
 642         SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
 643              SSB_SPROM8_RXPO5G_SHIFT);
 644         SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
 645         SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
 646              SSB_SPROM8_RSSISMC2G_SHIFT);
 647         SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
 648              SSB_SPROM8_RSSISAV2G_SHIFT);
 649         SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
 650              SSB_SPROM8_BXA2G_SHIFT);
 651         SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
 652         SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
 653              SSB_SPROM8_RSSISMC5G_SHIFT);
 654         SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
 655              SSB_SPROM8_RSSISAV5G_SHIFT);
 656         SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
 657              SSB_SPROM8_BXA5G_SHIFT);
 658         SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
 659         SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
 660         SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
 661         SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
 662         SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
 663         SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
 664         SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
 665         SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
 666         SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
 667         SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
 668         SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
 669         SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
 670         SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
 671         SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
 672         SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
 673         SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
 674         SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
 675 
 676         /* Extract the antenna gain values. */
 677         out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
 678                                                      SSB_SPROM8_AGAIN01,
 679                                                      SSB_SPROM8_AGAIN0,
 680                                                      SSB_SPROM8_AGAIN0_SHIFT);
 681         out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
 682                                                      SSB_SPROM8_AGAIN01,
 683                                                      SSB_SPROM8_AGAIN1,
 684                                                      SSB_SPROM8_AGAIN1_SHIFT);
 685         out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
 686                                                      SSB_SPROM8_AGAIN23,
 687                                                      SSB_SPROM8_AGAIN2,
 688                                                      SSB_SPROM8_AGAIN2_SHIFT);
 689         out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
 690                                                      SSB_SPROM8_AGAIN23,
 691                                                      SSB_SPROM8_AGAIN3,
 692                                                      SSB_SPROM8_AGAIN3_SHIFT);
 693 
 694         /* Extract cores power info info */
 695         for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
 696                 o = pwr_info_offset[i];
 697                 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
 698                         SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
 699                 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
 700                         SSB_SPROM8_2G_MAXP, 0);
 701 
 702                 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
 703                 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
 704                 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
 705 
 706                 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
 707                         SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
 708                 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
 709                         SSB_SPROM8_5G_MAXP, 0);
 710                 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
 711                         SSB_SPROM8_5GH_MAXP, 0);
 712                 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
 713                         SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
 714 
 715                 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
 716                 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
 717                 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
 718                 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
 719                 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
 720                 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
 721                 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
 722                 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
 723                 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
 724         }
 725 
 726         /* Extract FEM info */
 727         SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
 728                 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
 729         SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
 730                 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
 731         SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
 732                 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
 733         SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
 734                 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
 735         SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
 736                 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
 737 
 738         SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
 739                 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
 740         SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
 741                 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
 742         SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
 743                 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
 744         SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
 745                 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
 746         SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
 747                 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
 748 
 749         SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
 750              SSB_SPROM8_LEDDC_ON_SHIFT);
 751         SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
 752              SSB_SPROM8_LEDDC_OFF_SHIFT);
 753 
 754         SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
 755              SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
 756         SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
 757              SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
 758         SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
 759              SSB_SPROM8_TXRXC_SWITCH_SHIFT);
 760 
 761         SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
 762 
 763         SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
 764         SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
 765         SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
 766         SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
 767 
 768         SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
 769              SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
 770         SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
 771              SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
 772         SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
 773              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
 774              SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
 775         SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
 776              SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
 777         SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
 778              SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
 779              SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
 780         SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
 781              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
 782              SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
 783         SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
 784              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
 785              SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
 786         SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
 787              SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
 788 
 789         SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
 790         SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
 791         SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
 792         SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
 793 
 794         SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
 795              SSB_SPROM8_THERMAL_TRESH_SHIFT);
 796         SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
 797              SSB_SPROM8_THERMAL_OFFSET_SHIFT);
 798         SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
 799              SSB_SPROM8_TEMPDELTA_PHYCAL,
 800              SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
 801         SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
 802              SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
 803         SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
 804              SSB_SPROM8_TEMPDELTA_HYSTERESIS,
 805              SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
 806         sprom_extract_r458(out, in);
 807 
 808         /* TODO - get remaining rev 8 stuff needed */
 809 }
 810 
 811 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 812                          const u16 *in, u16 size)
 813 {
 814         memset(out, 0, sizeof(*out));
 815 
 816         out->revision = in[size - 1] & 0x00FF;
 817         pr_debug("SPROM revision %d detected\n", out->revision);
 818         memset(out->et0mac, 0xFF, 6);           /* preset et0 and et1 mac */
 819         memset(out->et1mac, 0xFF, 6);
 820 
 821         if ((bus->chip_id & 0xFF00) == 0x4400) {
 822                 /* Workaround: The BCM44XX chip has a stupid revision
 823                  * number stored in the SPROM.
 824                  * Always extract r1. */
 825                 out->revision = 1;
 826                 pr_debug("SPROM treated as revision %d\n", out->revision);
 827         }
 828 
 829         switch (out->revision) {
 830         case 1:
 831         case 2:
 832         case 3:
 833                 sprom_extract_r123(out, in);
 834                 break;
 835         case 4:
 836         case 5:
 837                 sprom_extract_r45(out, in);
 838                 break;
 839         case 8:
 840                 sprom_extract_r8(out, in);
 841                 break;
 842         default:
 843                 pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
 844                         out->revision);
 845                 out->revision = 1;
 846                 sprom_extract_r123(out, in);
 847         }
 848 
 849         if (out->boardflags_lo == 0xFFFF)
 850                 out->boardflags_lo = 0;  /* per specs */
 851         if (out->boardflags_hi == 0xFFFF)
 852                 out->boardflags_hi = 0;  /* per specs */
 853 
 854         return 0;
 855 }
 856 
 857 static int ssb_pci_sprom_get(struct ssb_bus *bus,
 858                              struct ssb_sprom *sprom)
 859 {
 860         int err;
 861         u16 *buf;
 862 
 863         if (!ssb_is_sprom_available(bus)) {
 864                 pr_err("No SPROM available!\n");
 865                 return -ENODEV;
 866         }
 867         if (bus->chipco.dev) {  /* can be unavailable! */
 868                 /*
 869                  * get SPROM offset: SSB_SPROM_BASE1 except for
 870                  * chipcommon rev >= 31 or chip ID is 0x4312 and
 871                  * chipcommon status & 3 == 2
 872                  */
 873                 if (bus->chipco.dev->id.revision >= 31)
 874                         bus->sprom_offset = SSB_SPROM_BASE31;
 875                 else if (bus->chip_id == 0x4312 &&
 876                          (bus->chipco.status & 0x03) == 2)
 877                         bus->sprom_offset = SSB_SPROM_BASE31;
 878                 else
 879                         bus->sprom_offset = SSB_SPROM_BASE1;
 880         } else {
 881                 bus->sprom_offset = SSB_SPROM_BASE1;
 882         }
 883         pr_debug("SPROM offset is 0x%x\n", bus->sprom_offset);
 884 
 885         buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 886         if (!buf)
 887                 return -ENOMEM;
 888         bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
 889         sprom_do_read(bus, buf);
 890         err = sprom_check_crc(buf, bus->sprom_size);
 891         if (err) {
 892                 /* try for a 440 byte SPROM - revision 4 and higher */
 893                 kfree(buf);
 894                 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
 895                               GFP_KERNEL);
 896                 if (!buf)
 897                         return -ENOMEM;
 898                 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
 899                 sprom_do_read(bus, buf);
 900                 err = sprom_check_crc(buf, bus->sprom_size);
 901                 if (err) {
 902                         /* All CRC attempts failed.
 903                          * Maybe there is no SPROM on the device?
 904                          * Now we ask the arch code if there is some sprom
 905                          * available for this device in some other storage */
 906                         err = ssb_fill_sprom_with_fallback(bus, sprom);
 907                         if (err) {
 908                                 pr_warn("WARNING: Using fallback SPROM failed (err %d)\n",
 909                                         err);
 910                                 goto out_free;
 911                         } else {
 912                                 pr_debug("Using SPROM revision %d provided by platform\n",
 913                                          sprom->revision);
 914                                 err = 0;
 915                                 goto out_free;
 916                         }
 917                         pr_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
 918                 }
 919         }
 920         err = sprom_extract(bus, sprom, buf, bus->sprom_size);
 921 
 922 out_free:
 923         kfree(buf);
 924         return err;
 925 }
 926 
 927 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
 928                                   struct ssb_boardinfo *bi)
 929 {
 930         bi->vendor = bus->host_pci->subsystem_vendor;
 931         bi->type = bus->host_pci->subsystem_device;
 932 }
 933 
 934 int ssb_pci_get_invariants(struct ssb_bus *bus,
 935                            struct ssb_init_invariants *iv)
 936 {
 937         int err;
 938 
 939         err = ssb_pci_sprom_get(bus, &iv->sprom);
 940         if (err)
 941                 goto out;
 942         ssb_pci_get_boardinfo(bus, &iv->boardinfo);
 943 
 944 out:
 945         return err;
 946 }
 947 
 948 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
 949 {
 950         if (likely(bus->powered_up))
 951                 return 0;
 952 
 953         pr_err("FATAL ERROR: Bus powered down while accessing PCI MMIO space\n");
 954         if (bus->power_warn_count <= 10) {
 955                 bus->power_warn_count++;
 956                 dump_stack();
 957         }
 958 
 959         return -ENODEV;
 960 }
 961 
 962 static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
 963 {
 964         struct ssb_bus *bus = dev->bus;
 965 
 966         if (unlikely(ssb_pci_assert_buspower(bus)))
 967                 return 0xFF;
 968         if (unlikely(bus->mapped_device != dev)) {
 969                 if (unlikely(ssb_pci_switch_core(bus, dev)))
 970                         return 0xFF;
 971         }
 972         return ioread8(bus->mmio + offset);
 973 }
 974 
 975 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
 976 {
 977         struct ssb_bus *bus = dev->bus;
 978 
 979         if (unlikely(ssb_pci_assert_buspower(bus)))
 980                 return 0xFFFF;
 981         if (unlikely(bus->mapped_device != dev)) {
 982                 if (unlikely(ssb_pci_switch_core(bus, dev)))
 983                         return 0xFFFF;
 984         }
 985         return ioread16(bus->mmio + offset);
 986 }
 987 
 988 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
 989 {
 990         struct ssb_bus *bus = dev->bus;
 991 
 992         if (unlikely(ssb_pci_assert_buspower(bus)))
 993                 return 0xFFFFFFFF;
 994         if (unlikely(bus->mapped_device != dev)) {
 995                 if (unlikely(ssb_pci_switch_core(bus, dev)))
 996                         return 0xFFFFFFFF;
 997         }
 998         return ioread32(bus->mmio + offset);
 999 }
1000 
1001 #ifdef CONFIG_SSB_BLOCKIO
1002 static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
1003                                size_t count, u16 offset, u8 reg_width)
1004 {
1005         struct ssb_bus *bus = dev->bus;
1006         void __iomem *addr = bus->mmio + offset;
1007 
1008         if (unlikely(ssb_pci_assert_buspower(bus)))
1009                 goto error;
1010         if (unlikely(bus->mapped_device != dev)) {
1011                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1012                         goto error;
1013         }
1014         switch (reg_width) {
1015         case sizeof(u8):
1016                 ioread8_rep(addr, buffer, count);
1017                 break;
1018         case sizeof(u16):
1019                 WARN_ON(count & 1);
1020                 ioread16_rep(addr, buffer, count >> 1);
1021                 break;
1022         case sizeof(u32):
1023                 WARN_ON(count & 3);
1024                 ioread32_rep(addr, buffer, count >> 2);
1025                 break;
1026         default:
1027                 WARN_ON(1);
1028         }
1029 
1030         return;
1031 error:
1032         memset(buffer, 0xFF, count);
1033 }
1034 #endif /* CONFIG_SSB_BLOCKIO */
1035 
1036 static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
1037 {
1038         struct ssb_bus *bus = dev->bus;
1039 
1040         if (unlikely(ssb_pci_assert_buspower(bus)))
1041                 return;
1042         if (unlikely(bus->mapped_device != dev)) {
1043                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1044                         return;
1045         }
1046         iowrite8(value, bus->mmio + offset);
1047 }
1048 
1049 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
1050 {
1051         struct ssb_bus *bus = dev->bus;
1052 
1053         if (unlikely(ssb_pci_assert_buspower(bus)))
1054                 return;
1055         if (unlikely(bus->mapped_device != dev)) {
1056                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1057                         return;
1058         }
1059         iowrite16(value, bus->mmio + offset);
1060 }
1061 
1062 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
1063 {
1064         struct ssb_bus *bus = dev->bus;
1065 
1066         if (unlikely(ssb_pci_assert_buspower(bus)))
1067                 return;
1068         if (unlikely(bus->mapped_device != dev)) {
1069                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1070                         return;
1071         }
1072         iowrite32(value, bus->mmio + offset);
1073 }
1074 
1075 #ifdef CONFIG_SSB_BLOCKIO
1076 static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1077                                 size_t count, u16 offset, u8 reg_width)
1078 {
1079         struct ssb_bus *bus = dev->bus;
1080         void __iomem *addr = bus->mmio + offset;
1081 
1082         if (unlikely(ssb_pci_assert_buspower(bus)))
1083                 return;
1084         if (unlikely(bus->mapped_device != dev)) {
1085                 if (unlikely(ssb_pci_switch_core(bus, dev)))
1086                         return;
1087         }
1088         switch (reg_width) {
1089         case sizeof(u8):
1090                 iowrite8_rep(addr, buffer, count);
1091                 break;
1092         case sizeof(u16):
1093                 WARN_ON(count & 1);
1094                 iowrite16_rep(addr, buffer, count >> 1);
1095                 break;
1096         case sizeof(u32):
1097                 WARN_ON(count & 3);
1098                 iowrite32_rep(addr, buffer, count >> 2);
1099                 break;
1100         default:
1101                 WARN_ON(1);
1102         }
1103 }
1104 #endif /* CONFIG_SSB_BLOCKIO */
1105 
1106 /* Not "static", as it's used in main.c */
1107 const struct ssb_bus_ops ssb_pci_ops = {
1108         .read8          = ssb_pci_read8,
1109         .read16         = ssb_pci_read16,
1110         .read32         = ssb_pci_read32,
1111         .write8         = ssb_pci_write8,
1112         .write16        = ssb_pci_write16,
1113         .write32        = ssb_pci_write32,
1114 #ifdef CONFIG_SSB_BLOCKIO
1115         .block_read     = ssb_pci_block_read,
1116         .block_write    = ssb_pci_block_write,
1117 #endif
1118 };
1119 
1120 static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
1121                                        struct device_attribute *attr,
1122                                        char *buf)
1123 {
1124         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1125         struct ssb_bus *bus;
1126 
1127         bus = ssb_pci_dev_to_bus(pdev);
1128         if (!bus)
1129                 return -ENODEV;
1130 
1131         return ssb_attr_sprom_show(bus, buf, sprom_do_read);
1132 }
1133 
1134 static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
1135                                         struct device_attribute *attr,
1136                                         const char *buf, size_t count)
1137 {
1138         struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1139         struct ssb_bus *bus;
1140 
1141         bus = ssb_pci_dev_to_bus(pdev);
1142         if (!bus)
1143                 return -ENODEV;
1144 
1145         return ssb_attr_sprom_store(bus, buf, count,
1146                                     sprom_check_crc, sprom_do_write);
1147 }
1148 
1149 static DEVICE_ATTR(ssb_sprom, 0600,
1150                    ssb_pci_attr_sprom_show,
1151                    ssb_pci_attr_sprom_store);
1152 
1153 void ssb_pci_exit(struct ssb_bus *bus)
1154 {
1155         struct pci_dev *pdev;
1156 
1157         if (bus->bustype != SSB_BUSTYPE_PCI)
1158                 return;
1159 
1160         pdev = bus->host_pci;
1161         device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1162 }
1163 
1164 int ssb_pci_init(struct ssb_bus *bus)
1165 {
1166         struct pci_dev *pdev;
1167         int err;
1168 
1169         if (bus->bustype != SSB_BUSTYPE_PCI)
1170                 return 0;
1171 
1172         pdev = bus->host_pci;
1173         mutex_init(&bus->sprom_mutex);
1174         err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1175         if (err)
1176                 goto out;
1177 
1178 out:
1179         return err;
1180 }

/* [<][>][^][v][top][bottom][index][help] */