2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 /*************************************\
20 * EEPROM access functions and helpers *
21 \*************************************/
31 static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
35 ATH5K_TRACE(ah->ah_sc);
37 * Initialize EEPROM access
39 if (ah->ah_version == AR5K_AR5210) {
40 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
41 (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
43 ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
44 AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
45 AR5K_EEPROM_CMD_READ);
48 for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
49 status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
50 if (status & AR5K_EEPROM_STAT_RDDONE) {
51 if (status & AR5K_EEPROM_STAT_RDERR)
53 *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
64 * Translate binary channel representation in EEPROM to frequency
66 static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin,
71 if (bin == AR5K_EEPROM_CHANNEL_DIS)
74 if (mode == AR5K_EEPROM_MODE_11A) {
75 if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
76 val = (5 * bin) + 4800;
78 val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
81 if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
91 * Read antenna infos from eeprom
93 static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
96 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
101 AR5K_EEPROM_READ(o++, val);
102 ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
103 ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f;
104 ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
106 AR5K_EEPROM_READ(o++, val);
107 ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
108 ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
109 ee->ee_ant_control[mode][i++] = val & 0x3f;
111 AR5K_EEPROM_READ(o++, val);
112 ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
113 ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
114 ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
116 AR5K_EEPROM_READ(o++, val);
117 ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
118 ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
119 ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
120 ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
122 AR5K_EEPROM_READ(o++, val);
123 ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
124 ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
125 ee->ee_ant_control[mode][i++] = val & 0x3f;
127 /* Get antenna modes */
128 ah->ah_antenna[mode][0] =
129 (ee->ee_ant_control[mode][0] << 4) | 0x1;
130 ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
131 ee->ee_ant_control[mode][1] |
132 (ee->ee_ant_control[mode][2] << 6) |
133 (ee->ee_ant_control[mode][3] << 12) |
134 (ee->ee_ant_control[mode][4] << 18) |
135 (ee->ee_ant_control[mode][5] << 24);
136 ah->ah_antenna[mode][AR5K_ANT_FIXED_B] =
137 ee->ee_ant_control[mode][6] |
138 (ee->ee_ant_control[mode][7] << 6) |
139 (ee->ee_ant_control[mode][8] << 12) |
140 (ee->ee_ant_control[mode][9] << 18) |
141 (ee->ee_ant_control[mode][10] << 24);
143 /* return new offset */
150 * Read supported modes from eeprom
152 static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
155 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
160 AR5K_EEPROM_READ(o++, val);
161 ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
162 ee->ee_thr_62[mode] = val & 0xff;
164 if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
165 ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
167 AR5K_EEPROM_READ(o++, val);
168 ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
169 ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
171 AR5K_EEPROM_READ(o++, val);
172 ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
174 if ((val & 0xff) & 0x80)
175 ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
177 ee->ee_noise_floor_thr[mode] = val & 0xff;
179 if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
180 ee->ee_noise_floor_thr[mode] =
181 mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
183 AR5K_EEPROM_READ(o++, val);
184 ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
185 ee->ee_x_gain[mode] = (val >> 1) & 0xf;
186 ee->ee_xpd[mode] = val & 0x1;
188 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
189 ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
191 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
192 AR5K_EEPROM_READ(o++, val);
193 ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
195 if (mode == AR5K_EEPROM_MODE_11A)
196 ee->ee_xr_power[mode] = val & 0x3f;
198 ee->ee_ob[mode][0] = val & 0x7;
199 ee->ee_db[mode][0] = (val >> 3) & 0x7;
203 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
204 ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
205 ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
207 ee->ee_i_gain[mode] = (val >> 13) & 0x7;
209 AR5K_EEPROM_READ(o++, val);
210 ee->ee_i_gain[mode] |= (val << 3) & 0x38;
212 if (mode == AR5K_EEPROM_MODE_11G)
213 ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
216 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
217 mode == AR5K_EEPROM_MODE_11A) {
218 ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
219 ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
222 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
223 mode == AR5K_EEPROM_MODE_11G)
224 ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
226 /* return new offset */
233 * Initialize eeprom & capabilities structs
235 int ath5k_eeprom_init(struct ath5k_hw *ah)
237 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
238 unsigned int mode, i;
243 /* Initial TX thermal adjustment values */
245 ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
246 ee->ee_gain_select = 1;
249 * Read values from EEPROM and store them in the capability structure
251 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
252 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
253 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
254 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
255 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
257 /* Return if we have an old EEPROM */
258 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
263 * Validate the checksum of the EEPROM date. There are some
264 * devices with invalid EEPROMs.
266 for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
267 AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
270 if (cksum != AR5K_EEPROM_INFO_CKSUM) {
271 ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
276 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
279 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
280 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
281 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
284 if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
285 AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
286 ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
287 ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
289 AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
290 ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
291 ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
295 * Get conformance test limit values
297 offset = AR5K_EEPROM_CTL(ah->ah_ee_version);
298 ee->ee_ctls = AR5K_EEPROM_N_CTLS(ah->ah_ee_version);
300 for (i = 0; i < ee->ee_ctls; i++) {
301 AR5K_EEPROM_READ(offset++, val);
302 ee->ee_ctl[i] = (val >> 8) & 0xff;
303 ee->ee_ctl[i + 1] = val & 0xff;
307 * Get values for 802.11a (5GHz)
309 mode = AR5K_EEPROM_MODE_11A;
311 ee->ee_turbo_max_power[mode] =
312 AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
314 offset = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
316 ret = ath5k_eeprom_read_ants(ah, &offset, mode);
320 AR5K_EEPROM_READ(offset++, val);
321 ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
322 ee->ee_ob[mode][3] = (val >> 5) & 0x7;
323 ee->ee_db[mode][3] = (val >> 2) & 0x7;
324 ee->ee_ob[mode][2] = (val << 1) & 0x7;
326 AR5K_EEPROM_READ(offset++, val);
327 ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
328 ee->ee_db[mode][2] = (val >> 12) & 0x7;
329 ee->ee_ob[mode][1] = (val >> 9) & 0x7;
330 ee->ee_db[mode][1] = (val >> 6) & 0x7;
331 ee->ee_ob[mode][0] = (val >> 3) & 0x7;
332 ee->ee_db[mode][0] = val & 0x7;
334 ret = ath5k_eeprom_read_modes(ah, &offset, mode);
338 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
339 AR5K_EEPROM_READ(offset++, val);
340 ee->ee_margin_tx_rx[mode] = val & 0x3f;
344 * Get values for 802.11b (2.4GHz)
346 mode = AR5K_EEPROM_MODE_11B;
347 offset = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
349 ret = ath5k_eeprom_read_ants(ah, &offset, mode);
353 AR5K_EEPROM_READ(offset++, val);
354 ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
355 ee->ee_ob[mode][1] = (val >> 4) & 0x7;
356 ee->ee_db[mode][1] = val & 0x7;
358 ret = ath5k_eeprom_read_modes(ah, &offset, mode);
362 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
363 AR5K_EEPROM_READ(offset++, val);
364 ee->ee_cal_pier[mode][0] =
365 ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
366 ee->ee_cal_pier[mode][1] =
367 ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
369 AR5K_EEPROM_READ(offset++, val);
370 ee->ee_cal_pier[mode][2] =
371 ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
374 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
375 ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
378 * Get values for 802.11g (2.4GHz)
380 mode = AR5K_EEPROM_MODE_11G;
381 offset = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
383 ret = ath5k_eeprom_read_ants(ah, &offset, mode);
387 AR5K_EEPROM_READ(offset++, val);
388 ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
389 ee->ee_ob[mode][1] = (val >> 4) & 0x7;
390 ee->ee_db[mode][1] = val & 0x7;
392 ret = ath5k_eeprom_read_modes(ah, &offset, mode);
396 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
397 AR5K_EEPROM_READ(offset++, val);
398 ee->ee_cal_pier[mode][0] =
399 ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
400 ee->ee_cal_pier[mode][1] =
401 ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
403 AR5K_EEPROM_READ(offset++, val);
404 ee->ee_turbo_max_power[mode] = val & 0x7f;
405 ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
407 AR5K_EEPROM_READ(offset++, val);
408 ee->ee_cal_pier[mode][2] =
409 ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
411 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
412 ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
414 AR5K_EEPROM_READ(offset++, val);
415 ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
416 ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
418 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
419 AR5K_EEPROM_READ(offset++, val);
420 ee->ee_cck_ofdm_gain_delta = val & 0xff;
425 * Read 5GHz EEPROM channels
432 * Read the MAC address from eeprom
434 int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
441 memset(mac, 0, ETH_ALEN);
442 memset(mac_d, 0, ETH_ALEN);
444 ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
448 for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
449 ret = ath5k_hw_eeprom_read(ah, offset, &data);
454 mac_d[octet + 1] = data & 0xff;
455 mac_d[octet] = data >> 8;
459 memcpy(mac, mac_d, ETH_ALEN);
461 if (!total || total == 3 * 0xffff)