1 /* 2 * Copyright (c) 2004-2008 Reyk Floeter <reyk (at) openbsd.org> 3 * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm (at) gmail.com> 4 * Copyright (c) 2008-2009 Felix Fietkau <nbd (at) openwrt.org> 5 * 6 * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj (at) rwcr.net>. 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 * 20 */ 21 22 FILE_LICENCE ( MIT ); 23 24 /*************************************\ 25 * EEPROM access functions and helpers * 26 \*************************************/ 27 28 #include <unistd.h> 29 #include <stdlib.h> 30 31 #include "ath5k.h" 32 #include "reg.h" 33 #include "base.h" 34 35 /* 36 * Read from eeprom 37 */ 38 static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) 39 { 40 u32 status, timeout; 41 42 /* 43 * Initialize EEPROM access 44 */ 45 if (ah->ah_version == AR5K_AR5210) { 46 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); 47 (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); 48 } else { 49 ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); 50 AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, 51 AR5K_EEPROM_CMD_READ); 52 } 53 54 for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { 55 status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); 56 if (status & AR5K_EEPROM_STAT_RDDONE) { 57 if (status & AR5K_EEPROM_STAT_RDERR) 58 return -EIO; 59 *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & 60 0xffff); 61 return 0; 62 } 63 udelay(15); 64 } 65 66 return -ETIMEDOUT; 67 } 68 69 /* 70 * Translate binary channel representation in EEPROM to frequency 71 */ 72 static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, 73 unsigned int mode) 74 { 75 u16 val; 76 77 if (bin == AR5K_EEPROM_CHANNEL_DIS) 78 return bin; 79 80 if (mode == AR5K_EEPROM_MODE_11A) { 81 if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) 82 val = (5 * bin) + 4800; 83 else 84 val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : 85 (bin * 10) + 5100; 86 } else { 87 if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) 88 val = bin + 2300; 89 else 90 val = bin + 2400; 91 } 92 93 return val; 94 } 95 96 /* 97 * Initialize eeprom & capabilities structs 98 */ 99 static int 100 ath5k_eeprom_init_header(struct ath5k_hw *ah) 101 { 102 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 103 int ret; 104 u16 val; 105 106 /* 107 * Read values from EEPROM and store them in the capability structure 108 */ 109 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic); 110 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect); 111 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain); 112 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version); 113 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header); 114 115 /* Return if we have an old EEPROM */ 116 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) 117 return 0; 118 119 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), 120 ee_ant_gain); 121 122 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { 123 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); 124 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); 125 126 /* XXX: Don't know which versions include these two */ 127 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2); 128 129 if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) 130 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3); 131 132 if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) { 133 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4); 134 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5); 135 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6); 136 } 137 } 138 139 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { 140 AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val); 141 ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7; 142 ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7; 143 144 AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val); 145 ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7; 146 ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; 147 } 148 149 AR5K_EEPROM_READ(AR5K_EEPROM_IS_HB63, val); 150 151 if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && val) 152 ee->ee_is_hb63 = 1; 153 else 154 ee->ee_is_hb63 = 0; 155 156 AR5K_EEPROM_READ(AR5K_EEPROM_RFKILL, val); 157 ee->ee_rfkill_pin = (u8) AR5K_REG_MS(val, AR5K_EEPROM_RFKILL_GPIO_SEL); 158 ee->ee_rfkill_pol = val & AR5K_EEPROM_RFKILL_POLARITY ? 1 : 0; 159 160 return 0; 161 } 162 163 164 /* 165 * Read antenna infos from eeprom 166 */ 167 static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, 168 unsigned int mode) 169 { 170 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 171 u32 o = *offset; 172 u16 val; 173 int ret, i = 0; 174 175 AR5K_EEPROM_READ(o++, val); 176 ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; 177 ee->ee_atn_tx_rx[mode] = (val >> 2) & 0x3f; 178 ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; 179 180 AR5K_EEPROM_READ(o++, val); 181 ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; 182 ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; 183 ee->ee_ant_control[mode][i++] = val & 0x3f; 184 185 AR5K_EEPROM_READ(o++, val); 186 ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f; 187 ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f; 188 ee->ee_ant_control[mode][i] = (val << 2) & 0x3f; 189 190 AR5K_EEPROM_READ(o++, val); 191 ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3; 192 ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f; 193 ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f; 194 ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; 195 196 AR5K_EEPROM_READ(o++, val); 197 ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; 198 ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; 199 ee->ee_ant_control[mode][i++] = val & 0x3f; 200 201 /* Get antenna modes */ 202 ah->ah_antenna[mode][0] = 203 (ee->ee_ant_control[mode][0] << 4); 204 ah->ah_antenna[mode][AR5K_ANT_FIXED_A] = 205 ee->ee_ant_control[mode][1] | 206 (ee->ee_ant_control[mode][2] << 6) | 207 (ee->ee_ant_control[mode][3] << 12) | 208 (ee->ee_ant_control[mode][4] << 18) | 209 (ee->ee_ant_control[mode][5] << 24); 210 ah->ah_antenna[mode][AR5K_ANT_FIXED_B] = 211 ee->ee_ant_control[mode][6] | 212 (ee->ee_ant_control[mode][7] << 6) | 213 (ee->ee_ant_control[mode][8] << 12) | 214 (ee->ee_ant_control[mode][9] << 18) | 215 (ee->ee_ant_control[mode][10] << 24); 216 217 /* return new offset */ 218 *offset = o; 219 220 return 0; 221 } 222 223 /* 224 * Read supported modes and some mode-specific calibration data 225 * from eeprom 226 */ 227 static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, 228 unsigned int mode) 229 { 230 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 231 u32 o = *offset; 232 u16 val; 233 int ret; 234 235 ee->ee_n_piers[mode] = 0; 236 AR5K_EEPROM_READ(o++, val); 237 ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); 238 switch(mode) { 239 case AR5K_EEPROM_MODE_11A: 240 ee->ee_ob[mode][3] = (val >> 5) & 0x7; 241 ee->ee_db[mode][3] = (val >> 2) & 0x7; 242 ee->ee_ob[mode][2] = (val << 1) & 0x7; 243 244 AR5K_EEPROM_READ(o++, val); 245 ee->ee_ob[mode][2] |= (val >> 15) & 0x1; 246 ee->ee_db[mode][2] = (val >> 12) & 0x7; 247 ee->ee_ob[mode][1] = (val >> 9) & 0x7; 248 ee->ee_db[mode][1] = (val >> 6) & 0x7; 249 ee->ee_ob[mode][0] = (val >> 3) & 0x7; 250 ee->ee_db[mode][0] = val & 0x7; 251 break; 252 case AR5K_EEPROM_MODE_11G: 253 case AR5K_EEPROM_MODE_11B: 254 ee->ee_ob[mode][1] = (val >> 4) & 0x7; 255 ee->ee_db[mode][1] = val & 0x7; 256 break; 257 } 258 259 AR5K_EEPROM_READ(o++, val); 260 ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff; 261 ee->ee_thr_62[mode] = val & 0xff; 262 263 if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) 264 ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28; 265 266 AR5K_EEPROM_READ(o++, val); 267 ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff; 268 ee->ee_tx_frm2xpa_enable[mode] = val & 0xff; 269 270 AR5K_EEPROM_READ(o++, val); 271 ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff; 272 273 if ((val & 0xff) & 0x80) 274 ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1); 275 else 276 ee->ee_noise_floor_thr[mode] = val & 0xff; 277 278 if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) 279 ee->ee_noise_floor_thr[mode] = 280 mode == AR5K_EEPROM_MODE_11A ? -54 : -1; 281 282 AR5K_EEPROM_READ(o++, val); 283 ee->ee_xlna_gain[mode] = (val >> 5) & 0xff; 284 ee->ee_x_gain[mode] = (val >> 1) & 0xf; 285 ee->ee_xpd[mode] = val & 0x1; 286 287 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) 288 ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; 289 290 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { 291 AR5K_EEPROM_READ(o++, val); 292 ee->ee_false_detect[mode] = (val >> 6) & 0x7f; 293 294 if (mode == AR5K_EEPROM_MODE_11A) 295 ee->ee_xr_power[mode] = val & 0x3f; 296 else { 297 ee->ee_ob[mode][0] = val & 0x7; 298 ee->ee_db[mode][0] = (val >> 3) & 0x7; 299 } 300 } 301 302 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) { 303 ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN; 304 ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA; 305 } else { 306 ee->ee_i_gain[mode] = (val >> 13) & 0x7; 307 308 AR5K_EEPROM_READ(o++, val); 309 ee->ee_i_gain[mode] |= (val << 3) & 0x38; 310 311 if (mode == AR5K_EEPROM_MODE_11G) { 312 ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff; 313 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6) 314 ee->ee_scaled_cck_delta = (val >> 11) & 0x1f; 315 } 316 } 317 318 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && 319 mode == AR5K_EEPROM_MODE_11A) { 320 ee->ee_i_cal[mode] = (val >> 8) & 0x3f; 321 ee->ee_q_cal[mode] = (val >> 3) & 0x1f; 322 } 323 324 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0) 325 goto done; 326 327 /* Note: >= v5 have bg freq piers on another location 328 * so these freq piers are ignored for >= v5 (should be 0xff 329 * anyway) */ 330 switch(mode) { 331 case AR5K_EEPROM_MODE_11A: 332 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1) 333 break; 334 335 AR5K_EEPROM_READ(o++, val); 336 ee->ee_margin_tx_rx[mode] = val & 0x3f; 337 break; 338 case AR5K_EEPROM_MODE_11B: 339 AR5K_EEPROM_READ(o++, val); 340 341 ee->ee_pwr_cal_b[0].freq = 342 ath5k_eeprom_bin2freq(ee, val & 0xff, mode); 343 if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS) 344 ee->ee_n_piers[mode]++; 345 346 ee->ee_pwr_cal_b[1].freq = 347 ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); 348 if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS) 349 ee->ee_n_piers[mode]++; 350 351 AR5K_EEPROM_READ(o++, val); 352 ee->ee_pwr_cal_b[2].freq = 353 ath5k_eeprom_bin2freq(ee, val & 0xff, mode); 354 if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS) 355 ee->ee_n_piers[mode]++; 356 357 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) 358 ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; 359 break; 360 case AR5K_EEPROM_MODE_11G: 361 AR5K_EEPROM_READ(o++, val); 362 363 ee->ee_pwr_cal_g[0].freq = 364 ath5k_eeprom_bin2freq(ee, val & 0xff, mode); 365 if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS) 366 ee->ee_n_piers[mode]++; 367 368 ee->ee_pwr_cal_g[1].freq = 369 ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); 370 if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS) 371 ee->ee_n_piers[mode]++; 372 373 AR5K_EEPROM_READ(o++, val); 374 ee->ee_turbo_max_power[mode] = val & 0x7f; 375 ee->ee_xr_power[mode] = (val >> 7) & 0x3f; 376 377 AR5K_EEPROM_READ(o++, val); 378 ee->ee_pwr_cal_g[2].freq = 379 ath5k_eeprom_bin2freq(ee, val & 0xff, mode); 380 if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS) 381 ee->ee_n_piers[mode]++; 382 383 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) 384 ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; 385 386 AR5K_EEPROM_READ(o++, val); 387 ee->ee_i_cal[mode] = (val >> 8) & 0x3f; 388 ee->ee_q_cal[mode] = (val >> 3) & 0x1f; 389 390 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { 391 AR5K_EEPROM_READ(o++, val); 392 ee->ee_cck_ofdm_gain_delta = val & 0xff; 393 } 394 break; 395 } 396 397 done: 398 /* return new offset */ 399 *offset = o; 400 401 return 0; 402 } 403 404 /* 405 * Read turbo mode information on newer EEPROM versions 406 */ 407 static int 408 ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah, 409 u32 *offset, unsigned int mode) 410 { 411 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 412 u32 o = *offset; 413 u16 val; 414 int ret; 415 416 if (ee->ee_version < AR5K_EEPROM_VERSION_5_0) 417 return 0; 418 419 switch (mode){ 420 case AR5K_EEPROM_MODE_11A: 421 ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f; 422 423 ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7; 424 AR5K_EEPROM_READ(o++, val); 425 ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3; 426 ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f; 427 428 ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f; 429 AR5K_EEPROM_READ(o++, val); 430 ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7; 431 ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff; 432 433 if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2) 434 ee->ee_pd_gain_overlap = (val >> 9) & 0xf; 435 break; 436 case AR5K_EEPROM_MODE_11G: 437 ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f; 438 439 ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7; 440 AR5K_EEPROM_READ(o++, val); 441 ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1; 442 ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f; 443 444 ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f; 445 AR5K_EEPROM_READ(o++, val); 446 ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5; 447 ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff; 448 break; 449 } 450 451 /* return new offset */ 452 *offset = o; 453 454 return 0; 455 } 456 457 /* Read mode-specific data (except power calibration data) */ 458 static int 459 ath5k_eeprom_init_modes(struct ath5k_hw *ah) 460 { 461 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 462 u32 mode_offset[3]; 463 unsigned int mode; 464 u32 offset; 465 int ret; 466 467 /* 468 * Get values for all modes 469 */ 470 mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version); 471 mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version); 472 mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version); 473 474 ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] = 475 AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header); 476 477 for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) { 478 offset = mode_offset[mode]; 479 480 ret = ath5k_eeprom_read_ants(ah, &offset, mode); 481 if (ret) 482 return ret; 483 484 ret = ath5k_eeprom_read_modes(ah, &offset, mode); 485 if (ret) 486 return ret; 487 488 ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode); 489 if (ret) 490 return ret; 491 } 492 493 /* override for older eeprom versions for better performance */ 494 if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) { 495 ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15; 496 ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28; 497 ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28; 498 } 499 500 return 0; 501 } 502 503 /* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff 504 * frequency mask) */ 505 static inline int 506 ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, 507 struct ath5k_chan_pcal_info *pc, unsigned int mode) 508 { 509 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 510 int o = *offset; 511 int i = 0; 512 u8 freq1, freq2; 513 int ret; 514 u16 val; 515 516 ee->ee_n_piers[mode] = 0; 517 while(i < max) { 518 AR5K_EEPROM_READ(o++, val); 519 520 freq1 = val & 0xff; 521 if (!freq1) 522 break; 523 524 pc[i++].freq = ath5k_eeprom_bin2freq(ee, 525 freq1, mode); 526 ee->ee_n_piers[mode]++; 527 528 freq2 = (val >> 8) & 0xff; 529 if (!freq2) 530 break; 531 532 pc[i++].freq = ath5k_eeprom_bin2freq(ee, 533 freq2, mode); 534 ee->ee_n_piers[mode]++; 535 } 536 537 /* return new offset */ 538 *offset = o; 539 540 return 0; 541 } 542 543 /* Read frequency piers for 802.11a */ 544 static int 545 ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) 546 { 547 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 548 struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a; 549 int i, ret; 550 u16 val; 551 u8 mask; 552 553 if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { 554 ath5k_eeprom_read_freq_list(ah, &offset, 555 AR5K_EEPROM_N_5GHZ_CHAN, pcal, 556 AR5K_EEPROM_MODE_11A); 557 } else { 558 mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version); 559 560 AR5K_EEPROM_READ(offset++, val); 561 pcal[0].freq = (val >> 9) & mask; 562 pcal[1].freq = (val >> 2) & mask; 563 pcal[2].freq = (val << 5) & mask; 564 565 AR5K_EEPROM_READ(offset++, val); 566 pcal[2].freq |= (val >> 11) & 0x1f; 567 pcal[3].freq = (val >> 4) & mask; 568 pcal[4].freq = (val << 3) & mask; 569 570 AR5K_EEPROM_READ(offset++, val); 571 pcal[4].freq |= (val >> 13) & 0x7; 572 pcal[5].freq = (val >> 6) & mask; 573 pcal[6].freq = (val << 1) & mask; 574 575 AR5K_EEPROM_READ(offset++, val); 576 pcal[6].freq |= (val >> 15) & 0x1; 577 pcal[7].freq = (val >> 8) & mask; 578 pcal[8].freq = (val >> 1) & mask; 579 pcal[9].freq = (val << 6) & mask; 580 581 AR5K_EEPROM_READ(offset++, val); 582 pcal[9].freq |= (val >> 10) & 0x3f; 583 584 /* Fixed number of piers */ 585 ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10; 586 587 for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) { 588 pcal[i].freq = ath5k_eeprom_bin2freq(ee, 589 pcal[i].freq, AR5K_EEPROM_MODE_11A); 590 } 591 } 592 593 return 0; 594 } 595 596 /* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */ 597 static inline int 598 ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) 599 { 600 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 601 struct ath5k_chan_pcal_info *pcal; 602 603 switch(mode) { 604 case AR5K_EEPROM_MODE_11B: 605 pcal = ee->ee_pwr_cal_b; 606 break; 607 case AR5K_EEPROM_MODE_11G: 608 pcal = ee->ee_pwr_cal_g; 609 break; 610 default: 611 return -EINVAL; 612 } 613 614 ath5k_eeprom_read_freq_list(ah, &offset, 615 AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal, 616 mode); 617 618 return 0; 619 } 620 621 /* 622 * Read power calibration for RF5111 chips 623 * 624 * For RF5111 we have an XPD -eXternal Power Detector- curve 625 * for each calibrated channel. Each curve has 0,5dB Power steps 626 * on x axis and PCDAC steps (offsets) on y axis and looks like an 627 * exponential function. To recreate the curve we read 11 points 628 * here and interpolate later. 629 */ 630 631 /* Used to match PCDAC steps with power values on RF5111 chips 632 * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC 633 * steps that match with the power values we read from eeprom. On 634 * older eeprom versions (< 3.2) these steps are equaly spaced at 635 * 10% of the pcdac curve -until the curve reaches it's maximum- 636 * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) 637 * these 11 steps are spaced in a different way. This function returns 638 * the pcdac steps based on eeprom version and curve min/max so that we 639 * can have pcdac/pwr points. 640 */ 641 static inline void 642 ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) 643 { 644 static const u16 intercepts3[] = 645 { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; 646 static const u16 intercepts3_2[] = 647 { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; 648 const u16 *ip; 649 unsigned i; 650 651 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2) 652 ip = intercepts3_2; 653 else 654 ip = intercepts3; 655 656 for (i = 0; i < ARRAY_SIZE(intercepts3); i++) 657 vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; 658 } 659 660 /* Convert RF5111 specific data to generic raw data 661 * used by interpolation code */ 662 static int 663 ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, 664 struct ath5k_chan_pcal_info *chinfo) 665 { 666 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 667 struct ath5k_chan_pcal_info_rf5111 *pcinfo; 668 struct ath5k_pdgain_info *pd; 669 u8 pier, point, idx; 670 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; 671 672 /* Fill raw data for each calibration pier */ 673 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { 674 675 pcinfo = &chinfo[pier].rf5111_info; 676 677 /* Allocate pd_curves for this cal pier */ 678 chinfo[pier].pd_curves = 679 calloc(AR5K_EEPROM_N_PD_CURVES, 680 sizeof(struct ath5k_pdgain_info)); 681 682 if (!chinfo[pier].pd_curves) 683 return -ENOMEM; 684 685 /* Only one curve for RF5111 686 * find out which one and place 687 * in in pd_curves. 688 * Note: ee_x_gain is reversed here */ 689 for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) { 690 691 if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) { 692 pdgain_idx[0] = idx; 693 break; 694 } 695 } 696 697 ee->ee_pd_gains[mode] = 1; 698 699 pd = &chinfo[pier].pd_curves[idx]; 700 701 pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111; 702 703 /* Allocate pd points for this curve */ 704 pd->pd_step = calloc(AR5K_EEPROM_N_PWR_POINTS_5111, sizeof(u8)); 705 if (!pd->pd_step) 706 return -ENOMEM; 707 708 pd->pd_pwr = calloc(AR5K_EEPROM_N_PWR_POINTS_5111, sizeof(s16)); 709 if (!pd->pd_pwr) 710 return -ENOMEM; 711 712 /* Fill raw dataset 713 * (convert power to 0.25dB units 714 * for RF5112 combatibility) */ 715 for (point = 0; point < pd->pd_points; point++) { 716 717 /* Absolute values */ 718 pd->pd_pwr[point] = 2 * pcinfo->pwr[point]; 719 720 /* Already sorted */ 721 pd->pd_step[point] = pcinfo->pcdac[point]; 722 } 723 724 /* Set min/max pwr */ 725 chinfo[pier].min_pwr = pd->pd_pwr[0]; 726 chinfo[pier].max_pwr = pd->pd_pwr[10]; 727 728 } 729 730 return 0; 731 } 732 733 /* Parse EEPROM data */ 734 static int 735 ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) 736 { 737 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 738 struct ath5k_chan_pcal_info *pcal; 739 int offset, ret; 740 int i; 741 u16 val; 742 743 offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); 744 switch(mode) { 745 case AR5K_EEPROM_MODE_11A: 746 if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) 747 return 0; 748 749 ret = ath5k_eeprom_init_11a_pcal_freq(ah, 750 offset + AR5K_EEPROM_GROUP1_OFFSET); 751 if (ret < 0) 752 return ret; 753 754 offset += AR5K_EEPROM_GROUP2_OFFSET; 755 pcal = ee->ee_pwr_cal_a; 756 break; 757 case AR5K_EEPROM_MODE_11B: 758 if (!AR5K_EEPROM_HDR_11B(ee->ee_header) && 759 !AR5K_EEPROM_HDR_11G(ee->ee_header)) 760 return 0; 761 762 pcal = ee->ee_pwr_cal_b; 763 offset += AR5K_EEPROM_GROUP3_OFFSET; 764 765 /* fixed piers */ 766 pcal[0].freq = 2412; 767 pcal[1].freq = 2447; 768 pcal[2].freq = 2484; 769 ee->ee_n_piers[mode] = 3; 770 break; 771 case AR5K_EEPROM_MODE_11G: 772 if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) 773 return 0; 774 775 pcal = ee->ee_pwr_cal_g; 776 offset += AR5K_EEPROM_GROUP4_OFFSET; 777 778 /* fixed piers */ 779 pcal[0].freq = 2312; 780 pcal[1].freq = 2412; 781 pcal[2].freq = 2484; 782 ee->ee_n_piers[mode] = 3; 783 break; 784 default: 785 return -EINVAL; 786 } 787 788 for (i = 0; i < ee->ee_n_piers[mode]; i++) { 789 struct ath5k_chan_pcal_info_rf5111 *cdata = 790 &pcal[i].rf5111_info; 791 792 AR5K_EEPROM_READ(offset++, val); 793 cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M); 794 cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M); 795 cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M); 796 797 AR5K_EEPROM_READ(offset++, val); 798 cdata->pwr[0] |= ((val >> 14) & 0x3); 799 cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M); 800 cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M); 801 cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M); 802 803 AR5K_EEPROM_READ(offset++, val); 804 cdata->pwr[3] |= ((val >> 12) & 0xf); 805 cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M); 806 cdata->pwr[5] = (val & AR5K_EEPROM_POWER_M); 807 808 AR5K_EEPROM_READ(offset++, val); 809 cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M); 810 cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M); 811 cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M); 812 813 AR5K_EEPROM_READ(offset++, val); 814 cdata->pwr[8] |= ((val >> 14) & 0x3); 815 cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M); 816 cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M); 817 818 ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min, 819 cdata->pcdac_max, cdata->pcdac); 820 } 821 822 return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal); 823 } 824 825 826 /* 827 * Read power calibration for RF5112 chips 828 * 829 * For RF5112 we have 4 XPD -eXternal Power Detector- curves 830 * for each calibrated channel on 0, -6, -12 and -18dbm but we only 831 * use the higher (3) and the lower (0) curves. Each curve has 0.5dB 832 * power steps on x axis and PCDAC steps on y axis and looks like a 833 * linear function. To recreate the curve and pass the power values 834 * on hw, we read 4 points for xpd 0 (lower gain -> max power) 835 * and 3 points for xpd 3 (higher gain -> lower power) here and 836 * interpolate later. 837 * 838 * Note: Many vendors just use xpd 0 so xpd 3 is zeroed. 839 */ 840 841 /* Convert RF5112 specific data to generic raw data 842 * used by interpolation code */ 843 static int 844 ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, 845 struct ath5k_chan_pcal_info *chinfo) 846 { 847 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 848 struct ath5k_chan_pcal_info_rf5112 *pcinfo; 849 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; 850 unsigned int pier, pdg, point; 851 852 /* Fill raw data for each calibration pier */ 853 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { 854 855 pcinfo = &chinfo[pier].rf5112_info; 856 857 /* Allocate pd_curves for this cal pier */ 858 chinfo[pier].pd_curves = 859 calloc(AR5K_EEPROM_N_PD_CURVES, 860 sizeof(struct ath5k_pdgain_info)); 861 862 if (!chinfo[pier].pd_curves) 863 return -ENOMEM; 864 865 /* Fill pd_curves */ 866 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { 867 868 u8 idx = pdgain_idx[pdg]; 869 struct ath5k_pdgain_info *pd = 870 &chinfo[pier].pd_curves[idx]; 871 872 /* Lowest gain curve (max power) */ 873 if (pdg == 0) { 874 /* One more point for better accuracy */ 875 pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS; 876 877 /* Allocate pd points for this curve */ 878 pd->pd_step = calloc(pd->pd_points, sizeof(u8)); 879 880 if (!pd->pd_step) 881 return -ENOMEM; 882 883 pd->pd_pwr = calloc(pd->pd_points, sizeof(s16)); 884 885 if (!pd->pd_pwr) 886 return -ENOMEM; 887 888 889 /* Fill raw dataset 890 * (all power levels are in 0.25dB units) */ 891 pd->pd_step[0] = pcinfo->pcdac_x0[0]; 892 pd->pd_pwr[0] = pcinfo->pwr_x0[0]; 893 894 for (point = 1; point < pd->pd_points; 895 point++) { 896 /* Absolute values */ 897 pd->pd_pwr[point] = 898 pcinfo->pwr_x0[point]; 899 900 /* Deltas */ 901 pd->pd_step[point] = 902 pd->pd_step[point - 1] + 903 pcinfo->pcdac_x0[point]; 904 } 905 906 /* Set min power for this frequency */ 907 chinfo[pier].min_pwr = pd->pd_pwr[0]; 908 909 /* Highest gain curve (min power) */ 910 } else if (pdg == 1) { 911 912 pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS; 913 914 /* Allocate pd points for this curve */ 915 pd->pd_step = calloc(pd->pd_points, sizeof(u8)); 916 917 if (!pd->pd_step) 918 return -ENOMEM; 919 920 pd->pd_pwr = calloc(pd->pd_points, sizeof(s16)); 921 922 if (!pd->pd_pwr) 923 return -ENOMEM; 924 925 /* Fill raw dataset 926 * (all power levels are in 0.25dB units) */ 927 for (point = 0; point < pd->pd_points; 928 point++) { 929 /* Absolute values */ 930 pd->pd_pwr[point] = 931 pcinfo->pwr_x3[point]; 932 933 /* Fixed points */ 934 pd->pd_step[point] = 935 pcinfo->pcdac_x3[point]; 936 } 937 938 /* Since we have a higher gain curve 939 * override min power */ 940 chinfo[pier].min_pwr = pd->pd_pwr[0]; 941 } 942 } 943 } 944 945 return 0; 946 } 947 948 /* Parse EEPROM data */ 949 static int 950 ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) 951 { 952 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 953 struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info; 954 struct ath5k_chan_pcal_info *gen_chan_info; 955 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; 956 u32 offset; 957 u8 i, c; 958 u16 val; 959 int ret; 960 u8 pd_gains = 0; 961 962 /* Count how many curves we have and 963 * identify them (which one of the 4 964 * available curves we have on each count). 965 * Curves are stored from lower (x0) to 966 * higher (x3) gain */ 967 for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) { 968 /* ee_x_gain[mode] is x gain mask */ 969 if ((ee->ee_x_gain[mode] >> i) & 0x1) 970 pdgain_idx[pd_gains++] = i; 971 } 972 ee->ee_pd_gains[mode] = pd_gains; 973 974 if (pd_gains == 0 || pd_gains > 2) 975 return -EINVAL; 976 977 switch (mode) { 978 case AR5K_EEPROM_MODE_11A: 979 /* 980 * Read 5GHz EEPROM channels 981 */ 982 offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); 983 ath5k_eeprom_init_11a_pcal_freq(ah, offset); 984 985 offset += AR5K_EEPROM_GROUP2_OFFSET; 986 gen_chan_info = ee->ee_pwr_cal_a; 987 break; 988 case AR5K_EEPROM_MODE_11B: 989 offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); 990 if (AR5K_EEPROM_HDR_11A(ee->ee_header)) 991 offset += AR5K_EEPROM_GROUP3_OFFSET; 992 993 /* NB: frequency piers parsed during mode init */ 994 gen_chan_info = ee->ee_pwr_cal_b; 995 break; 996 case AR5K_EEPROM_MODE_11G: 997 offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); 998 if (AR5K_EEPROM_HDR_11A(ee->ee_header)) 999 offset += AR5K_EEPROM_GROUP4_OFFSET; 1000 else if (AR5K_EEPROM_HDR_11B(ee->ee_header)) 1001 offset += AR5K_EEPROM_GROUP2_OFFSET; 1002 1003 /* NB: frequency piers parsed during mode init */ 1004 gen_chan_info = ee->ee_pwr_cal_g; 1005 break; 1006 default: 1007 return -EINVAL; 1008 } 1009 1010 for (i = 0; i < ee->ee_n_piers[mode]; i++) { 1011 chan_pcal_info = &gen_chan_info[i].rf5112_info; 1012 1013 /* Power values in quarter dB 1014 * for the lower xpd gain curve 1015 * (0 dBm -> higher output power) */ 1016 for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) { 1017 AR5K_EEPROM_READ(offset++, val); 1018 chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff); 1019 chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff); 1020 } 1021 1022 /* PCDAC steps 1023 * corresponding to the above power 1024 * measurements */ 1025 AR5K_EEPROM_READ(offset++, val); 1026 chan_pcal_info->pcdac_x0[1] = (val & 0x1f); 1027 chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f); 1028 chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f); 1029 1030 /* Power values in quarter dB 1031 * for the higher xpd gain curve 1032 * (18 dBm -> lower output power) */ 1033 AR5K_EEPROM_READ(offset++, val); 1034 chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff); 1035 chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff); 1036 1037 AR5K_EEPROM_READ(offset++, val); 1038 chan_pcal_info->pwr_x3[2] = (val & 0xff); 1039 1040 /* PCDAC steps 1041 * corresponding to the above power 1042 * measurements (fixed) */ 1043 chan_pcal_info->pcdac_x3[0] = 20; 1044 chan_pcal_info->pcdac_x3[1] = 35; 1045 chan_pcal_info->pcdac_x3[2] = 63; 1046 1047 if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) { 1048 chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f); 1049 1050 /* Last xpd0 power level is also channel maximum */ 1051 gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3]; 1052 } else { 1053 chan_pcal_info->pcdac_x0[0] = 1; 1054 gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff); 1055 } 1056 1057 } 1058 1059 return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info); 1060 } 1061 1062 1063 /* 1064 * Read power calibration for RF2413 chips 1065 * 1066 * For RF2413 we have a Power to PDDAC table (Power Detector) 1067 * instead of a PCDAC and 4 pd gain curves for each calibrated channel. 1068 * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y 1069 * axis and looks like an exponential function like the RF5111 curve. 1070 * 1071 * To recreate the curves we read here the points and interpolate 1072 * later. Note that in most cases only 2 (higher and lower) curves are 1073 * used (like RF5112) but vendors have the oportunity to include all 1074 * 4 curves on eeprom. The final curve (higher power) has an extra 1075 * point for better accuracy like RF5112. 1076 */ 1077 1078 /* For RF2413 power calibration data doesn't start on a fixed location and 1079 * if a mode is not supported, it's section is missing -not zeroed-. 1080 * So we need to calculate the starting offset for each section by using 1081 * these two functions */ 1082 1083 /* Return the size of each section based on the mode and the number of pd 1084 * gains available (maximum 4). */ 1085 static inline unsigned int 1086 ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) 1087 { 1088 static const unsigned int pdgains_size[] = { 4, 6, 9, 12 }; 1089 unsigned int sz; 1090 1091 sz = pdgains_size[ee->ee_pd_gains[mode] - 1]; 1092 sz *= ee->ee_n_piers[mode]; 1093 1094 return sz; 1095 } 1096 1097 /* Return the starting offset for a section based on the modes supported 1098 * and each section's size. */ 1099 static unsigned int 1100 ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) 1101 { 1102 u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4); 1103 1104 switch(mode) { 1105 case AR5K_EEPROM_MODE_11G: 1106 if (AR5K_EEPROM_HDR_11B(ee->ee_header)) 1107 offset += ath5k_pdgains_size_2413(ee, 1108 AR5K_EEPROM_MODE_11B) + 1109 AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; 1110 /* fall through */ 1111 case AR5K_EEPROM_MODE_11B: 1112 if (AR5K_EEPROM_HDR_11A(ee->ee_header)) 1113 offset += ath5k_pdgains_size_2413(ee, 1114 AR5K_EEPROM_MODE_11A) + 1115 AR5K_EEPROM_N_5GHZ_CHAN / 2; 1116 /* fall through */ 1117 case AR5K_EEPROM_MODE_11A: 1118 break; 1119 default: 1120 break; 1121 } 1122 1123 return offset; 1124 } 1125 1126 /* Convert RF2413 specific data to generic raw data 1127 * used by interpolation code */ 1128 static int 1129 ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, 1130 struct ath5k_chan_pcal_info *chinfo) 1131 { 1132 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 1133 struct ath5k_chan_pcal_info_rf2413 *pcinfo; 1134 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; 1135 unsigned int pier, point; 1136 int pdg; 1137 1138 /* Fill raw data for each calibration pier */ 1139 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { 1140 1141 pcinfo = &chinfo[pier].rf2413_info; 1142 1143 /* Allocate pd_curves for this cal pier */ 1144 chinfo[pier].pd_curves = 1145 calloc(AR5K_EEPROM_N_PD_CURVES, 1146 sizeof(struct ath5k_pdgain_info)); 1147 1148 if (!chinfo[pier].pd_curves) 1149 return -ENOMEM; 1150 1151 /* Fill pd_curves */ 1152 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { 1153 1154 u8 idx = pdgain_idx[pdg]; 1155 struct ath5k_pdgain_info *pd = 1156 &chinfo[pier].pd_curves[idx]; 1157 1158 /* One more point for the highest power 1159 * curve (lowest gain) */ 1160 if (pdg == ee->ee_pd_gains[mode] - 1) 1161 pd->pd_points = AR5K_EEPROM_N_PD_POINTS; 1162 else 1163 pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1; 1164 1165 /* Allocate pd points for this curve */ 1166 pd->pd_step = calloc(pd->pd_points, sizeof(u8)); 1167 1168 if (!pd->pd_step) 1169 return -ENOMEM; 1170 1171 pd->pd_pwr = calloc(pd->pd_points, sizeof(s16)); 1172 1173 if (!pd->pd_pwr) 1174 return -ENOMEM; 1175 1176 /* Fill raw dataset 1177 * convert all pwr levels to 1178 * quarter dB for RF5112 combatibility */ 1179 pd->pd_step[0] = pcinfo->pddac_i[pdg]; 1180 pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg]; 1181 1182 for (point = 1; point < pd->pd_points; point++) { 1183 1184 pd->pd_pwr[point] = pd->pd_pwr[point - 1] + 1185 2 * pcinfo->pwr[pdg][point - 1]; 1186 1187 pd->pd_step[point] = pd->pd_step[point - 1] + 1188 pcinfo->pddac[pdg][point - 1]; 1189 1190 } 1191 1192 /* Highest gain curve -> min power */ 1193 if (pdg == 0) 1194 chinfo[pier].min_pwr = pd->pd_pwr[0]; 1195 1196 /* Lowest gain curve -> max power */ 1197 if (pdg == ee->ee_pd_gains[mode] - 1) 1198 chinfo[pier].max_pwr = 1199 pd->pd_pwr[pd->pd_points - 1]; 1200 } 1201 } 1202 1203 return 0; 1204 } 1205 1206 /* Parse EEPROM data */ 1207 static int 1208 ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) 1209 { 1210 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 1211 struct ath5k_chan_pcal_info_rf2413 *pcinfo; 1212 struct ath5k_chan_pcal_info *chinfo; 1213 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; 1214 u32 offset; 1215 int idx, i, ret; 1216 u16 val; 1217 u8 pd_gains = 0; 1218 1219 /* Count how many curves we have and 1220 * identify them (which one of the 4 1221 * available curves we have on each count). 1222 * Curves are stored from higher to 1223 * lower gain so we go backwards */ 1224 for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) { 1225 /* ee_x_gain[mode] is x gain mask */ 1226 if ((ee->ee_x_gain[mode] >> idx) & 0x1) 1227 pdgain_idx[pd_gains++] = idx; 1228 1229 } 1230 ee->ee_pd_gains[mode] = pd_gains; 1231 1232 if (pd_gains == 0) 1233 return -EINVAL; 1234 1235 offset = ath5k_cal_data_offset_2413(ee, mode); 1236 switch (mode) { 1237 case AR5K_EEPROM_MODE_11A: 1238 if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) 1239 return 0; 1240 1241 ath5k_eeprom_init_11a_pcal_freq(ah, offset); 1242 offset += AR5K_EEPROM_N_5GHZ_CHAN / 2; 1243 chinfo = ee->ee_pwr_cal_a; 1244 break; 1245 case AR5K_EEPROM_MODE_11B: 1246 if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) 1247 return 0; 1248 1249 ath5k_eeprom_init_11bg_2413(ah, mode, offset); 1250 offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; 1251 chinfo = ee->ee_pwr_cal_b; 1252 break; 1253 case AR5K_EEPROM_MODE_11G: 1254 if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) 1255 return 0; 1256 1257 ath5k_eeprom_init_11bg_2413(ah, mode, offset); 1258 offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; 1259 chinfo = ee->ee_pwr_cal_g; 1260 break; 1261 default: 1262 return -EINVAL; 1263 } 1264 1265 for (i = 0; i < ee->ee_n_piers[mode]; i++) { 1266 pcinfo = &chinfo[i].rf2413_info; 1267 1268 /* 1269 * Read pwr_i, pddac_i and the first 1270 * 2 pd points (pwr, pddac) 1271 */ 1272 AR5K_EEPROM_READ(offset++, val); 1273 pcinfo->pwr_i[0] = val & 0x1f; 1274 pcinfo->pddac_i[0] = (val >> 5) & 0x7f; 1275 pcinfo->pwr[0][0] = (val >> 12) & 0xf; 1276 1277 AR5K_EEPROM_READ(offset++, val); 1278 pcinfo->pddac[0][0] = val & 0x3f; 1279 pcinfo->pwr[0][1] = (val >> 6) & 0xf; 1280 pcinfo->pddac[0][1] = (val >> 10) & 0x3f; 1281 1282 AR5K_EEPROM_READ(offset++, val); 1283 pcinfo->pwr[0][2] = val & 0xf; 1284 pcinfo->pddac[0][2] = (val >> 4) & 0x3f; 1285 1286 pcinfo->pwr[0][3] = 0; 1287 pcinfo->pddac[0][3] = 0; 1288 1289 if (pd_gains > 1) { 1290 /* 1291 * Pd gain 0 is not the last pd gain 1292 * so it only has 2 pd points. 1293 * Continue wih pd gain 1. 1294 */ 1295 pcinfo->pwr_i[1] = (val >> 10) & 0x1f; 1296 1297 pcinfo->pddac_i[1] = (val >> 15) & 0x1; 1298 AR5K_EEPROM_READ(offset++, val); 1299 pcinfo->pddac_i[1] |= (val & 0x3F) << 1; 1300 1301 pcinfo->pwr[1][0] = (val >> 6) & 0xf; 1302 pcinfo->pddac[1][0] = (val >> 10) & 0x3f; 1303 1304 AR5K_EEPROM_READ(offset++, val); 1305 pcinfo->pwr[1][1] = val & 0xf; 1306 pcinfo->pddac[1][1] = (val >> 4) & 0x3f; 1307 pcinfo->pwr[1][2] = (val >> 10) & 0xf; 1308 1309 pcinfo->pddac[1][2] = (val >> 14) & 0x3; 1310 AR5K_EEPROM_READ(offset++, val); 1311 pcinfo->pddac[1][2] |= (val & 0xF) << 2; 1312 1313 pcinfo->pwr[1][3] = 0; 1314 pcinfo->pddac[1][3] = 0; 1315 } else if (pd_gains == 1) { 1316 /* 1317 * Pd gain 0 is the last one so 1318 * read the extra point. 1319 */ 1320 pcinfo->pwr[0][3] = (val >> 10) & 0xf; 1321 1322 pcinfo->pddac[0][3] = (val >> 14) & 0x3; 1323 AR5K_EEPROM_READ(offset++, val); 1324 pcinfo->pddac[0][3] |= (val & 0xF) << 2; 1325 } 1326 1327 /* 1328 * Proceed with the other pd_gains 1329 * as above. 1330 */ 1331 if (pd_gains > 2) { 1332 pcinfo->pwr_i[2] = (val >> 4) & 0x1f; 1333 pcinfo->pddac_i[2] = (val >> 9) & 0x7f; 1334 1335 AR5K_EEPROM_READ(offset++, val); 1336 pcinfo->pwr[2][0] = (val >> 0) & 0xf; 1337 pcinfo->pddac[2][0] = (val >> 4) & 0x3f; 1338 pcinfo->pwr[2][1] = (val >> 10) & 0xf; 1339 1340 pcinfo->pddac[2][1] = (val >> 14) & 0x3; 1341 AR5K_EEPROM_READ(offset++, val); 1342 pcinfo->pddac[2][1] |= (val & 0xF) << 2; 1343 1344 pcinfo->pwr[2][2] = (val >> 4) & 0xf; 1345 pcinfo->pddac[2][2] = (val >> 8) & 0x3f; 1346 1347 pcinfo->pwr[2][3] = 0; 1348 pcinfo->pddac[2][3] = 0; 1349 } else if (pd_gains == 2) { 1350 pcinfo->pwr[1][3] = (val >> 4) & 0xf; 1351 pcinfo->pddac[1][3] = (val >> 8) & 0x3f; 1352 } 1353 1354 if (pd_gains > 3) { 1355 pcinfo->pwr_i[3] = (val >> 14) & 0x3; 1356 AR5K_EEPROM_READ(offset++, val); 1357 pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2; 1358 1359 pcinfo->pddac_i[3] = (val >> 3) & 0x7f; 1360 pcinfo->pwr[3][0] = (val >> 10) & 0xf; 1361 pcinfo->pddac[3][0] = (val >> 14) & 0x3; 1362 1363 AR5K_EEPROM_READ(offset++, val); 1364 pcinfo->pddac[3][0] |= (val & 0xF) << 2; 1365 pcinfo->pwr[3][1] = (val >> 4) & 0xf; 1366 pcinfo->pddac[3][1] = (val >> 8) & 0x3f; 1367 1368 pcinfo->pwr[3][2] = (val >> 14) & 0x3; 1369 AR5K_EEPROM_READ(offset++, val); 1370 pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2; 1371 1372 pcinfo->pddac[3][2] = (val >> 2) & 0x3f; 1373 pcinfo->pwr[3][3] = (val >> 8) & 0xf; 1374 1375 pcinfo->pddac[3][3] = (val >> 12) & 0xF; 1376 AR5K_EEPROM_READ(offset++, val); 1377 pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4; 1378 } else if (pd_gains == 3) { 1379 pcinfo->pwr[2][3] = (val >> 14) & 0x3; 1380 AR5K_EEPROM_READ(offset++, val); 1381 pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2; 1382 1383 pcinfo->pddac[2][3] = (val >> 2) & 0x3f; 1384 } 1385 } 1386 1387 return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo); 1388 } 1389 1390 1391 /* 1392 * Read per rate target power (this is the maximum tx power 1393 * supported by the card). This info is used when setting 1394 * tx power, no matter the channel. 1395 * 1396 * This also works for v5 EEPROMs. 1397 */ 1398 static int 1399 ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) 1400 { 1401 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 1402 struct ath5k_rate_pcal_info *rate_pcal_info; 1403 u8 *rate_target_pwr_num; 1404 u32 offset; 1405 u16 val; 1406 int ret, i; 1407 1408 offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1); 1409 rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode]; 1410 switch (mode) { 1411 case AR5K_EEPROM_MODE_11A: 1412 offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version); 1413 rate_pcal_info = ee->ee_rate_tpwr_a; 1414 ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN; 1415 break; 1416 case AR5K_EEPROM_MODE_11B: 1417 offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version); 1418 rate_pcal_info = ee->ee_rate_tpwr_b; 1419 ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */ 1420 break; 1421 case AR5K_EEPROM_MODE_11G: 1422 offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version); 1423 rate_pcal_info = ee->ee_rate_tpwr_g; 1424 ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN; 1425 break; 1426 default: 1427 return -EINVAL; 1428 } 1429 1430 /* Different freq mask for older eeproms (<= v3.2) */ 1431 if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) { 1432 for (i = 0; i < (*rate_target_pwr_num); i++) { 1433 AR5K_EEPROM_READ(offset++, val); 1434 rate_pcal_info[i].freq = 1435 ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode); 1436 1437 rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f); 1438 rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f; 1439 1440 AR5K_EEPROM_READ(offset++, val); 1441 1442 if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || 1443 val == 0) { 1444 (*rate_target_pwr_num) = i; 1445 break; 1446 } 1447 1448 rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7); 1449 rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f); 1450 rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f); 1451 } 1452 } else { 1453 for (i = 0; i < (*rate_target_pwr_num); i++) { 1454 AR5K_EEPROM_READ(offset++, val); 1455 rate_pcal_info[i].freq = 1456 ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); 1457 1458 rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f); 1459 rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f; 1460 1461 AR5K_EEPROM_READ(offset++, val); 1462 1463 if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || 1464 val == 0) { 1465 (*rate_target_pwr_num) = i; 1466 break; 1467 } 1468 1469 rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf; 1470 rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f); 1471 rate_pcal_info[i].target_power_54 = (val & 0x3f); 1472 } 1473 } 1474 1475 return 0; 1476 } 1477 1478 /* 1479 * Read per channel calibration info from EEPROM 1480 * 1481 * This info is used to calibrate the baseband power table. Imagine 1482 * that for each channel there is a power curve that's hw specific 1483 * (depends on amplifier etc) and we try to "correct" this curve using 1484 * offests we pass on to phy chip (baseband -> before amplifier) so that 1485 * it can use accurate power values when setting tx power (takes amplifier's 1486 * performance on each channel into account). 1487 * 1488 * EEPROM provides us with the offsets for some pre-calibrated channels 1489 * and we have to interpolate to create the full table for these channels and 1490 * also the table for any channel. 1491 */ 1492 static int 1493 ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) 1494 { 1495 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 1496 int (*read_pcal)(struct ath5k_hw *hw, int mode); 1497 int mode; 1498 int err; 1499 1500 if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) && 1501 (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1)) 1502 read_pcal = ath5k_eeprom_read_pcal_info_5112; 1503 else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) && 1504 (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2)) 1505 read_pcal = ath5k_eeprom_read_pcal_info_2413; 1506 else 1507 read_pcal = ath5k_eeprom_read_pcal_info_5111; 1508 1509 1510 for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; 1511 mode++) { 1512 err = read_pcal(ah, mode); 1513 if (err) 1514 return err; 1515 1516 err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode); 1517 if (err < 0) 1518 return err; 1519 } 1520 1521 return 0; 1522 } 1523 1524 static int 1525 ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) 1526 { 1527 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 1528 struct ath5k_chan_pcal_info *chinfo; 1529 u8 pier, pdg; 1530 1531 switch (mode) { 1532 case AR5K_EEPROM_MODE_11A: 1533 if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) 1534 return 0; 1535 chinfo = ee->ee_pwr_cal_a; 1536 break; 1537 case AR5K_EEPROM_MODE_11B: 1538 if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) 1539 return 0; 1540 chinfo = ee->ee_pwr_cal_b; 1541 break; 1542 case AR5K_EEPROM_MODE_11G: 1543 if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) 1544 return 0; 1545 chinfo = ee->ee_pwr_cal_g; 1546 break; 1547 default: 1548 return -EINVAL; 1549 } 1550 1551 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { 1552 if (!chinfo[pier].pd_curves) 1553 continue; 1554 1555 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { 1556 struct ath5k_pdgain_info *pd = 1557 &chinfo[pier].pd_curves[pdg]; 1558 1559 if (pd != NULL) { 1560 free(pd->pd_step); 1561 free(pd->pd_pwr); 1562 } 1563 } 1564 1565 free(chinfo[pier].pd_curves); 1566 } 1567 1568 return 0; 1569 } 1570 1571 void 1572 ath5k_eeprom_detach(struct ath5k_hw *ah) 1573 { 1574 u8 mode; 1575 1576 for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) 1577 ath5k_eeprom_free_pcal_info(ah, mode); 1578 } 1579 1580 /* Read conformance test limits used for regulatory control */ 1581 static int 1582 ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) 1583 { 1584 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 1585 struct ath5k_edge_power *rep; 1586 unsigned int fmask, pmask; 1587 unsigned int ctl_mode; 1588 int ret, i, j; 1589 u32 offset; 1590 u16 val; 1591 1592 pmask = AR5K_EEPROM_POWER_M; 1593 fmask = AR5K_EEPROM_FREQ_M(ee->ee_version); 1594 offset = AR5K_EEPROM_CTL(ee->ee_version); 1595 ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version); 1596 for (i = 0; i < ee->ee_ctls; i += 2) { 1597 AR5K_EEPROM_READ(offset++, val); 1598 ee->ee_ctl[i] = (val >> 8) & 0xff; 1599 ee->ee_ctl[i + 1] = val & 0xff; 1600 } 1601 1602 offset = AR5K_EEPROM_GROUP8_OFFSET; 1603 if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) 1604 offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) - 1605 AR5K_EEPROM_GROUP5_OFFSET; 1606 else 1607 offset += AR5K_EEPROM_GROUPS_START(ee->ee_version); 1608 1609 rep = ee->ee_ctl_pwr; 1610 for(i = 0; i < ee->ee_ctls; i++) { 1611 switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) { 1612 case AR5K_CTL_11A: 1613 case AR5K_CTL_TURBO: 1614 ctl_mode = AR5K_EEPROM_MODE_11A; 1615 break; 1616 default: 1617 ctl_mode = AR5K_EEPROM_MODE_11G; 1618 break; 1619 } 1620 if (ee->ee_ctl[i] == 0) { 1621 if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) 1622 offset += 8; 1623 else 1624 offset += 7; 1625 rep += AR5K_EEPROM_N_EDGES; 1626 continue; 1627 } 1628 if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { 1629 for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) { 1630 AR5K_EEPROM_READ(offset++, val); 1631 rep[j].freq = (val >> 8) & fmask; 1632 rep[j + 1].freq = val & fmask; 1633 } 1634 for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) { 1635 AR5K_EEPROM_READ(offset++, val); 1636 rep[j].edge = (val >> 8) & pmask; 1637 rep[j].flag = (val >> 14) & 1; 1638 rep[j + 1].edge = val & pmask; 1639 rep[j + 1].flag = (val >> 6) & 1; 1640 } 1641 } else { 1642 AR5K_EEPROM_READ(offset++, val); 1643 rep[0].freq = (val >> 9) & fmask; 1644 rep[1].freq = (val >> 2) & fmask; 1645 rep[2].freq = (val << 5) & fmask; 1646 1647 AR5K_EEPROM_READ(offset++, val); 1648 rep[2].freq |= (val >> 11) & 0x1f; 1649 rep[3].freq = (val >> 4) & fmask; 1650 rep[4].freq = (val << 3) & fmask; 1651 1652 AR5K_EEPROM_READ(offset++, val); 1653 rep[4].freq |= (val >> 13) & 0x7; 1654 rep[5].freq = (val >> 6) & fmask; 1655 rep[6].freq = (val << 1) & fmask; 1656 1657 AR5K_EEPROM_READ(offset++, val); 1658 rep[6].freq |= (val >> 15) & 0x1; 1659 rep[7].freq = (val >> 8) & fmask; 1660 1661 rep[0].edge = (val >> 2) & pmask; 1662 rep[1].edge = (val << 4) & pmask; 1663 1664 AR5K_EEPROM_READ(offset++, val); 1665 rep[1].edge |= (val >> 12) & 0xf; 1666 rep[2].edge = (val >> 6) & pmask; 1667 rep[3].edge = val & pmask; 1668 1669 AR5K_EEPROM_READ(offset++, val); 1670 rep[4].edge = (val >> 10) & pmask; 1671 rep[5].edge = (val >> 4) & pmask; 1672 rep[6].edge = (val << 2) & pmask; 1673 1674 AR5K_EEPROM_READ(offset++, val); 1675 rep[6].edge |= (val >> 14) & 0x3; 1676 rep[7].edge = (val >> 8) & pmask; 1677 } 1678 for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) { 1679 rep[j].freq = ath5k_eeprom_bin2freq(ee, 1680 rep[j].freq, ctl_mode); 1681 } 1682 rep += AR5K_EEPROM_N_EDGES; 1683 } 1684 1685 return 0; 1686 } 1687 1688 1689 /* 1690 * Initialize eeprom power tables 1691 */ 1692 int 1693 ath5k_eeprom_init(struct ath5k_hw *ah) 1694 { 1695 int err; 1696 1697 err = ath5k_eeprom_init_header(ah); 1698 if (err < 0) 1699 return err; 1700 1701 err = ath5k_eeprom_init_modes(ah); 1702 if (err < 0) 1703 return err; 1704 1705 err = ath5k_eeprom_read_pcal_info(ah); 1706 if (err < 0) 1707 return err; 1708 1709 err = ath5k_eeprom_read_ctl_info(ah); 1710 if (err < 0) 1711 return err; 1712 1713 return 0; 1714 } 1715 1716 /* 1717 * Read the MAC address from eeprom 1718 */ 1719 int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) 1720 { 1721 u8 mac_d[ETH_ALEN] = {}; 1722 u32 total, offset; 1723 u16 data; 1724 int octet, ret; 1725 1726 ret = ath5k_hw_eeprom_read(ah, 0x20, &data); 1727 if (ret) 1728 return ret; 1729 1730 for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { 1731 ret = ath5k_hw_eeprom_read(ah, offset, &data); 1732 if (ret) 1733 return ret; 1734 1735 total += data; 1736 mac_d[octet + 1] = data & 0xff; 1737 mac_d[octet] = data >> 8; 1738 octet += 2; 1739 } 1740 1741 if (!total || total == 3 * 0xffff) 1742 return -EINVAL; 1743 1744 memcpy(mac, mac_d, ETH_ALEN); 1745 1746 return 0; 1747 } 1748 1749 int ath5k_eeprom_is_hb63(struct ath5k_hw *ah) 1750 { 1751 u16 data; 1752 1753 ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data); 1754 1755 if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data) 1756 return 1; 1757 else 1758 return 0; 1759 } 1760 1761