0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "bcma_private.h"
0011
0012 #include <linux/bcma/bcma.h>
0013 #include <linux/bcma/bcma_regs.h>
0014 #include <linux/pci.h>
0015 #include <linux/io.h>
0016 #include <linux/dma-mapping.h>
0017 #include <linux/slab.h>
0018
0019 static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus,
0040 struct ssb_sprom *out))
0041 {
0042 if (get_fallback_sprom)
0043 return -EEXIST;
0044 get_fallback_sprom = sprom_callback;
0045
0046 return 0;
0047 }
0048
0049 static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
0050 struct ssb_sprom *out)
0051 {
0052 int err;
0053
0054 if (!get_fallback_sprom) {
0055 err = -ENOENT;
0056 goto fail;
0057 }
0058
0059 err = get_fallback_sprom(bus, out);
0060 if (err)
0061 goto fail;
0062
0063 bcma_debug(bus, "Using SPROM revision %d provided by platform.\n",
0064 bus->sprom.revision);
0065 return 0;
0066 fail:
0067 bcma_warn(bus, "Using fallback SPROM failed (err %d)\n", err);
0068 return err;
0069 }
0070
0071
0072
0073
0074
0075 static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom,
0076 size_t words)
0077 {
0078 int i;
0079 for (i = 0; i < words; i++)
0080 sprom[i] = bcma_read16(bus->drv_cc.core, offset + (i * 2));
0081 }
0082
0083
0084
0085
0086
0087 static inline u8 bcma_crc8(u8 crc, u8 data)
0088 {
0089
0090 static const u8 t[] = {
0091 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
0092 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
0093 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
0094 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
0095 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
0096 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
0097 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
0098 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
0099 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
0100 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
0101 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
0102 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
0103 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
0104 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
0105 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
0106 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
0107 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
0108 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
0109 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
0110 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
0111 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
0112 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
0113 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
0114 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
0115 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
0116 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
0117 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
0118 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
0119 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
0120 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
0121 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
0122 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
0123 };
0124 return t[crc ^ data];
0125 }
0126
0127 static u8 bcma_sprom_crc(const u16 *sprom, size_t words)
0128 {
0129 int word;
0130 u8 crc = 0xFF;
0131
0132 for (word = 0; word < words - 1; word++) {
0133 crc = bcma_crc8(crc, sprom[word] & 0x00FF);
0134 crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8);
0135 }
0136 crc = bcma_crc8(crc, sprom[words - 1] & 0x00FF);
0137 crc ^= 0xFF;
0138
0139 return crc;
0140 }
0141
0142 static int bcma_sprom_check_crc(const u16 *sprom, size_t words)
0143 {
0144 u8 crc;
0145 u8 expected_crc;
0146 u16 tmp;
0147
0148 crc = bcma_sprom_crc(sprom, words);
0149 tmp = sprom[words - 1] & SSB_SPROM_REVISION_CRC;
0150 expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
0151 if (crc != expected_crc)
0152 return -EPROTO;
0153
0154 return 0;
0155 }
0156
0157 static int bcma_sprom_valid(struct bcma_bus *bus, const u16 *sprom,
0158 size_t words)
0159 {
0160 u16 revision;
0161 int err;
0162
0163 err = bcma_sprom_check_crc(sprom, words);
0164 if (err)
0165 return err;
0166
0167 revision = sprom[words - 1] & SSB_SPROM_REVISION_REV;
0168 if (revision != 8 && revision != 9 && revision != 10) {
0169 pr_err("Unsupported SPROM revision: %d\n", revision);
0170 return -ENOENT;
0171 }
0172
0173 bus->sprom.revision = revision;
0174 bcma_debug(bus, "Found SPROM revision %d\n", revision);
0175
0176 return 0;
0177 }
0178
0179
0180
0181
0182
0183 #define SPOFF(offset) ((offset) / sizeof(u16))
0184
0185 #define SPEX(_field, _offset, _mask, _shift) \
0186 bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift))
0187
0188 #define SPEX32(_field, _offset, _mask, _shift) \
0189 bus->sprom._field = ((((u32)sprom[SPOFF((_offset)+2)] << 16 | \
0190 sprom[SPOFF(_offset)]) & (_mask)) >> (_shift))
0191
0192 #define SPEX_ARRAY8(_field, _offset, _mask, _shift) \
0193 do { \
0194 SPEX(_field[0], _offset + 0, _mask, _shift); \
0195 SPEX(_field[1], _offset + 2, _mask, _shift); \
0196 SPEX(_field[2], _offset + 4, _mask, _shift); \
0197 SPEX(_field[3], _offset + 6, _mask, _shift); \
0198 SPEX(_field[4], _offset + 8, _mask, _shift); \
0199 SPEX(_field[5], _offset + 10, _mask, _shift); \
0200 SPEX(_field[6], _offset + 12, _mask, _shift); \
0201 SPEX(_field[7], _offset + 14, _mask, _shift); \
0202 } while (0)
0203
0204 static s8 sprom_extract_antgain(const u16 *in, u16 offset, u16 mask, u16 shift)
0205 {
0206 u16 v;
0207 u8 gain;
0208
0209 v = in[SPOFF(offset)];
0210 gain = (v & mask) >> shift;
0211 if (gain == 0xFF) {
0212 gain = 8;
0213 } else {
0214
0215 gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
0216 }
0217
0218 return (s8)gain;
0219 }
0220
0221 static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
0222 {
0223 u16 v, o;
0224 int i;
0225 static const u16 pwr_info_offset[] = {
0226 SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
0227 SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
0228 };
0229 BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
0230 ARRAY_SIZE(bus->sprom.core_pwr_info));
0231
0232 for (i = 0; i < 3; i++) {
0233 v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
0234 *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
0235 }
0236
0237 SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0);
0238 SPEX(board_type, SSB_SPROM1_SPID, ~0, 0);
0239
0240 SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
0241 SSB_SPROM4_TXPID2G0_SHIFT);
0242 SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G1,
0243 SSB_SPROM4_TXPID2G1_SHIFT);
0244 SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G2,
0245 SSB_SPROM4_TXPID2G2_SHIFT);
0246 SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G3,
0247 SSB_SPROM4_TXPID2G3_SHIFT);
0248
0249 SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL0,
0250 SSB_SPROM4_TXPID5GL0_SHIFT);
0251 SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL1,
0252 SSB_SPROM4_TXPID5GL1_SHIFT);
0253 SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL2,
0254 SSB_SPROM4_TXPID5GL2_SHIFT);
0255 SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL3,
0256 SSB_SPROM4_TXPID5GL3_SHIFT);
0257
0258 SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G0,
0259 SSB_SPROM4_TXPID5G0_SHIFT);
0260 SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G1,
0261 SSB_SPROM4_TXPID5G1_SHIFT);
0262 SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G2,
0263 SSB_SPROM4_TXPID5G2_SHIFT);
0264 SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G3,
0265 SSB_SPROM4_TXPID5G3_SHIFT);
0266
0267 SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH0,
0268 SSB_SPROM4_TXPID5GH0_SHIFT);
0269 SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH1,
0270 SSB_SPROM4_TXPID5GH1_SHIFT);
0271 SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH2,
0272 SSB_SPROM4_TXPID5GH2_SHIFT);
0273 SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH3,
0274 SSB_SPROM4_TXPID5GH3_SHIFT);
0275
0276 SPEX(boardflags_lo, SSB_SPROM8_BFLLO, ~0, 0);
0277 SPEX(boardflags_hi, SSB_SPROM8_BFLHI, ~0, 0);
0278 SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0);
0279 SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0);
0280
0281 SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
0282 SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
0283
0284
0285 for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
0286 o = pwr_info_offset[i];
0287 SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
0288 SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
0289 SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
0290 SSB_SPROM8_2G_MAXP, 0);
0291
0292 SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
0293 SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
0294 SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
0295
0296 SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
0297 SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
0298 SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
0299 SSB_SPROM8_5G_MAXP, 0);
0300 SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
0301 SSB_SPROM8_5GH_MAXP, 0);
0302 SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
0303 SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
0304
0305 SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
0306 SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
0307 SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
0308 SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
0309 SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
0310 SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
0311 SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
0312 SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
0313 SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
0314 }
0315
0316 SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS,
0317 SSB_SROM8_FEM_TSSIPOS_SHIFT);
0318 SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN,
0319 SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
0320 SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_PDET_RANGE,
0321 SSB_SROM8_FEM_PDET_RANGE_SHIFT);
0322 SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TR_ISO,
0323 SSB_SROM8_FEM_TR_ISO_SHIFT);
0324 SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_ANTSWLUT,
0325 SSB_SROM8_FEM_ANTSWLUT_SHIFT);
0326
0327 SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TSSIPOS,
0328 SSB_SROM8_FEM_TSSIPOS_SHIFT);
0329 SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_EXTPA_GAIN,
0330 SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
0331 SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_PDET_RANGE,
0332 SSB_SROM8_FEM_PDET_RANGE_SHIFT);
0333 SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TR_ISO,
0334 SSB_SROM8_FEM_TR_ISO_SHIFT);
0335 SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
0336 SSB_SROM8_FEM_ANTSWLUT_SHIFT);
0337
0338 SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
0339 SSB_SPROM8_ANTAVAIL_A_SHIFT);
0340 SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
0341 SSB_SPROM8_ANTAVAIL_BG_SHIFT);
0342 SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
0343 SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
0344 SSB_SPROM8_ITSSI_BG_SHIFT);
0345 SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
0346 SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
0347 SSB_SPROM8_ITSSI_A_SHIFT);
0348 SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
0349 SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
0350 SSB_SPROM8_MAXP_AL_SHIFT);
0351 SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
0352 SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
0353 SSB_SPROM8_GPIOA_P1_SHIFT);
0354 SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
0355 SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
0356 SSB_SPROM8_GPIOB_P3_SHIFT);
0357 SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
0358 SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
0359 SSB_SPROM8_TRI5G_SHIFT);
0360 SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
0361 SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
0362 SSB_SPROM8_TRI5GH_SHIFT);
0363 SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G,
0364 SSB_SPROM8_RXPO2G_SHIFT);
0365 SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
0366 SSB_SPROM8_RXPO5G_SHIFT);
0367 SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
0368 SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
0369 SSB_SPROM8_RSSISMC2G_SHIFT);
0370 SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
0371 SSB_SPROM8_RSSISAV2G_SHIFT);
0372 SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
0373 SSB_SPROM8_BXA2G_SHIFT);
0374 SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
0375 SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
0376 SSB_SPROM8_RSSISMC5G_SHIFT);
0377 SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
0378 SSB_SPROM8_RSSISAV5G_SHIFT);
0379 SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
0380 SSB_SPROM8_BXA5G_SHIFT);
0381
0382 SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0);
0383 SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0);
0384 SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0);
0385 SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0);
0386 SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0);
0387 SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0);
0388 SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0);
0389 SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0);
0390 SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0);
0391 SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0);
0392 SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0);
0393 SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0);
0394 SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0);
0395 SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0);
0396 SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0);
0397 SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0);
0398 SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
0399
0400
0401 bus->sprom.antenna_gain.a0 = sprom_extract_antgain(sprom,
0402 SSB_SPROM8_AGAIN01,
0403 SSB_SPROM8_AGAIN0,
0404 SSB_SPROM8_AGAIN0_SHIFT);
0405 bus->sprom.antenna_gain.a1 = sprom_extract_antgain(sprom,
0406 SSB_SPROM8_AGAIN01,
0407 SSB_SPROM8_AGAIN1,
0408 SSB_SPROM8_AGAIN1_SHIFT);
0409 bus->sprom.antenna_gain.a2 = sprom_extract_antgain(sprom,
0410 SSB_SPROM8_AGAIN23,
0411 SSB_SPROM8_AGAIN2,
0412 SSB_SPROM8_AGAIN2_SHIFT);
0413 bus->sprom.antenna_gain.a3 = sprom_extract_antgain(sprom,
0414 SSB_SPROM8_AGAIN23,
0415 SSB_SPROM8_AGAIN3,
0416 SSB_SPROM8_AGAIN3_SHIFT);
0417
0418 SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
0419 SSB_SPROM8_LEDDC_ON_SHIFT);
0420 SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
0421 SSB_SPROM8_LEDDC_OFF_SHIFT);
0422
0423 SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
0424 SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
0425 SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
0426 SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
0427 SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
0428 SSB_SPROM8_TXRXC_SWITCH_SHIFT);
0429
0430 SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
0431
0432 SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
0433 SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
0434 SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
0435 SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
0436
0437 SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
0438 SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
0439 SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
0440 SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
0441 SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
0442 SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
0443 SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
0444 SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
0445 SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
0446 SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
0447 SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
0448 SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
0449 SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
0450 SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
0451 SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
0452 SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
0453 SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
0454 SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
0455 SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
0456 SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
0457
0458 SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
0459 SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
0460 SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
0461 SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
0462
0463 SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
0464 SSB_SPROM8_THERMAL_TRESH_SHIFT);
0465 SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
0466 SSB_SPROM8_THERMAL_OFFSET_SHIFT);
0467 SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
0468 SSB_SPROM8_TEMPDELTA_PHYCAL,
0469 SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
0470 SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
0471 SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
0472 SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
0473 SSB_SPROM8_TEMPDELTA_HYSTERESIS,
0474 SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
0475 }
0476
0477
0478
0479
0480 static bool bcma_sprom_ext_available(struct bcma_bus *bus)
0481 {
0482 u32 chip_status;
0483 u32 srom_control;
0484 u32 present_mask;
0485
0486 if (bus->drv_cc.core->id.rev >= 31) {
0487 if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
0488 return false;
0489
0490 srom_control = bcma_read32(bus->drv_cc.core,
0491 BCMA_CC_SROM_CONTROL);
0492 return srom_control & BCMA_CC_SROM_CONTROL_PRESENT;
0493 }
0494
0495
0496 chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
0497 switch (bus->chipinfo.id) {
0498 case BCMA_CHIP_ID_BCM4313:
0499 present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
0500 break;
0501
0502 case BCMA_CHIP_ID_BCM4331:
0503 present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
0504 break;
0505
0506 default:
0507 return true;
0508 }
0509
0510 return chip_status & present_mask;
0511 }
0512
0513
0514
0515
0516 static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
0517 {
0518 u32 chip_status;
0519 u32 otpsize = 0;
0520 bool present;
0521
0522 chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
0523 switch (bus->chipinfo.id) {
0524 case BCMA_CHIP_ID_BCM4313:
0525 present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
0526 break;
0527
0528 case BCMA_CHIP_ID_BCM4331:
0529 present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
0530 break;
0531 case BCMA_CHIP_ID_BCM43142:
0532 case BCMA_CHIP_ID_BCM43224:
0533 case BCMA_CHIP_ID_BCM43225:
0534
0535 present = true;
0536 break;
0537 case BCMA_CHIP_ID_BCM43131:
0538 case BCMA_CHIP_ID_BCM43217:
0539 case BCMA_CHIP_ID_BCM43227:
0540 case BCMA_CHIP_ID_BCM43228:
0541 case BCMA_CHIP_ID_BCM43428:
0542 present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT;
0543 break;
0544 default:
0545 present = false;
0546 break;
0547 }
0548
0549 if (present) {
0550 otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS;
0551 otpsize >>= BCMA_CC_CAP_OTPS_SHIFT;
0552 }
0553
0554 return otpsize != 0;
0555 }
0556
0557
0558
0559
0560
0561
0562
0563 static int bcma_sprom_onchip_offset(struct bcma_bus *bus)
0564 {
0565 struct bcma_device *cc = bus->drv_cc.core;
0566 u32 offset;
0567
0568
0569 if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0)
0570 return 0;
0571
0572
0573 offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET);
0574 return BCMA_CC_SPROM + (offset >> 3);
0575 }
0576
0577 int bcma_sprom_get(struct bcma_bus *bus)
0578 {
0579 u16 offset = BCMA_CC_SPROM;
0580 u16 *sprom;
0581 static const size_t sprom_sizes[] = {
0582 SSB_SPROMSIZE_WORDS_R4,
0583 SSB_SPROMSIZE_WORDS_R10,
0584 SSB_SPROMSIZE_WORDS_R11,
0585 };
0586 int i, err = 0;
0587
0588 if (!bus->drv_cc.core)
0589 return -EOPNOTSUPP;
0590
0591 if (!bcma_sprom_ext_available(bus)) {
0592 bool sprom_onchip;
0593
0594
0595
0596
0597
0598
0599 sprom_onchip = bcma_sprom_onchip_available(bus);
0600 if (sprom_onchip) {
0601
0602 offset = bcma_sprom_onchip_offset(bus);
0603 }
0604 if (!offset || !sprom_onchip) {
0605
0606
0607
0608
0609
0610 err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
0611 return err;
0612 }
0613 }
0614
0615 if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
0616 bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
0617 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
0618
0619 bcma_debug(bus, "SPROM offset 0x%x\n", offset);
0620 for (i = 0; i < ARRAY_SIZE(sprom_sizes); i++) {
0621 size_t words = sprom_sizes[i];
0622
0623 sprom = kcalloc(words, sizeof(u16), GFP_KERNEL);
0624 if (!sprom)
0625 return -ENOMEM;
0626
0627 bcma_sprom_read(bus, offset, sprom, words);
0628 err = bcma_sprom_valid(bus, sprom, words);
0629 if (!err)
0630 break;
0631
0632 kfree(sprom);
0633 }
0634
0635 if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
0636 bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
0637 bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
0638
0639 if (err) {
0640 bcma_warn(bus, "Invalid SPROM read from the PCIe card, trying to use fallback SPROM\n");
0641 err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
0642 } else {
0643 bcma_sprom_extract_r8(bus, sprom);
0644 kfree(sprom);
0645 }
0646
0647 return err;
0648 }