aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k
diff options
context:
space:
mode:
authorNick Kossifidis <mick@madwifi.org>2008-12-20 21:47:39 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 15:58:42 -0500
commit0ea9c00c9d4e6309637a2defe18d26b6cda0fdc0 (patch)
treeeb8477b48b95d95f47288bcdc1debf6e382059b9 /drivers/net/wireless/ath5k
parent754be3098b22d1bea9620b40fe2f9f2286c55101 (diff)
ath5k: Update EEPROM code
*Read misc2...6 values from eeprom since we want to use them (fixes wrong power calibration info offset on RF2413+ chips) *Initialize num_piers to 0 for RF2413 chips (note that we read 2GHz frequency piers while reading mode sections, we have to ignore them -usualy they are 0xff anyway but during my tests i got a 1 on b mode with no data- and use the newer eemap. *Add some more comments (please forgive my poor English ;-( ) and some minor code cleanup *Tested on 2425 and 2112 and has the same data with ath_info (i wrote some debug code on debug.c to print everything like ath_info but i haven't tested it yet on 5111 and it's full of > 80 col lines, if anyone wants to play with it let me know). Signed-Off-by: Nick Kossifidis <mickflemm@gmail.com> Acked-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath5k')
-rw-r--r--drivers/net/wireless/ath5k/eeprom.c143
1 files changed, 116 insertions, 27 deletions
diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c
index 1cb7edfae625..079e9ca168d5 100644
--- a/drivers/net/wireless/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath5k/eeprom.c
@@ -137,6 +137,18 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
137 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { 137 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
138 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); 138 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
139 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); 139 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
140
141 /* XXX: Don't know which versions include these two */
142 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2);
143
144 if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3)
145 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3);
146
147 if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) {
148 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4);
149 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5);
150 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6);
151 }
140 } 152 }
141 153
142 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { 154 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
@@ -213,7 +225,8 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
213} 225}
214 226
215/* 227/*
216 * Read supported modes from eeprom 228 * Read supported modes and some mode-specific calibration data
229 * from eeprom
217 */ 230 */
218static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, 231static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
219 unsigned int mode) 232 unsigned int mode)
@@ -315,6 +328,9 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
315 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0) 328 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0)
316 goto done; 329 goto done;
317 330
331 /* Note: >= v5 have bg freq piers on another location
332 * so these freq piers are ignored for >= v5 (should be 0xff
333 * anyway) */
318 switch(mode) { 334 switch(mode) {
319 case AR5K_EEPROM_MODE_11A: 335 case AR5K_EEPROM_MODE_11A:
320 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1) 336 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
@@ -442,7 +458,7 @@ ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
442 return 0; 458 return 0;
443} 459}
444 460
445 461/* Read mode-specific data (except power calibration data) */
446static int 462static int
447ath5k_eeprom_init_modes(struct ath5k_hw *ah) 463ath5k_eeprom_init_modes(struct ath5k_hw *ah)
448{ 464{
@@ -488,6 +504,16 @@ ath5k_eeprom_init_modes(struct ath5k_hw *ah)
488 return 0; 504 return 0;
489} 505}
490 506
507/* Used to match PCDAC steps with power values on RF5111 chips
508 * (eeprom versions < 4). For RF5111 we have 10 pre-defined PCDAC
509 * steps that match with the power values we read from eeprom. On
510 * older eeprom versions (< 3.2) these steps are equaly spaced at
511 * 10% of the pcdac curve -until the curve reaches it's maximum-
512 * (10 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
513 * these 10 steps are spaced in a different way. This function returns
514 * the pcdac steps based on eeprom version and curve min/max so that we
515 * can have pcdac/pwr points.
516 */
491static inline void 517static inline void
492ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) 518ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
493{ 519{
@@ -507,37 +533,48 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
507 *vp++ = (ip[i] * max + (100 - ip[i]) * min) / 100; 533 *vp++ = (ip[i] * max + (100 - ip[i]) * min) / 100;
508} 534}
509 535
536/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff
537 * frequency mask) */
510static inline int 538static inline int
511ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, 539ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
512 struct ath5k_chan_pcal_info *pc, u8 *count) 540 struct ath5k_chan_pcal_info *pc, unsigned int mode)
513{ 541{
542 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
514 int o = *offset; 543 int o = *offset;
515 int i = 0; 544 int i = 0;
516 u8 f1, f2; 545 u8 freq1, freq2;
517 int ret; 546 int ret;
518 u16 val; 547 u16 val;
519 548
520 while(i < max) { 549 while(i < max) {
521 AR5K_EEPROM_READ(o++, val); 550 AR5K_EEPROM_READ(o++, val);
522 551
523 f1 = (val >> 8) & 0xff; 552 freq1 = (val >> 8) & 0xff;
524 f2 = val & 0xff; 553 freq2 = val & 0xff;
525 554
526 if (f1) 555 if (freq1) {
527 pc[i++].freq = f1; 556 pc[i++].freq = ath5k_eeprom_bin2freq(ee,
557 freq1, mode);
558 ee->ee_n_piers[mode]++;
559 }
528 560
529 if (f2) 561 if (freq2) {
530 pc[i++].freq = f2; 562 pc[i++].freq = ath5k_eeprom_bin2freq(ee,
563 freq2, mode);
564 ee->ee_n_piers[mode]++;
565 }
531 566
532 if (!f1 || !f2) 567 if (!freq1 || !freq2)
533 break; 568 break;
534 } 569 }
570
571 /* return new offset */
535 *offset = o; 572 *offset = o;
536 *count = i;
537 573
538 return 0; 574 return 0;
539} 575}
540 576
577/* Read frequency piers for 802.11a */
541static int 578static int
542ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) 579ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
543{ 580{
@@ -550,7 +587,7 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
550 if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { 587 if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
551 ath5k_eeprom_read_freq_list(ah, &offset, 588 ath5k_eeprom_read_freq_list(ah, &offset,
552 AR5K_EEPROM_N_5GHZ_CHAN, pcal, 589 AR5K_EEPROM_N_5GHZ_CHAN, pcal,
553 &ee->ee_n_piers[AR5K_EEPROM_MODE_11A]); 590 AR5K_EEPROM_MODE_11A);
554 } else { 591 } else {
555 mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version); 592 mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version);
556 593
@@ -577,23 +614,25 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
577 614
578 AR5K_EEPROM_READ(offset++, val); 615 AR5K_EEPROM_READ(offset++, val);
579 pcal[9].freq |= (val >> 10) & 0x3f; 616 pcal[9].freq |= (val >> 10) & 0x3f;
617
618 /* Fixed number of piers */
580 ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10; 619 ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10;
581 }
582 620
583 for(i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i += 1) { 621 for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) {
584 pcal[i].freq = ath5k_eeprom_bin2freq(ee, 622 pcal[i].freq = ath5k_eeprom_bin2freq(ee,
585 pcal[i].freq, AR5K_EEPROM_MODE_11A); 623 pcal[i].freq, AR5K_EEPROM_MODE_11A);
624 }
586 } 625 }
587 626
588 return 0; 627 return 0;
589} 628}
590 629
630/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */
591static inline int 631static inline int
592ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) 632ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
593{ 633{
594 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 634 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
595 struct ath5k_chan_pcal_info *pcal; 635 struct ath5k_chan_pcal_info *pcal;
596 int i;
597 636
598 switch(mode) { 637 switch(mode) {
599 case AR5K_EEPROM_MODE_11B: 638 case AR5K_EEPROM_MODE_11B:
@@ -608,16 +647,18 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
608 647
609 ath5k_eeprom_read_freq_list(ah, &offset, 648 ath5k_eeprom_read_freq_list(ah, &offset,
610 AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal, 649 AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal,
611 &ee->ee_n_piers[mode]); 650 mode);
612 for(i = 0; i < AR5K_EEPROM_N_2GHZ_CHAN_2413; i += 1) {
613 pcal[i].freq = ath5k_eeprom_bin2freq(ee,
614 pcal[i].freq, mode);
615 }
616 651
617 return 0; 652 return 0;
618} 653}
619 654
620 655/* Read power calibration for RF5111 chips
656 * For RF5111 we have an XPD -eXternal Power Detector- curve
657 * for each calibrated channel. Each curve has PCDAC steps on
658 * x axis and power on y axis and looks like a logarithmic
659 * function. To recreate the curve and pass the power values
660 * on the pcdac table, we read 10 points here and interpolate later.
661 */
621static int 662static int
622ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) 663ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
623{ 664{
@@ -714,6 +755,17 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
714 return 0; 755 return 0;
715} 756}
716 757
758/* Read power calibration for RF5112 chips
759 * For RF5112 we have 4 XPD -eXternal Power Detector- curves
760 * for each calibrated channel on 0, -6, -12 and -18dbm but we only
761 * use the higher (3) and the lower (0) curves. Each curve has PCDAC
762 * steps on x axis and power on y axis and looks like a linear
763 * function. To recreate the curve and pass the power values
764 * on the pcdac table, we read 4 points for xpd 0 and 3 points
765 * for xpd 3 here and interpolate later.
766 *
767 * Note: Many vendors just use xpd 0 so xpd 3 is zeroed.
768 */
717static int 769static int
718ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) 770ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
719{ 771{
@@ -790,7 +842,7 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
790 842
791 /* PCDAC steps 843 /* PCDAC steps
792 * corresponding to the above power 844 * corresponding to the above power
793 * measurements (static) */ 845 * measurements (fixed) */
794 chan_pcal_info->pcdac_x3[0] = 20; 846 chan_pcal_info->pcdac_x3[0] = 20;
795 chan_pcal_info->pcdac_x3[1] = 35; 847 chan_pcal_info->pcdac_x3[1] = 35;
796 chan_pcal_info->pcdac_x3[2] = 63; 848 chan_pcal_info->pcdac_x3[2] = 63;
@@ -814,6 +866,13 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
814 return 0; 866 return 0;
815} 867}
816 868
869/* For RF2413 power calibration data doesn't start on a fixed location and
870 * if a mode is not supported, it's section is missing -not zeroed-.
871 * So we need to calculate the starting offset for each section by using
872 * these two functions */
873
874/* Return the size of each section based on the mode and the number of pd
875 * gains available (maximum 4). */
817static inline unsigned int 876static inline unsigned int
818ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) 877ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
819{ 878{
@@ -826,6 +885,8 @@ ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
826 return sz; 885 return sz;
827} 886}
828 887
888/* Return the starting offset for a section based on the modes supported
889 * and each section's size. */
829static unsigned int 890static unsigned int
830ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) 891ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
831{ 892{
@@ -834,11 +895,13 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
834 switch(mode) { 895 switch(mode) {
835 case AR5K_EEPROM_MODE_11G: 896 case AR5K_EEPROM_MODE_11G:
836 if (AR5K_EEPROM_HDR_11B(ee->ee_header)) 897 if (AR5K_EEPROM_HDR_11B(ee->ee_header))
837 offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) + 2; 898 offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) +
899 AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
838 /* fall through */ 900 /* fall through */
839 case AR5K_EEPROM_MODE_11B: 901 case AR5K_EEPROM_MODE_11B:
840 if (AR5K_EEPROM_HDR_11A(ee->ee_header)) 902 if (AR5K_EEPROM_HDR_11A(ee->ee_header))
841 offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) + 5; 903 offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) +
904 AR5K_EEPROM_N_5GHZ_CHAN / 2;
842 /* fall through */ 905 /* fall through */
843 case AR5K_EEPROM_MODE_11A: 906 case AR5K_EEPROM_MODE_11A:
844 break; 907 break;
@@ -849,6 +912,17 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
849 return offset; 912 return offset;
850} 913}
851 914
915/* Read power calibration for RF2413 chips
916 * For RF2413 we have a PDDAC table (Power Detector) instead
917 * of a PCDAC and 4 pd gain curves for each calibrated channel.
918 * Each curve has PDDAC steps on x axis and power on y axis and
919 * looks like an exponential function. To recreate the curves
920 * we read here the points and interpolate later. Note that
921 * in most cases only higher and lower curves are used (like
922 * RF5112) but vendors have the oportunity to include all 4
923 * curves on eeprom. The final curve (higher power) has an extra
924 * point for better accuracy like RF5112.
925 */
852static int 926static int
853ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) 927ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
854{ 928{
@@ -868,6 +942,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
868 ee->ee_pd_gains[mode] = pd_gains; 942 ee->ee_pd_gains[mode] = pd_gains;
869 943
870 offset = ath5k_cal_data_offset_2413(ee, mode); 944 offset = ath5k_cal_data_offset_2413(ee, mode);
945 ee->ee_n_piers[mode] = 0;
871 switch (mode) { 946 switch (mode) {
872 case AR5K_EEPROM_MODE_11A: 947 case AR5K_EEPROM_MODE_11A:
873 if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) 948 if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
@@ -1163,6 +1238,20 @@ static int ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned
1163 return 0; 1238 return 0;
1164} 1239}
1165 1240
1241/*
1242 * Read per channel calibration info from EEPROM
1243 *
1244 * This info is used to calibrate the baseband power table. Imagine
1245 * that for each channel there is a power curve that's hw specific
1246 * (depends on amplifier etc) and we try to "correct" this curve using
1247 * offests we pass on to phy chip (baseband -> before amplifier) so that
1248 * it can use accurate power values when setting tx power (takes amplifier's
1249 * performance on each channel into account).
1250 *
1251 * EEPROM provides us with the offsets for some pre-calibrated channels
1252 * and we have to interpolate to create the full table for these channels and
1253 * also the table for any channel.
1254 */
1166static int 1255static int
1167ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) 1256ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
1168{ 1257{
@@ -1193,7 +1282,7 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
1193 return 0; 1282 return 0;
1194} 1283}
1195 1284
1196/* Read conformance test limits */ 1285/* Read conformance test limits used for regulatory control */
1197static int 1286static int
1198ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) 1287ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
1199{ 1288{