0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include "ssb_private.h"
0019
0020 #include <linux/ssb/ssb.h>
0021 #include <linux/ssb/ssb_regs.h>
0022 #include <linux/slab.h>
0023 #include <linux/pci.h>
0024 #include <linux/delay.h>
0025
0026
0027
0028 #define SSB_VERBOSE_PCICORESWITCH_DEBUG 0
0029
0030
0031
0032 int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
0033 {
0034 int err;
0035 int attempts = 0;
0036 u32 cur_core;
0037
0038 while (1) {
0039 err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
0040 (coreidx * SSB_CORE_SIZE)
0041 + SSB_ENUM_BASE);
0042 if (err)
0043 goto error;
0044 err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
0045 &cur_core);
0046 if (err)
0047 goto error;
0048 cur_core = (cur_core - SSB_ENUM_BASE)
0049 / SSB_CORE_SIZE;
0050 if (cur_core == coreidx)
0051 break;
0052
0053 if (attempts++ > SSB_BAR0_MAX_RETRIES)
0054 goto error;
0055 udelay(10);
0056 }
0057 return 0;
0058 error:
0059 pr_err("Failed to switch to core %u\n", coreidx);
0060 return -ENODEV;
0061 }
0062
0063 int ssb_pci_switch_core(struct ssb_bus *bus,
0064 struct ssb_device *dev)
0065 {
0066 int err;
0067 unsigned long flags;
0068
0069 #if SSB_VERBOSE_PCICORESWITCH_DEBUG
0070 pr_info("Switching to %s core, index %d\n",
0071 ssb_core_name(dev->id.coreid), dev->core_index);
0072 #endif
0073
0074 spin_lock_irqsave(&bus->bar_lock, flags);
0075 err = ssb_pci_switch_coreidx(bus, dev->core_index);
0076 if (!err)
0077 bus->mapped_device = dev;
0078 spin_unlock_irqrestore(&bus->bar_lock, flags);
0079
0080 return err;
0081 }
0082
0083
0084 int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
0085 {
0086 int err;
0087 u32 in, out, outenable;
0088 u16 pci_status;
0089
0090 if (bus->bustype != SSB_BUSTYPE_PCI)
0091 return 0;
0092
0093 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_IN, &in);
0094 if (err)
0095 goto err_pci;
0096 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT, &out);
0097 if (err)
0098 goto err_pci;
0099 err = pci_read_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, &outenable);
0100 if (err)
0101 goto err_pci;
0102
0103 outenable |= what;
0104
0105 if (turn_on) {
0106
0107
0108
0109
0110 if (!(in & SSB_GPIO_XTAL)) {
0111 if (what & SSB_GPIO_XTAL) {
0112
0113 out |= SSB_GPIO_XTAL;
0114 if (what & SSB_GPIO_PLL)
0115 out |= SSB_GPIO_PLL;
0116 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
0117 if (err)
0118 goto err_pci;
0119 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE,
0120 outenable);
0121 if (err)
0122 goto err_pci;
0123 msleep(1);
0124 }
0125 if (what & SSB_GPIO_PLL) {
0126
0127 out &= ~SSB_GPIO_PLL;
0128 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
0129 if (err)
0130 goto err_pci;
0131 msleep(5);
0132 }
0133 }
0134
0135 err = pci_read_config_word(bus->host_pci, PCI_STATUS, &pci_status);
0136 if (err)
0137 goto err_pci;
0138 pci_status &= ~PCI_STATUS_SIG_TARGET_ABORT;
0139 err = pci_write_config_word(bus->host_pci, PCI_STATUS, pci_status);
0140 if (err)
0141 goto err_pci;
0142 } else {
0143 if (what & SSB_GPIO_XTAL) {
0144
0145 out &= ~SSB_GPIO_XTAL;
0146 }
0147 if (what & SSB_GPIO_PLL) {
0148
0149 out |= SSB_GPIO_PLL;
0150 }
0151 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT, out);
0152 if (err)
0153 goto err_pci;
0154 err = pci_write_config_dword(bus->host_pci, SSB_GPIO_OUT_ENABLE, outenable);
0155 if (err)
0156 goto err_pci;
0157 }
0158
0159 out:
0160 return err;
0161
0162 err_pci:
0163 pr_err("Error: ssb_pci_xtal() could not access PCI config space!\n");
0164 err = -EBUSY;
0165 goto out;
0166 }
0167
0168
0169 #define SPOFF(offset) ((offset) / sizeof(u16))
0170
0171 #define SPEX16(_outvar, _offset, _mask, _shift) \
0172 out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
0173 #define SPEX32(_outvar, _offset, _mask, _shift) \
0174 out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
0175 in[SPOFF(_offset)]) & (_mask)) >> (_shift))
0176 #define SPEX(_outvar, _offset, _mask, _shift) \
0177 SPEX16(_outvar, _offset, _mask, _shift)
0178
0179 #define SPEX_ARRAY8(_field, _offset, _mask, _shift) \
0180 do { \
0181 SPEX(_field[0], _offset + 0, _mask, _shift); \
0182 SPEX(_field[1], _offset + 2, _mask, _shift); \
0183 SPEX(_field[2], _offset + 4, _mask, _shift); \
0184 SPEX(_field[3], _offset + 6, _mask, _shift); \
0185 SPEX(_field[4], _offset + 8, _mask, _shift); \
0186 SPEX(_field[5], _offset + 10, _mask, _shift); \
0187 SPEX(_field[6], _offset + 12, _mask, _shift); \
0188 SPEX(_field[7], _offset + 14, _mask, _shift); \
0189 } while (0)
0190
0191
0192 static inline u8 ssb_crc8(u8 crc, u8 data)
0193 {
0194
0195 static const u8 t[] = {
0196 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
0197 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
0198 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
0199 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
0200 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
0201 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
0202 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
0203 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
0204 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
0205 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
0206 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
0207 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
0208 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
0209 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
0210 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
0211 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
0212 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
0213 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
0214 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
0215 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
0216 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
0217 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
0218 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
0219 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
0220 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
0221 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
0222 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
0223 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
0224 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
0225 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
0226 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
0227 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
0228 };
0229 return t[crc ^ data];
0230 }
0231
0232 static void sprom_get_mac(char *mac, const u16 *in)
0233 {
0234 int i;
0235 for (i = 0; i < 3; i++) {
0236 *mac++ = in[i] >> 8;
0237 *mac++ = in[i];
0238 }
0239 }
0240
0241 static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
0242 {
0243 int word;
0244 u8 crc = 0xFF;
0245
0246 for (word = 0; word < size - 1; word++) {
0247 crc = ssb_crc8(crc, sprom[word] & 0x00FF);
0248 crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8);
0249 }
0250 crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF);
0251 crc ^= 0xFF;
0252
0253 return crc;
0254 }
0255
0256 static int sprom_check_crc(const u16 *sprom, size_t size)
0257 {
0258 u8 crc;
0259 u8 expected_crc;
0260 u16 tmp;
0261
0262 crc = ssb_sprom_crc(sprom, size);
0263 tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC;
0264 expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
0265 if (crc != expected_crc)
0266 return -EPROTO;
0267
0268 return 0;
0269 }
0270
0271 static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
0272 {
0273 int i;
0274
0275 for (i = 0; i < bus->sprom_size; i++)
0276 sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
0277
0278 return 0;
0279 }
0280
0281 static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
0282 {
0283 struct pci_dev *pdev = bus->host_pci;
0284 int i, err;
0285 u32 spromctl;
0286 u16 size = bus->sprom_size;
0287
0288 pr_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
0289 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
0290 if (err)
0291 goto err_ctlreg;
0292 spromctl |= SSB_SPROMCTL_WE;
0293 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
0294 if (err)
0295 goto err_ctlreg;
0296 pr_notice("[ 0%%");
0297 msleep(500);
0298 for (i = 0; i < size; i++) {
0299 if (i == size / 4)
0300 pr_cont("25%%");
0301 else if (i == size / 2)
0302 pr_cont("50%%");
0303 else if (i == (size * 3) / 4)
0304 pr_cont("75%%");
0305 else if (i % 2)
0306 pr_cont(".");
0307 writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
0308 msleep(20);
0309 }
0310 err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
0311 if (err)
0312 goto err_ctlreg;
0313 spromctl &= ~SSB_SPROMCTL_WE;
0314 err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
0315 if (err)
0316 goto err_ctlreg;
0317 msleep(500);
0318 pr_cont("100%% ]\n");
0319 pr_notice("SPROM written\n");
0320
0321 return 0;
0322 err_ctlreg:
0323 pr_err("Could not access SPROM control register.\n");
0324 return err;
0325 }
0326
0327 static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset,
0328 u16 mask, u16 shift)
0329 {
0330 u16 v;
0331 u8 gain;
0332
0333 v = in[SPOFF(offset)];
0334 gain = (v & mask) >> shift;
0335 if (gain == 0xFF)
0336 gain = 2;
0337 if (sprom_revision == 1) {
0338
0339 gain <<= 2;
0340 } else {
0341
0342 gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
0343 }
0344
0345 return (s8)gain;
0346 }
0347
0348 static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in)
0349 {
0350 SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
0351 SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
0352 SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0);
0353 SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0);
0354 SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0);
0355 SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0);
0356 SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0);
0357 SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0);
0358 SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0);
0359 SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO,
0360 SSB_SPROM2_MAXP_A_LO_SHIFT);
0361 }
0362
0363 static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
0364 {
0365 u16 loc[3];
0366
0367 if (out->revision == 3)
0368 loc[0] = SSB_SPROM3_IL0MAC;
0369 else {
0370 loc[0] = SSB_SPROM1_IL0MAC;
0371 loc[1] = SSB_SPROM1_ET0MAC;
0372 loc[2] = SSB_SPROM1_ET1MAC;
0373 }
0374 sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
0375 if (out->revision < 3) {
0376 sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
0377 sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
0378 }
0379 SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
0380 SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
0381 SSB_SPROM1_ETHPHY_ET1A_SHIFT);
0382 SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
0383 SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
0384 SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
0385 SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
0386 if (out->revision == 1)
0387 SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
0388 SSB_SPROM1_BINF_CCODE_SHIFT);
0389 SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
0390 SSB_SPROM1_BINF_ANTA_SHIFT);
0391 SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
0392 SSB_SPROM1_BINF_ANTBG_SHIFT);
0393 SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0);
0394 SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0);
0395 SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0);
0396 SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0);
0397 SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0);
0398 SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0);
0399 SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0);
0400 SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1,
0401 SSB_SPROM1_GPIOA_P1_SHIFT);
0402 SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0);
0403 SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3,
0404 SSB_SPROM1_GPIOB_P3_SHIFT);
0405 SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A,
0406 SSB_SPROM1_MAXPWR_A_SHIFT);
0407 SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0);
0408 SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A,
0409 SSB_SPROM1_ITSSI_A_SHIFT);
0410 SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0);
0411 SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
0412
0413 SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
0414 SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
0415
0416
0417 out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
0418 SSB_SPROM1_AGAIN,
0419 SSB_SPROM1_AGAIN_BG,
0420 SSB_SPROM1_AGAIN_BG_SHIFT);
0421 out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
0422 SSB_SPROM1_AGAIN,
0423 SSB_SPROM1_AGAIN_A,
0424 SSB_SPROM1_AGAIN_A_SHIFT);
0425 if (out->revision >= 2)
0426 sprom_extract_r23(out, in);
0427 }
0428
0429
0430 static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
0431 {
0432 SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
0433 SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
0434 SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
0435 SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
0436 SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
0437 SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
0438 SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
0439 SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
0440
0441 SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
0442 SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
0443 SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
0444 SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
0445 SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
0446 SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
0447 SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
0448 SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
0449
0450 SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
0451 SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
0452 SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
0453 SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
0454 SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
0455 SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
0456 SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
0457 SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
0458
0459 SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
0460 SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
0461 SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
0462 SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
0463 SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
0464 SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
0465 SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
0466 SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
0467 }
0468
0469 static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
0470 {
0471 static const u16 pwr_info_offset[] = {
0472 SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1,
0473 SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3
0474 };
0475 u16 il0mac_offset;
0476 int i;
0477
0478 BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
0479 ARRAY_SIZE(out->core_pwr_info));
0480
0481 if (out->revision == 4)
0482 il0mac_offset = SSB_SPROM4_IL0MAC;
0483 else
0484 il0mac_offset = SSB_SPROM5_IL0MAC;
0485
0486 sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
0487
0488 SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
0489 SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
0490 SSB_SPROM4_ETHPHY_ET1A_SHIFT);
0491 SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
0492 SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
0493 if (out->revision == 4) {
0494 SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
0495 SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
0496 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
0497 SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
0498 SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
0499 SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
0500 } else {
0501 SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
0502 SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
0503 SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
0504 SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
0505 SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
0506 SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
0507 }
0508 SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
0509 SSB_SPROM4_ANTAVAIL_A_SHIFT);
0510 SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG,
0511 SSB_SPROM4_ANTAVAIL_BG_SHIFT);
0512 SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0);
0513 SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG,
0514 SSB_SPROM4_ITSSI_BG_SHIFT);
0515 SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0);
0516 SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A,
0517 SSB_SPROM4_ITSSI_A_SHIFT);
0518 if (out->revision == 4) {
0519 SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0);
0520 SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1,
0521 SSB_SPROM4_GPIOA_P1_SHIFT);
0522 SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0);
0523 SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3,
0524 SSB_SPROM4_GPIOB_P3_SHIFT);
0525 } else {
0526 SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0);
0527 SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1,
0528 SSB_SPROM5_GPIOA_P1_SHIFT);
0529 SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0);
0530 SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3,
0531 SSB_SPROM5_GPIOB_P3_SHIFT);
0532 }
0533
0534
0535 out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
0536 SSB_SPROM4_AGAIN01,
0537 SSB_SPROM4_AGAIN0,
0538 SSB_SPROM4_AGAIN0_SHIFT);
0539 out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
0540 SSB_SPROM4_AGAIN01,
0541 SSB_SPROM4_AGAIN1,
0542 SSB_SPROM4_AGAIN1_SHIFT);
0543 out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
0544 SSB_SPROM4_AGAIN23,
0545 SSB_SPROM4_AGAIN2,
0546 SSB_SPROM4_AGAIN2_SHIFT);
0547 out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
0548 SSB_SPROM4_AGAIN23,
0549 SSB_SPROM4_AGAIN3,
0550 SSB_SPROM4_AGAIN3_SHIFT);
0551
0552
0553 for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
0554 u16 o = pwr_info_offset[i];
0555
0556 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
0557 SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT);
0558 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
0559 SSB_SPROM4_2G_MAXP, 0);
0560
0561 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0);
0562 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0);
0563 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0);
0564 SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0);
0565
0566 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
0567 SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT);
0568 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
0569 SSB_SPROM4_5G_MAXP, 0);
0570 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP,
0571 SSB_SPROM4_5GH_MAXP, 0);
0572 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP,
0573 SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT);
0574
0575 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0);
0576 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0);
0577 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0);
0578 SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0);
0579 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0);
0580 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0);
0581 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0);
0582 SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0);
0583 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0);
0584 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0);
0585 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0);
0586 SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0);
0587 }
0588
0589 sprom_extract_r458(out, in);
0590
0591
0592 }
0593
0594 static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
0595 {
0596 int i;
0597 u16 o;
0598 static const u16 pwr_info_offset[] = {
0599 SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
0600 SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
0601 };
0602 BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
0603 ARRAY_SIZE(out->core_pwr_info));
0604
0605
0606 sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
0607
0608 SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
0609 SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0);
0610 SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
0611 SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
0612 SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
0613 SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
0614 SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
0615 SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
0616 SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
0617 SSB_SPROM8_ANTAVAIL_A_SHIFT);
0618 SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
0619 SSB_SPROM8_ANTAVAIL_BG_SHIFT);
0620 SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
0621 SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
0622 SSB_SPROM8_ITSSI_BG_SHIFT);
0623 SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
0624 SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
0625 SSB_SPROM8_ITSSI_A_SHIFT);
0626 SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
0627 SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
0628 SSB_SPROM8_MAXP_AL_SHIFT);
0629 SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
0630 SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
0631 SSB_SPROM8_GPIOA_P1_SHIFT);
0632 SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
0633 SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
0634 SSB_SPROM8_GPIOB_P3_SHIFT);
0635 SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
0636 SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
0637 SSB_SPROM8_TRI5G_SHIFT);
0638 SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
0639 SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
0640 SSB_SPROM8_TRI5GH_SHIFT);
0641 SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
0642 SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
0643 SSB_SPROM8_RXPO5G_SHIFT);
0644 SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
0645 SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
0646 SSB_SPROM8_RSSISMC2G_SHIFT);
0647 SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
0648 SSB_SPROM8_RSSISAV2G_SHIFT);
0649 SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
0650 SSB_SPROM8_BXA2G_SHIFT);
0651 SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
0652 SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
0653 SSB_SPROM8_RSSISMC5G_SHIFT);
0654 SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
0655 SSB_SPROM8_RSSISAV5G_SHIFT);
0656 SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
0657 SSB_SPROM8_BXA5G_SHIFT);
0658 SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
0659 SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
0660 SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
0661 SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
0662 SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
0663 SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
0664 SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
0665 SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
0666 SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
0667 SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
0668 SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
0669 SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
0670 SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
0671 SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
0672 SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
0673 SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
0674 SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
0675
0676
0677 out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
0678 SSB_SPROM8_AGAIN01,
0679 SSB_SPROM8_AGAIN0,
0680 SSB_SPROM8_AGAIN0_SHIFT);
0681 out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
0682 SSB_SPROM8_AGAIN01,
0683 SSB_SPROM8_AGAIN1,
0684 SSB_SPROM8_AGAIN1_SHIFT);
0685 out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
0686 SSB_SPROM8_AGAIN23,
0687 SSB_SPROM8_AGAIN2,
0688 SSB_SPROM8_AGAIN2_SHIFT);
0689 out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
0690 SSB_SPROM8_AGAIN23,
0691 SSB_SPROM8_AGAIN3,
0692 SSB_SPROM8_AGAIN3_SHIFT);
0693
0694
0695 for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
0696 o = pwr_info_offset[i];
0697 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
0698 SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
0699 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
0700 SSB_SPROM8_2G_MAXP, 0);
0701
0702 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
0703 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
0704 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
0705
0706 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
0707 SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
0708 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
0709 SSB_SPROM8_5G_MAXP, 0);
0710 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
0711 SSB_SPROM8_5GH_MAXP, 0);
0712 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
0713 SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
0714
0715 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
0716 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
0717 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
0718 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
0719 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
0720 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
0721 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
0722 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
0723 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
0724 }
0725
0726
0727 SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
0728 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
0729 SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
0730 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
0731 SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
0732 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
0733 SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
0734 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
0735 SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
0736 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
0737
0738 SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
0739 SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
0740 SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
0741 SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
0742 SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
0743 SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
0744 SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
0745 SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
0746 SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
0747 SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
0748
0749 SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
0750 SSB_SPROM8_LEDDC_ON_SHIFT);
0751 SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
0752 SSB_SPROM8_LEDDC_OFF_SHIFT);
0753
0754 SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
0755 SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
0756 SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
0757 SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
0758 SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
0759 SSB_SPROM8_TXRXC_SWITCH_SHIFT);
0760
0761 SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
0762
0763 SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
0764 SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
0765 SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
0766 SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
0767
0768 SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
0769 SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
0770 SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
0771 SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
0772 SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
0773 SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
0774 SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
0775 SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
0776 SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
0777 SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
0778 SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
0779 SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
0780 SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
0781 SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
0782 SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
0783 SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
0784 SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
0785 SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
0786 SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
0787 SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
0788
0789 SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
0790 SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
0791 SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
0792 SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
0793
0794 SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
0795 SSB_SPROM8_THERMAL_TRESH_SHIFT);
0796 SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
0797 SSB_SPROM8_THERMAL_OFFSET_SHIFT);
0798 SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
0799 SSB_SPROM8_TEMPDELTA_PHYCAL,
0800 SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
0801 SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
0802 SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
0803 SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
0804 SSB_SPROM8_TEMPDELTA_HYSTERESIS,
0805 SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
0806 sprom_extract_r458(out, in);
0807
0808
0809 }
0810
0811 static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
0812 const u16 *in, u16 size)
0813 {
0814 memset(out, 0, sizeof(*out));
0815
0816 out->revision = in[size - 1] & 0x00FF;
0817 pr_debug("SPROM revision %d detected\n", out->revision);
0818 memset(out->et0mac, 0xFF, 6);
0819 memset(out->et1mac, 0xFF, 6);
0820
0821 if ((bus->chip_id & 0xFF00) == 0x4400) {
0822
0823
0824
0825 out->revision = 1;
0826 pr_debug("SPROM treated as revision %d\n", out->revision);
0827 }
0828
0829 switch (out->revision) {
0830 case 1:
0831 case 2:
0832 case 3:
0833 sprom_extract_r123(out, in);
0834 break;
0835 case 4:
0836 case 5:
0837 sprom_extract_r45(out, in);
0838 break;
0839 case 8:
0840 sprom_extract_r8(out, in);
0841 break;
0842 default:
0843 pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
0844 out->revision);
0845 out->revision = 1;
0846 sprom_extract_r123(out, in);
0847 }
0848
0849 if (out->boardflags_lo == 0xFFFF)
0850 out->boardflags_lo = 0;
0851 if (out->boardflags_hi == 0xFFFF)
0852 out->boardflags_hi = 0;
0853
0854 return 0;
0855 }
0856
0857 static int ssb_pci_sprom_get(struct ssb_bus *bus,
0858 struct ssb_sprom *sprom)
0859 {
0860 int err;
0861 u16 *buf;
0862
0863 if (!ssb_is_sprom_available(bus)) {
0864 pr_err("No SPROM available!\n");
0865 return -ENODEV;
0866 }
0867 if (bus->chipco.dev) {
0868
0869
0870
0871
0872
0873 if (bus->chipco.dev->id.revision >= 31)
0874 bus->sprom_offset = SSB_SPROM_BASE31;
0875 else if (bus->chip_id == 0x4312 &&
0876 (bus->chipco.status & 0x03) == 2)
0877 bus->sprom_offset = SSB_SPROM_BASE31;
0878 else
0879 bus->sprom_offset = SSB_SPROM_BASE1;
0880 } else {
0881 bus->sprom_offset = SSB_SPROM_BASE1;
0882 }
0883 pr_debug("SPROM offset is 0x%x\n", bus->sprom_offset);
0884
0885 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
0886 if (!buf)
0887 return -ENOMEM;
0888 bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
0889 sprom_do_read(bus, buf);
0890 err = sprom_check_crc(buf, bus->sprom_size);
0891 if (err) {
0892
0893 kfree(buf);
0894 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
0895 GFP_KERNEL);
0896 if (!buf)
0897 return -ENOMEM;
0898 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
0899 sprom_do_read(bus, buf);
0900 err = sprom_check_crc(buf, bus->sprom_size);
0901 if (err) {
0902
0903
0904
0905
0906 err = ssb_fill_sprom_with_fallback(bus, sprom);
0907 if (err) {
0908 pr_warn("WARNING: Using fallback SPROM failed (err %d)\n",
0909 err);
0910 goto out_free;
0911 } else {
0912 pr_debug("Using SPROM revision %d provided by platform\n",
0913 sprom->revision);
0914 err = 0;
0915 goto out_free;
0916 }
0917 }
0918 }
0919 err = sprom_extract(bus, sprom, buf, bus->sprom_size);
0920
0921 out_free:
0922 kfree(buf);
0923 return err;
0924 }
0925
0926 static void ssb_pci_get_boardinfo(struct ssb_bus *bus,
0927 struct ssb_boardinfo *bi)
0928 {
0929 bi->vendor = bus->host_pci->subsystem_vendor;
0930 bi->type = bus->host_pci->subsystem_device;
0931 }
0932
0933 int ssb_pci_get_invariants(struct ssb_bus *bus,
0934 struct ssb_init_invariants *iv)
0935 {
0936 int err;
0937
0938 err = ssb_pci_sprom_get(bus, &iv->sprom);
0939 if (err)
0940 goto out;
0941 ssb_pci_get_boardinfo(bus, &iv->boardinfo);
0942
0943 out:
0944 return err;
0945 }
0946
0947 static int ssb_pci_assert_buspower(struct ssb_bus *bus)
0948 {
0949 if (likely(bus->powered_up))
0950 return 0;
0951
0952 pr_err("FATAL ERROR: Bus powered down while accessing PCI MMIO space\n");
0953 if (bus->power_warn_count <= 10) {
0954 bus->power_warn_count++;
0955 dump_stack();
0956 }
0957
0958 return -ENODEV;
0959 }
0960
0961 static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
0962 {
0963 struct ssb_bus *bus = dev->bus;
0964
0965 if (unlikely(ssb_pci_assert_buspower(bus)))
0966 return 0xFF;
0967 if (unlikely(bus->mapped_device != dev)) {
0968 if (unlikely(ssb_pci_switch_core(bus, dev)))
0969 return 0xFF;
0970 }
0971 return ioread8(bus->mmio + offset);
0972 }
0973
0974 static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
0975 {
0976 struct ssb_bus *bus = dev->bus;
0977
0978 if (unlikely(ssb_pci_assert_buspower(bus)))
0979 return 0xFFFF;
0980 if (unlikely(bus->mapped_device != dev)) {
0981 if (unlikely(ssb_pci_switch_core(bus, dev)))
0982 return 0xFFFF;
0983 }
0984 return ioread16(bus->mmio + offset);
0985 }
0986
0987 static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
0988 {
0989 struct ssb_bus *bus = dev->bus;
0990
0991 if (unlikely(ssb_pci_assert_buspower(bus)))
0992 return 0xFFFFFFFF;
0993 if (unlikely(bus->mapped_device != dev)) {
0994 if (unlikely(ssb_pci_switch_core(bus, dev)))
0995 return 0xFFFFFFFF;
0996 }
0997 return ioread32(bus->mmio + offset);
0998 }
0999
1000 #ifdef CONFIG_SSB_BLOCKIO
1001 static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
1002 size_t count, u16 offset, u8 reg_width)
1003 {
1004 struct ssb_bus *bus = dev->bus;
1005 void __iomem *addr = bus->mmio + offset;
1006
1007 if (unlikely(ssb_pci_assert_buspower(bus)))
1008 goto error;
1009 if (unlikely(bus->mapped_device != dev)) {
1010 if (unlikely(ssb_pci_switch_core(bus, dev)))
1011 goto error;
1012 }
1013 switch (reg_width) {
1014 case sizeof(u8):
1015 ioread8_rep(addr, buffer, count);
1016 break;
1017 case sizeof(u16):
1018 WARN_ON(count & 1);
1019 ioread16_rep(addr, buffer, count >> 1);
1020 break;
1021 case sizeof(u32):
1022 WARN_ON(count & 3);
1023 ioread32_rep(addr, buffer, count >> 2);
1024 break;
1025 default:
1026 WARN_ON(1);
1027 }
1028
1029 return;
1030 error:
1031 memset(buffer, 0xFF, count);
1032 }
1033 #endif
1034
1035 static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
1036 {
1037 struct ssb_bus *bus = dev->bus;
1038
1039 if (unlikely(ssb_pci_assert_buspower(bus)))
1040 return;
1041 if (unlikely(bus->mapped_device != dev)) {
1042 if (unlikely(ssb_pci_switch_core(bus, dev)))
1043 return;
1044 }
1045 iowrite8(value, bus->mmio + offset);
1046 }
1047
1048 static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
1049 {
1050 struct ssb_bus *bus = dev->bus;
1051
1052 if (unlikely(ssb_pci_assert_buspower(bus)))
1053 return;
1054 if (unlikely(bus->mapped_device != dev)) {
1055 if (unlikely(ssb_pci_switch_core(bus, dev)))
1056 return;
1057 }
1058 iowrite16(value, bus->mmio + offset);
1059 }
1060
1061 static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
1062 {
1063 struct ssb_bus *bus = dev->bus;
1064
1065 if (unlikely(ssb_pci_assert_buspower(bus)))
1066 return;
1067 if (unlikely(bus->mapped_device != dev)) {
1068 if (unlikely(ssb_pci_switch_core(bus, dev)))
1069 return;
1070 }
1071 iowrite32(value, bus->mmio + offset);
1072 }
1073
1074 #ifdef CONFIG_SSB_BLOCKIO
1075 static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
1076 size_t count, u16 offset, u8 reg_width)
1077 {
1078 struct ssb_bus *bus = dev->bus;
1079 void __iomem *addr = bus->mmio + offset;
1080
1081 if (unlikely(ssb_pci_assert_buspower(bus)))
1082 return;
1083 if (unlikely(bus->mapped_device != dev)) {
1084 if (unlikely(ssb_pci_switch_core(bus, dev)))
1085 return;
1086 }
1087 switch (reg_width) {
1088 case sizeof(u8):
1089 iowrite8_rep(addr, buffer, count);
1090 break;
1091 case sizeof(u16):
1092 WARN_ON(count & 1);
1093 iowrite16_rep(addr, buffer, count >> 1);
1094 break;
1095 case sizeof(u32):
1096 WARN_ON(count & 3);
1097 iowrite32_rep(addr, buffer, count >> 2);
1098 break;
1099 default:
1100 WARN_ON(1);
1101 }
1102 }
1103 #endif
1104
1105
1106 const struct ssb_bus_ops ssb_pci_ops = {
1107 .read8 = ssb_pci_read8,
1108 .read16 = ssb_pci_read16,
1109 .read32 = ssb_pci_read32,
1110 .write8 = ssb_pci_write8,
1111 .write16 = ssb_pci_write16,
1112 .write32 = ssb_pci_write32,
1113 #ifdef CONFIG_SSB_BLOCKIO
1114 .block_read = ssb_pci_block_read,
1115 .block_write = ssb_pci_block_write,
1116 #endif
1117 };
1118
1119 static ssize_t ssb_sprom_show(struct device *pcidev,
1120 struct device_attribute *attr,
1121 char *buf)
1122 {
1123 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1124 struct ssb_bus *bus;
1125
1126 bus = ssb_pci_dev_to_bus(pdev);
1127 if (!bus)
1128 return -ENODEV;
1129
1130 return ssb_attr_sprom_show(bus, buf, sprom_do_read);
1131 }
1132
1133 static ssize_t ssb_sprom_store(struct device *pcidev,
1134 struct device_attribute *attr,
1135 const char *buf, size_t count)
1136 {
1137 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
1138 struct ssb_bus *bus;
1139
1140 bus = ssb_pci_dev_to_bus(pdev);
1141 if (!bus)
1142 return -ENODEV;
1143
1144 return ssb_attr_sprom_store(bus, buf, count,
1145 sprom_check_crc, sprom_do_write);
1146 }
1147
1148 static DEVICE_ATTR_ADMIN_RW(ssb_sprom);
1149
1150 void ssb_pci_exit(struct ssb_bus *bus)
1151 {
1152 struct pci_dev *pdev;
1153
1154 if (bus->bustype != SSB_BUSTYPE_PCI)
1155 return;
1156
1157 pdev = bus->host_pci;
1158 device_remove_file(&pdev->dev, &dev_attr_ssb_sprom);
1159 }
1160
1161 int ssb_pci_init(struct ssb_bus *bus)
1162 {
1163 struct pci_dev *pdev;
1164
1165 if (bus->bustype != SSB_BUSTYPE_PCI)
1166 return 0;
1167
1168 pdev = bus->host_pci;
1169 mutex_init(&bus->sprom_mutex);
1170
1171 return device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
1172 }