24 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26 #include <linux/slab.h>
50 val = (5 * bin) + 4800;
52 val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
109 ATH5K_ERR(ah,
"Invalid max custom EEPROM size: "
110 "%d (0x%04x) max expected: %d (0x%04x)\n",
118 for (cksum = 0, offset = 0; offset < eep_max; offset++) {
124 "checksum: 0x%04x eep_max: 0x%04x (%s)\n",
127 "default size" :
"custom size");
189 static int ath5k_eeprom_read_ants(
struct ath5k_hw *ah,
u32 *offset,
249 static int ath5k_eeprom_read_modes(
struct ath5k_hw *ah,
u32 *offset,
294 if ((val & 0xff) & 0x80)
365 ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
370 ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
376 ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
387 ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
392 ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
402 ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
467 ath5k_eeprom_init_modes(
struct ath5k_hw *ah)
486 offset = mode_offset[
mode];
488 ret = ath5k_eeprom_read_ants(ah, &offset, mode);
492 ret = ath5k_eeprom_read_modes(ah, &offset, mode);
510 ath5k_eeprom_read_freq_list(
struct ath5k_hw *ah,
int *offset,
int max,
527 pc[i++].
freq = ath5k_eeprom_bin2freq(ee,
531 freq2 = (val >> 8) & 0xff;
535 pc[i++].
freq = ath5k_eeprom_bin2freq(ee,
548 ath5k_eeprom_init_11a_pcal_freq(
struct ath5k_hw *ah,
int offset)
557 ath5k_eeprom_read_freq_list(ah, &offset,
564 pcal[0].
freq = (val >> 9) & mask;
565 pcal[1].
freq = (val >> 2) & mask;
566 pcal[2].
freq = (val << 5) & mask;
569 pcal[2].
freq |= (val >> 11) & 0x1f;
570 pcal[3].
freq = (val >> 4) & mask;
571 pcal[4].
freq = (val << 3) & mask;
574 pcal[4].
freq |= (val >> 13) & 0x7;
575 pcal[5].
freq = (val >> 6) & mask;
576 pcal[6].
freq = (val << 1) & mask;
579 pcal[6].
freq |= (val >> 15) & 0x1;
580 pcal[7].
freq = (val >> 8) & mask;
581 pcal[8].
freq = (val >> 1) & mask;
582 pcal[9].
freq = (val << 6) & mask;
585 pcal[9].
freq |= (val >> 10) & 0x3f;
591 pcal[
i].
freq = ath5k_eeprom_bin2freq(ee,
601 ath5k_eeprom_init_11bg_2413(
struct ath5k_hw *ah,
unsigned int mode,
int offset)
617 ath5k_eeprom_read_freq_list(ah, &offset,
648 static const u16 intercepts3[] = {
649 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100
651 static const u16 intercepts3_2[] = {
652 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
663 vp[i] = (ip[i] * max + (100 - ip[i]) *
min) / 100;
667 ath5k_eeprom_free_pcal_info(
struct ath5k_hw *ah,
int mode)
705 kfree(chinfo[pier].pd_curves);
714 ath5k_eeprom_convert_pcal_info_5111(
struct ath5k_hw *ah,
int mode,
734 if (!chinfo[pier].pd_curves)
743 if (!((ee->
ee_x_gain[mode] >> idx) & 0x1)) {
769 for (point = 0; point < pd->
pd_points; point++) {
787 ath5k_eeprom_free_pcal_info(ah, mode);
793 ath5k_eeprom_read_pcal_info_5111(
struct ath5k_hw *ah,
int mode)
807 ret = ath5k_eeprom_init_11a_pcal_freq(ah,
856 cdata->
pwr[0] |= ((val >> 14) & 0x3);
862 cdata->
pwr[3] |= ((val >> 12) & 0xf);
872 cdata->
pwr[8] |= ((val >> 14) & 0x3);
876 ath5k_get_pcdac_intercepts(ah, cdata->
pcdac_min,
880 return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal);
902 ath5k_eeprom_convert_pcal_info_5112(
struct ath5k_hw *ah,
int mode,
908 unsigned int pier, pdg,
point;
917 kcalloc(AR5K_EEPROM_N_PD_CURVES,
921 if (!chinfo[pier].pd_curves)
927 u8 idx = pdgain_idx[pdg];
970 }
else if (pdg == 1) {
1010 ath5k_eeprom_free_pcal_info(ah, mode);
1016 ath5k_eeprom_read_pcal_info_5112(
struct ath5k_hw *ah,
int mode)
1035 pdgain_idx[pd_gains++] =
i;
1039 if (pd_gains == 0 || pd_gains > 2)
1048 ath5k_eeprom_init_11a_pcal_freq(ah, offset);
1083 chan_pcal_info->
pwr_x0[
c] = (
s8) (val & 0xff);
1084 chan_pcal_info->
pwr_x0[++
c] = (
s8) ((val >> 8) & 0xff);
1091 chan_pcal_info->
pcdac_x0[1] = (val & 0x1f);
1092 chan_pcal_info->
pcdac_x0[2] = ((val >> 5) & 0x1f);
1093 chan_pcal_info->
pcdac_x0[3] = ((val >> 10) & 0x1f);
1099 chan_pcal_info->
pwr_x3[0] = (
s8) (val & 0xff);
1100 chan_pcal_info->
pwr_x3[1] = (
s8) ((val >> 8) & 0xff);
1103 chan_pcal_info->
pwr_x3[2] = (val & 0xff);
1113 chan_pcal_info->
pcdac_x0[0] = ((val >> 8) & 0x3f);
1119 gen_chan_info[
i].
max_pwr = (
s8) ((val >> 8) & 0xff);
1124 return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info);
1150 static inline unsigned int
1153 static const unsigned int pdgains_size[] = { 4, 6, 9, 12 };
1172 offset += ath5k_pdgains_size_2413(ee,
1178 offset += ath5k_pdgains_size_2413(ee,
1194 ath5k_eeprom_convert_pcal_info_2413(
struct ath5k_hw *ah,
int mode,
1200 unsigned int pier, pdg,
point;
1209 kcalloc(AR5K_EEPROM_N_PD_CURVES,
1213 if (!chinfo[pier].pd_curves)
1219 u8 idx = pdgain_idx[pdg];
1249 for (point = 1; point < pd->
pd_points; point++) {
1252 2 * pcinfo->
pwr[pdg][point - 1];
1255 pcinfo->
pddac[pdg][point - 1];
1273 ath5k_eeprom_free_pcal_info(ah, mode);
1279 ath5k_eeprom_read_pcal_info_2413(
struct ath5k_hw *ah,
int mode)
1295 for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) {
1298 pdgain_idx[pd_gains++] =
idx;
1306 offset = ath5k_cal_data_offset_2413(ee, mode);
1312 ath5k_eeprom_init_11a_pcal_freq(ah, offset);
1320 ath5k_eeprom_init_11bg_2413(ah, mode, offset);
1328 ath5k_eeprom_init_11bg_2413(ah, mode, offset);
1344 pcinfo->
pwr_i[0] = val & 0x1f;
1345 pcinfo->
pddac_i[0] = (val >> 5) & 0x7f;
1346 pcinfo->
pwr[0][0] = (val >> 12) & 0xf;
1349 pcinfo->
pddac[0][0] = val & 0x3f;
1350 pcinfo->
pwr[0][1] = (val >> 6) & 0xf;
1351 pcinfo->
pddac[0][1] = (val >> 10) & 0x3f;
1354 pcinfo->
pwr[0][2] = val & 0xf;
1355 pcinfo->
pddac[0][2] = (val >> 4) & 0x3f;
1357 pcinfo->
pwr[0][3] = 0;
1358 pcinfo->
pddac[0][3] = 0;
1366 pcinfo->
pwr_i[1] = (val >> 10) & 0x1f;
1368 pcinfo->
pddac_i[1] = (val >> 15) & 0x1;
1370 pcinfo->
pddac_i[1] |= (val & 0x3F) << 1;
1372 pcinfo->
pwr[1][0] = (val >> 6) & 0xf;
1373 pcinfo->
pddac[1][0] = (val >> 10) & 0x3f;
1376 pcinfo->
pwr[1][1] = val & 0xf;
1377 pcinfo->
pddac[1][1] = (val >> 4) & 0x3f;
1378 pcinfo->
pwr[1][2] = (val >> 10) & 0xf;
1380 pcinfo->
pddac[1][2] = (val >> 14) & 0x3;
1382 pcinfo->
pddac[1][2] |= (val & 0xF) << 2;
1384 pcinfo->
pwr[1][3] = 0;
1385 pcinfo->
pddac[1][3] = 0;
1386 }
else if (pd_gains == 1) {
1391 pcinfo->
pwr[0][3] = (val >> 10) & 0xf;
1393 pcinfo->
pddac[0][3] = (val >> 14) & 0x3;
1395 pcinfo->
pddac[0][3] |= (val & 0xF) << 2;
1403 pcinfo->
pwr_i[2] = (val >> 4) & 0x1f;
1404 pcinfo->
pddac_i[2] = (val >> 9) & 0x7f;
1407 pcinfo->
pwr[2][0] = (val >> 0) & 0xf;
1408 pcinfo->
pddac[2][0] = (val >> 4) & 0x3f;
1409 pcinfo->
pwr[2][1] = (val >> 10) & 0xf;
1411 pcinfo->
pddac[2][1] = (val >> 14) & 0x3;
1413 pcinfo->
pddac[2][1] |= (val & 0xF) << 2;
1415 pcinfo->
pwr[2][2] = (val >> 4) & 0xf;
1416 pcinfo->
pddac[2][2] = (val >> 8) & 0x3f;
1418 pcinfo->
pwr[2][3] = 0;
1419 pcinfo->
pddac[2][3] = 0;
1420 }
else if (pd_gains == 2) {
1421 pcinfo->
pwr[1][3] = (val >> 4) & 0xf;
1422 pcinfo->
pddac[1][3] = (val >> 8) & 0x3f;
1426 pcinfo->
pwr_i[3] = (val >> 14) & 0x3;
1428 pcinfo->
pwr_i[3] |= ((val >> 0) & 0x7) << 2;
1430 pcinfo->
pddac_i[3] = (val >> 3) & 0x7f;
1431 pcinfo->
pwr[3][0] = (val >> 10) & 0xf;
1432 pcinfo->
pddac[3][0] = (val >> 14) & 0x3;
1435 pcinfo->
pddac[3][0] |= (val & 0xF) << 2;
1436 pcinfo->
pwr[3][1] = (val >> 4) & 0xf;
1437 pcinfo->
pddac[3][1] = (val >> 8) & 0x3f;
1439 pcinfo->
pwr[3][2] = (val >> 14) & 0x3;
1441 pcinfo->
pwr[3][2] |= ((val >> 0) & 0x3) << 2;
1443 pcinfo->
pddac[3][2] = (val >> 2) & 0x3f;
1444 pcinfo->
pwr[3][3] = (val >> 8) & 0xf;
1446 pcinfo->
pddac[3][3] = (val >> 12) & 0xF;
1448 pcinfo->
pddac[3][3] |= ((val >> 0) & 0x3) << 4;
1449 }
else if (pd_gains == 3) {
1450 pcinfo->
pwr[2][3] = (val >> 14) & 0x3;
1452 pcinfo->
pwr[2][3] |= ((val >> 0) & 0x3) << 2;
1454 pcinfo->
pddac[2][3] = (val >> 2) & 0x3f;
1458 return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo);
1470 ath5k_eeprom_read_target_rate_pwr_info(
struct ath5k_hw *ah,
unsigned int mode)
1474 u8 *rate_target_pwr_num;
1503 for (i = 0; i < (*rate_target_pwr_num); i++) {
1505 rate_pcal_info[
i].
freq =
1506 ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode);
1515 (*rate_target_pwr_num) =
i;
1524 for (i = 0; i < (*rate_target_pwr_num); i++) {
1526 rate_pcal_info[
i].
freq =
1527 ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
1536 (*rate_target_pwr_num) =
i;
1565 ath5k_eeprom_read_pcal_info(
struct ath5k_hw *ah)
1574 read_pcal = ath5k_eeprom_read_pcal_info_5112;
1577 read_pcal = ath5k_eeprom_read_pcal_info_2413;
1579 read_pcal = ath5k_eeprom_read_pcal_info_5111;
1584 err = read_pcal(ah, mode);
1588 err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode);
1598 ath5k_eeprom_read_ctl_info(
struct ath5k_hw *ah)
1602 unsigned int fmask, pmask;
1603 unsigned int ctl_mode;
1612 for (i = 0; i < ee->
ee_ctls; i += 2) {
1614 ee->
ee_ctl[
i] = (val >> 8) & 0xff;
1615 ee->
ee_ctl[i + 1] = val & 0xff;
1626 for (i = 0; i < ee->
ee_ctls; i++) {
1636 if (ee->
ee_ctl[i] == 0) {
1647 rep[
j].
freq = (val >> 8) & fmask;
1648 rep[j + 1].
freq = val & fmask;
1652 rep[
j].
edge = (val >> 8) & pmask;
1653 rep[
j].
flag = (val >> 14) & 1;
1654 rep[j + 1].
edge = val & pmask;
1655 rep[j + 1].
flag = (val >> 6) & 1;
1659 rep[0].
freq = (val >> 9) & fmask;
1660 rep[1].
freq = (val >> 2) & fmask;
1661 rep[2].
freq = (val << 5) & fmask;
1664 rep[2].
freq |= (val >> 11) & 0x1f;
1665 rep[3].
freq = (val >> 4) & fmask;
1666 rep[4].
freq = (val << 3) & fmask;
1669 rep[4].
freq |= (val >> 13) & 0x7;
1670 rep[5].
freq = (val >> 6) & fmask;
1671 rep[6].
freq = (val << 1) & fmask;
1674 rep[6].
freq |= (val >> 15) & 0x1;
1675 rep[7].
freq = (val >> 8) & fmask;
1677 rep[0].
edge = (val >> 2) & pmask;
1678 rep[1].
edge = (val << 4) & pmask;
1681 rep[1].
edge |= (val >> 12) & 0xf;
1682 rep[2].
edge = (val >> 6) & pmask;
1683 rep[3].
edge = val & pmask;
1686 rep[4].
edge = (val >> 10) & pmask;
1687 rep[5].
edge = (val >> 4) & pmask;
1688 rep[6].
edge = (val << 2) & pmask;
1691 rep[6].
edge |= (val >> 14) & 0x3;
1692 rep[7].
edge = (val >> 8) & pmask;
1695 rep[
j].
freq = ath5k_eeprom_bin2freq(ee,
1696 rep[j].
freq, ctl_mode);
1705 ath5k_eeprom_read_spur_chans(
struct ath5k_hw *ah)
1749 err = ath5k_eeprom_init_header(ah);
1753 err = ath5k_eeprom_init_modes(ah);
1757 err = ath5k_eeprom_read_pcal_info(ah);
1761 err = ath5k_eeprom_read_ctl_info(ah);
1765 err = ath5k_eeprom_read_spur_chans(ah);
1778 ath5k_eeprom_free_pcal_info(ah, mode);