aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/eeprom.c')
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c255
1 files changed, 113 insertions, 142 deletions
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index ae316fec4a6a..392771f93759 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -28,45 +28,16 @@
28#include "debug.h" 28#include "debug.h"
29#include "base.h" 29#include "base.h"
30 30
31/*
32 * Read from eeprom
33 */
34static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
35{
36 u32 status, timeout;
37
38 /*
39 * Initialize EEPROM access
40 */
41 if (ah->ah_version == AR5K_AR5210) {
42 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
43 (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
44 } else {
45 ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
46 AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
47 AR5K_EEPROM_CMD_READ);
48 }
49
50 for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
51 status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
52 if (status & AR5K_EEPROM_STAT_RDDONE) {
53 if (status & AR5K_EEPROM_STAT_RDERR)
54 return -EIO;
55 *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
56 0xffff);
57 return 0;
58 }
59 udelay(15);
60 }
61 31
62 return -ETIMEDOUT; 32/******************\
63} 33* Helper functions *
34\******************/
64 35
65/* 36/*
66 * Translate binary channel representation in EEPROM to frequency 37 * Translate binary channel representation in EEPROM to frequency
67 */ 38 */
68static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, 39static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
69 unsigned int mode) 40 unsigned int mode)
70{ 41{
71 u16 val; 42 u16 val;
72 43
@@ -89,6 +60,11 @@ static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
89 return val; 60 return val;
90} 61}
91 62
63
64/*********\
65* Parsers *
66\*********/
67
92/* 68/*
93 * Initialize eeprom & capabilities structs 69 * Initialize eeprom & capabilities structs
94 */ 70 */
@@ -96,7 +72,6 @@ static int
96ath5k_eeprom_init_header(struct ath5k_hw *ah) 72ath5k_eeprom_init_header(struct ath5k_hw *ah)
97{ 73{
98 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 74 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
99 int ret;
100 u16 val; 75 u16 val;
101 u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX; 76 u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX;
102 77
@@ -198,7 +173,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
198 * 173 *
199 * XXX: Serdes values seem to be fixed so 174 * XXX: Serdes values seem to be fixed so
200 * no need to read them here, we write them 175 * no need to read them here, we write them
201 * during ath5k_hw_attach */ 176 * during ath5k_hw_init */
202 AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val); 177 AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val);
203 ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ? 178 ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ?
204 true : false; 179 true : false;
@@ -216,7 +191,7 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
216 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 191 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
217 u32 o = *offset; 192 u32 o = *offset;
218 u16 val; 193 u16 val;
219 int ret, i = 0; 194 int i = 0;
220 195
221 AR5K_EEPROM_READ(o++, val); 196 AR5K_EEPROM_READ(o++, val);
222 ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; 197 ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
@@ -276,7 +251,6 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
276 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 251 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
277 u32 o = *offset; 252 u32 o = *offset;
278 u16 val; 253 u16 val;
279 int ret;
280 254
281 ee->ee_n_piers[mode] = 0; 255 ee->ee_n_piers[mode] = 0;
282 AR5K_EEPROM_READ(o++, val); 256 AR5K_EEPROM_READ(o++, val);
@@ -539,7 +513,6 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
539 int o = *offset; 513 int o = *offset;
540 int i = 0; 514 int i = 0;
541 u8 freq1, freq2; 515 u8 freq1, freq2;
542 int ret;
543 u16 val; 516 u16 val;
544 517
545 ee->ee_n_piers[mode] = 0; 518 ee->ee_n_piers[mode] = 0;
@@ -575,7 +548,7 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
575{ 548{
576 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; 549 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
577 struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a; 550 struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a;
578 int i, ret; 551 int i;
579 u16 val; 552 u16 val;
580 u8 mask; 553 u8 mask;
581 554
@@ -647,6 +620,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
647 return 0; 620 return 0;
648} 621}
649 622
623
650/* 624/*
651 * Read power calibration for RF5111 chips 625 * Read power calibration for RF5111 chips
652 * 626 *
@@ -661,7 +635,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
661 * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC 635 * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
662 * steps that match with the power values we read from eeprom. On 636 * steps that match with the power values we read from eeprom. On
663 * older eeprom versions (< 3.2) these steps are equaly spaced at 637 * older eeprom versions (< 3.2) these steps are equaly spaced at
664 * 10% of the pcdac curve -until the curve reaches it's maximum- 638 * 10% of the pcdac curve -until the curve reaches its maximum-
665 * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) 639 * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
666 * these 11 steps are spaced in a different way. This function returns 640 * these 11 steps are spaced in a different way. This function returns
667 * the pcdac steps based on eeprom version and curve min/max so that we 641 * the pcdac steps based on eeprom version and curve min/max so that we
@@ -686,6 +660,51 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
686 vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; 660 vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
687} 661}
688 662
663static int
664ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
665{
666 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
667 struct ath5k_chan_pcal_info *chinfo;
668 u8 pier, pdg;
669
670 switch (mode) {
671 case AR5K_EEPROM_MODE_11A:
672 if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
673 return 0;
674 chinfo = ee->ee_pwr_cal_a;
675 break;
676 case AR5K_EEPROM_MODE_11B:
677 if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
678 return 0;
679 chinfo = ee->ee_pwr_cal_b;
680 break;
681 case AR5K_EEPROM_MODE_11G:
682 if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
683 return 0;
684 chinfo = ee->ee_pwr_cal_g;
685 break;
686 default:
687 return -EINVAL;
688 }
689
690 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
691 if (!chinfo[pier].pd_curves)
692 continue;
693
694 for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) {
695 struct ath5k_pdgain_info *pd =
696 &chinfo[pier].pd_curves[pdg];
697
698 kfree(pd->pd_step);
699 kfree(pd->pd_pwr);
700 }
701
702 kfree(chinfo[pier].pd_curves);
703 }
704
705 return 0;
706}
707
689/* Convert RF5111 specific data to generic raw data 708/* Convert RF5111 specific data to generic raw data
690 * used by interpolation code */ 709 * used by interpolation code */
691static int 710static int
@@ -710,7 +729,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
710 GFP_KERNEL); 729 GFP_KERNEL);
711 730
712 if (!chinfo[pier].pd_curves) 731 if (!chinfo[pier].pd_curves)
713 return -ENOMEM; 732 goto err_out;
714 733
715 /* Only one curve for RF5111 734 /* Only one curve for RF5111
716 * find out which one and place 735 * find out which one and place
@@ -734,12 +753,12 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
734 pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, 753 pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
735 sizeof(u8), GFP_KERNEL); 754 sizeof(u8), GFP_KERNEL);
736 if (!pd->pd_step) 755 if (!pd->pd_step)
737 return -ENOMEM; 756 goto err_out;
738 757
739 pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, 758 pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,
740 sizeof(s16), GFP_KERNEL); 759 sizeof(s16), GFP_KERNEL);
741 if (!pd->pd_pwr) 760 if (!pd->pd_pwr)
742 return -ENOMEM; 761 goto err_out;
743 762
744 /* Fill raw dataset 763 /* Fill raw dataset
745 * (convert power to 0.25dB units 764 * (convert power to 0.25dB units
@@ -760,6 +779,10 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
760 } 779 }
761 780
762 return 0; 781 return 0;
782
783err_out:
784 ath5k_eeprom_free_pcal_info(ah, mode);
785 return -ENOMEM;
763} 786}
764 787
765/* Parse EEPROM data */ 788/* Parse EEPROM data */
@@ -893,7 +916,7 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
893 GFP_KERNEL); 916 GFP_KERNEL);
894 917
895 if (!chinfo[pier].pd_curves) 918 if (!chinfo[pier].pd_curves)
896 return -ENOMEM; 919 goto err_out;
897 920
898 /* Fill pd_curves */ 921 /* Fill pd_curves */
899 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { 922 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
@@ -912,14 +935,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
912 sizeof(u8), GFP_KERNEL); 935 sizeof(u8), GFP_KERNEL);
913 936
914 if (!pd->pd_step) 937 if (!pd->pd_step)
915 return -ENOMEM; 938 goto err_out;
916 939
917 pd->pd_pwr = kcalloc(pd->pd_points, 940 pd->pd_pwr = kcalloc(pd->pd_points,
918 sizeof(s16), GFP_KERNEL); 941 sizeof(s16), GFP_KERNEL);
919 942
920 if (!pd->pd_pwr) 943 if (!pd->pd_pwr)
921 return -ENOMEM; 944 goto err_out;
922
923 945
924 /* Fill raw dataset 946 /* Fill raw dataset
925 * (all power levels are in 0.25dB units) */ 947 * (all power levels are in 0.25dB units) */
@@ -951,13 +973,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
951 sizeof(u8), GFP_KERNEL); 973 sizeof(u8), GFP_KERNEL);
952 974
953 if (!pd->pd_step) 975 if (!pd->pd_step)
954 return -ENOMEM; 976 goto err_out;
955 977
956 pd->pd_pwr = kcalloc(pd->pd_points, 978 pd->pd_pwr = kcalloc(pd->pd_points,
957 sizeof(s16), GFP_KERNEL); 979 sizeof(s16), GFP_KERNEL);
958 980
959 if (!pd->pd_pwr) 981 if (!pd->pd_pwr)
960 return -ENOMEM; 982 goto err_out;
961 983
962 /* Fill raw dataset 984 /* Fill raw dataset
963 * (all power levels are in 0.25dB units) */ 985 * (all power levels are in 0.25dB units) */
@@ -980,6 +1002,10 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
980 } 1002 }
981 1003
982 return 0; 1004 return 0;
1005
1006err_out:
1007 ath5k_eeprom_free_pcal_info(ah, mode);
1008 return -ENOMEM;
983} 1009}
984 1010
985/* Parse EEPROM data */ 1011/* Parse EEPROM data */
@@ -993,7 +1019,6 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
993 u32 offset; 1019 u32 offset;
994 u8 i, c; 1020 u8 i, c;
995 u16 val; 1021 u16 val;
996 int ret;
997 u8 pd_gains = 0; 1022 u8 pd_gains = 0;
998 1023
999 /* Count how many curves we have and 1024 /* Count how many curves we have and
@@ -1107,13 +1132,13 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
1107 * 1132 *
1108 * To recreate the curves we read here the points and interpolate 1133 * To recreate the curves we read here the points and interpolate
1109 * later. Note that in most cases only 2 (higher and lower) curves are 1134 * later. Note that in most cases only 2 (higher and lower) curves are
1110 * used (like RF5112) but vendors have the oportunity to include all 1135 * used (like RF5112) but vendors have the opportunity to include all
1111 * 4 curves on eeprom. The final curve (higher power) has an extra 1136 * 4 curves on eeprom. The final curve (higher power) has an extra
1112 * point for better accuracy like RF5112. 1137 * point for better accuracy like RF5112.
1113 */ 1138 */
1114 1139
1115/* For RF2413 power calibration data doesn't start on a fixed location and 1140/* For RF2413 power calibration data doesn't start on a fixed location and
1116 * if a mode is not supported, it's section is missing -not zeroed-. 1141 * if a mode is not supported, its section is missing -not zeroed-.
1117 * So we need to calculate the starting offset for each section by using 1142 * So we need to calculate the starting offset for each section by using
1118 * these two functions */ 1143 * these two functions */
1119 1144
@@ -1183,7 +1208,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
1183 GFP_KERNEL); 1208 GFP_KERNEL);
1184 1209
1185 if (!chinfo[pier].pd_curves) 1210 if (!chinfo[pier].pd_curves)
1186 return -ENOMEM; 1211 goto err_out;
1187 1212
1188 /* Fill pd_curves */ 1213 /* Fill pd_curves */
1189 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { 1214 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
@@ -1204,13 +1229,13 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
1204 sizeof(u8), GFP_KERNEL); 1229 sizeof(u8), GFP_KERNEL);
1205 1230
1206 if (!pd->pd_step) 1231 if (!pd->pd_step)
1207 return -ENOMEM; 1232 goto err_out;
1208 1233
1209 pd->pd_pwr = kcalloc(pd->pd_points, 1234 pd->pd_pwr = kcalloc(pd->pd_points,
1210 sizeof(s16), GFP_KERNEL); 1235 sizeof(s16), GFP_KERNEL);
1211 1236
1212 if (!pd->pd_pwr) 1237 if (!pd->pd_pwr)
1213 return -ENOMEM; 1238 goto err_out;
1214 1239
1215 /* Fill raw dataset 1240 /* Fill raw dataset
1216 * convert all pwr levels to 1241 * convert all pwr levels to
@@ -1240,6 +1265,10 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
1240 } 1265 }
1241 1266
1242 return 0; 1267 return 0;
1268
1269err_out:
1270 ath5k_eeprom_free_pcal_info(ah, mode);
1271 return -ENOMEM;
1243} 1272}
1244 1273
1245/* Parse EEPROM data */ 1274/* Parse EEPROM data */
@@ -1251,7 +1280,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
1251 struct ath5k_chan_pcal_info *chinfo; 1280 struct ath5k_chan_pcal_info *chinfo;
1252 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; 1281 u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
1253 u32 offset; 1282 u32 offset;
1254 int idx, i, ret; 1283 int idx, i;
1255 u16 val; 1284 u16 val;
1256 u8 pd_gains = 0; 1285 u8 pd_gains = 0;
1257 1286
@@ -1329,7 +1358,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
1329 /* 1358 /*
1330 * Pd gain 0 is not the last pd gain 1359 * Pd gain 0 is not the last pd gain
1331 * so it only has 2 pd points. 1360 * so it only has 2 pd points.
1332 * Continue wih pd gain 1. 1361 * Continue with pd gain 1.
1333 */ 1362 */
1334 pcinfo->pwr_i[1] = (val >> 10) & 0x1f; 1363 pcinfo->pwr_i[1] = (val >> 10) & 0x1f;
1335 1364
@@ -1442,7 +1471,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
1442 u8 *rate_target_pwr_num; 1471 u8 *rate_target_pwr_num;
1443 u32 offset; 1472 u32 offset;
1444 u16 val; 1473 u16 val;
1445 int ret, i; 1474 int i;
1446 1475
1447 offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1); 1476 offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1);
1448 rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode]; 1477 rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode];
@@ -1514,6 +1543,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
1514 return 0; 1543 return 0;
1515} 1544}
1516 1545
1546
1517/* 1547/*
1518 * Read per channel calibration info from EEPROM 1548 * Read per channel calibration info from EEPROM
1519 * 1549 *
@@ -1560,62 +1590,6 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
1560 return 0; 1590 return 0;
1561} 1591}
1562 1592
1563static int
1564ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
1565{
1566 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1567 struct ath5k_chan_pcal_info *chinfo;
1568 u8 pier, pdg;
1569
1570 switch (mode) {
1571 case AR5K_EEPROM_MODE_11A:
1572 if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
1573 return 0;
1574 chinfo = ee->ee_pwr_cal_a;
1575 break;
1576 case AR5K_EEPROM_MODE_11B:
1577 if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
1578 return 0;
1579 chinfo = ee->ee_pwr_cal_b;
1580 break;
1581 case AR5K_EEPROM_MODE_11G:
1582 if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
1583 return 0;
1584 chinfo = ee->ee_pwr_cal_g;
1585 break;
1586 default:
1587 return -EINVAL;
1588 }
1589
1590 for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
1591 if (!chinfo[pier].pd_curves)
1592 continue;
1593
1594 for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
1595 struct ath5k_pdgain_info *pd =
1596 &chinfo[pier].pd_curves[pdg];
1597
1598 if (pd != NULL) {
1599 kfree(pd->pd_step);
1600 kfree(pd->pd_pwr);
1601 }
1602 }
1603
1604 kfree(chinfo[pier].pd_curves);
1605 }
1606
1607 return 0;
1608}
1609
1610void
1611ath5k_eeprom_detach(struct ath5k_hw *ah)
1612{
1613 u8 mode;
1614
1615 for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
1616 ath5k_eeprom_free_pcal_info(ah, mode);
1617}
1618
1619/* Read conformance test limits used for regulatory control */ 1593/* Read conformance test limits used for regulatory control */
1620static int 1594static int
1621ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) 1595ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
@@ -1624,7 +1598,7 @@ ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
1624 struct ath5k_edge_power *rep; 1598 struct ath5k_edge_power *rep;
1625 unsigned int fmask, pmask; 1599 unsigned int fmask, pmask;
1626 unsigned int ctl_mode; 1600 unsigned int ctl_mode;
1627 int ret, i, j; 1601 int i, j;
1628 u32 offset; 1602 u32 offset;
1629 u16 val; 1603 u16 val;
1630 1604
@@ -1756,6 +1730,11 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah)
1756 return ret; 1730 return ret;
1757} 1731}
1758 1732
1733
1734/***********************\
1735* Init/Detach functions *
1736\***********************/
1737
1759/* 1738/*
1760 * Initialize eeprom data structure 1739 * Initialize eeprom data structure
1761 */ 1740 */
@@ -1787,35 +1766,27 @@ ath5k_eeprom_init(struct ath5k_hw *ah)
1787 return 0; 1766 return 0;
1788} 1767}
1789 1768
1790/* 1769void
1791 * Read the MAC address from eeprom 1770ath5k_eeprom_detach(struct ath5k_hw *ah)
1792 */
1793int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
1794{ 1771{
1795 u8 mac_d[ETH_ALEN] = {}; 1772 u8 mode;
1796 u32 total, offset;
1797 u16 data;
1798 int octet, ret;
1799
1800 ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
1801 if (ret)
1802 return ret;
1803 1773
1804 for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { 1774 for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
1805 ret = ath5k_hw_eeprom_read(ah, offset, &data); 1775 ath5k_eeprom_free_pcal_info(ah, mode);
1806 if (ret) 1776}
1807 return ret;
1808 1777
1809 total += data; 1778int
1810 mac_d[octet + 1] = data & 0xff; 1779ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel)
1811 mac_d[octet] = data >> 8; 1780{
1812 octet += 2; 1781 switch (channel->hw_value & CHANNEL_MODES) {
1782 case CHANNEL_A:
1783 case CHANNEL_XR:
1784 return AR5K_EEPROM_MODE_11A;
1785 case CHANNEL_G:
1786 return AR5K_EEPROM_MODE_11G;
1787 case CHANNEL_B:
1788 return AR5K_EEPROM_MODE_11B;
1789 default:
1790 return -1;
1813 } 1791 }
1814
1815 if (!total || total == 3 * 0xffff)
1816 return -EINVAL;
1817
1818 memcpy(mac, mac_d, ETH_ALEN);
1819
1820 return 0;
1821} 1792}