2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
4 * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
6 * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
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.
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.
24 /*************************************\
25 * EEPROM access functions and helpers *
26 \*************************************/
38 static int ath5k_hw_eeprom_read(struct ath5k_hw
*ah
, u32 offset
, u16
*data
)
43 * Initialize EEPROM access
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
));
49 ath5k_hw_reg_write(ah
, offset
, AR5K_EEPROM_BASE
);
50 AR5K_REG_ENABLE_BITS(ah
, AR5K_EEPROM_CMD
,
51 AR5K_EEPROM_CMD_READ
);
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
)
59 *data
= (u16
)(ath5k_hw_reg_read(ah
, AR5K_EEPROM_DATA
) &
70 * Translate binary channel representation in EEPROM to frequency
72 static u16
ath5k_eeprom_bin2freq(struct ath5k_eeprom_info
*ee
, u16 bin
,
77 if (bin
== AR5K_EEPROM_CHANNEL_DIS
)
80 if (mode
== AR5K_EEPROM_MODE_11A
) {
81 if (ee
->ee_version
> AR5K_EEPROM_VERSION_3_2
)
82 val
= (5 * bin
) + 4800;
84 val
= bin
> 62 ? (10 * 62) + (5 * (bin
- 62)) + 5100 :
87 if (ee
->ee_version
> AR5K_EEPROM_VERSION_3_2
)
97 * Initialize eeprom & capabilities structs
100 ath5k_eeprom_init_header(struct ath5k_hw
*ah
)
102 struct ath5k_eeprom_info
*ee
= &ah
->ah_capabilities
.cap_eeprom
;
107 * Read values from EEPROM and store them in the capability structure
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
);
115 /* Return if we have an old EEPROM */
116 if (ah
->ah_ee_version
< AR5K_EEPROM_VERSION_3_0
)
119 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah
->ah_ee_version
),
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
);
126 /* XXX: Don't know which versions include these two */
127 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2
, ee_misc2
);
129 if (ee
->ee_version
>= AR5K_EEPROM_VERSION_4_3
)
130 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3
, ee_misc3
);
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
);
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;
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;
149 AR5K_EEPROM_READ(AR5K_EEPROM_IS_HB63
, val
);
151 if ((ah
->ah_mac_version
== (AR5K_SREV_AR2425
>> 4)) && val
)
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;
165 * Read antenna infos from eeprom
167 static int ath5k_eeprom_read_ants(struct ath5k_hw
*ah
, u32
*offset
,
170 struct ath5k_eeprom_info
*ee
= &ah
->ah_capabilities
.cap_eeprom
;
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;
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;
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;
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;
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;
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);
217 /* return new offset */
224 * Read supported modes and some mode-specific calibration data
227 static int ath5k_eeprom_read_modes(struct ath5k_hw
*ah
, u32
*offset
,
230 struct ath5k_eeprom_info
*ee
= &ah
->ah_capabilities
.cap_eeprom
;
235 ee
->ee_n_piers
[mode
] = 0;
236 AR5K_EEPROM_READ(o
++, val
);
237 ee
->ee_adc_desired_size
[mode
] = (s8
)((val
>> 8) & 0xff);
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;
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;
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;
259 AR5K_EEPROM_READ(o
++, val
);
260 ee
->ee_tx_end2xlna_enable
[mode
] = (val
>> 8) & 0xff;
261 ee
->ee_thr_62
[mode
] = val
& 0xff;
263 if (ah
->ah_ee_version
<= AR5K_EEPROM_VERSION_3_2
)
264 ee
->ee_thr_62
[mode
] = mode
== AR5K_EEPROM_MODE_11A
? 15 : 28;
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;
270 AR5K_EEPROM_READ(o
++, val
);
271 ee
->ee_pga_desired_size
[mode
] = (val
>> 8) & 0xff;
273 if ((val
& 0xff) & 0x80)
274 ee
->ee_noise_floor_thr
[mode
] = -((((val
& 0xff) ^ 0xff)) + 1);
276 ee
->ee_noise_floor_thr
[mode
] = val
& 0xff;
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;
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;
287 if (ah
->ah_ee_version
>= AR5K_EEPROM_VERSION_4_0
)
288 ee
->ee_fixed_bias
[mode
] = (val
>> 13) & 0x1;
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;
294 if (mode
== AR5K_EEPROM_MODE_11A
)
295 ee
->ee_xr_power
[mode
] = val
& 0x3f;
297 ee
->ee_ob
[mode
][0] = val
& 0x7;
298 ee
->ee_db
[mode
][0] = (val
>> 3) & 0x7;
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
;
306 ee
->ee_i_gain
[mode
] = (val
>> 13) & 0x7;
308 AR5K_EEPROM_READ(o
++, val
);
309 ee
->ee_i_gain
[mode
] |= (val
<< 3) & 0x38;
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;
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;
324 if (ah
->ah_ee_version
< AR5K_EEPROM_VERSION_4_0
)
327 /* Note: >= v5 have bg freq piers on another location
328 * so these freq piers are ignored for >= v5 (should be 0xff
331 case AR5K_EEPROM_MODE_11A
:
332 if (ah
->ah_ee_version
< AR5K_EEPROM_VERSION_4_1
)
335 AR5K_EEPROM_READ(o
++, val
);
336 ee
->ee_margin_tx_rx
[mode
] = val
& 0x3f;
338 case AR5K_EEPROM_MODE_11B
:
339 AR5K_EEPROM_READ(o
++, val
);
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
]++;
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
]++;
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
]++;
357 if (ah
->ah_ee_version
>= AR5K_EEPROM_VERSION_4_1
)
358 ee
->ee_margin_tx_rx
[mode
] = (val
>> 8) & 0x3f;
360 case AR5K_EEPROM_MODE_11G
:
361 AR5K_EEPROM_READ(o
++, val
);
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
]++;
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
]++;
373 AR5K_EEPROM_READ(o
++, val
);
374 ee
->ee_turbo_max_power
[mode
] = val
& 0x7f;
375 ee
->ee_xr_power
[mode
] = (val
>> 7) & 0x3f;
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
]++;
383 if (ah
->ah_ee_version
>= AR5K_EEPROM_VERSION_4_1
)
384 ee
->ee_margin_tx_rx
[mode
] = (val
>> 8) & 0x3f;
386 AR5K_EEPROM_READ(o
++, val
);
387 ee
->ee_i_cal
[mode
] = (val
>> 8) & 0x3f;
388 ee
->ee_q_cal
[mode
] = (val
>> 3) & 0x1f;
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;
398 /* return new offset */
405 * Read turbo mode information on newer EEPROM versions
408 ath5k_eeprom_read_turbo_modes(struct ath5k_hw
*ah
,
409 u32
*offset
, unsigned int mode
)
411 struct ath5k_eeprom_info
*ee
= &ah
->ah_capabilities
.cap_eeprom
;
416 if (ee
->ee_version
< AR5K_EEPROM_VERSION_5_0
)
420 case AR5K_EEPROM_MODE_11A
:
421 ee
->ee_switch_settling_turbo
[mode
] = (val
>> 6) & 0x7f;
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;
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;
433 if (AR5K_EEPROM_EEMAP(ee
->ee_misc0
) >=2)
434 ee
->ee_pd_gain_overlap
= (val
>> 9) & 0xf;
436 case AR5K_EEPROM_MODE_11G
:
437 ee
->ee_switch_settling_turbo
[mode
] = (val
>> 8) & 0x7f;
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;
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;
451 /* return new offset */
457 /* Read mode-specific data (except power calibration data) */
459 ath5k_eeprom_init_modes(struct ath5k_hw
*ah
)
461 struct ath5k_eeprom_info
*ee
= &ah
->ah_capabilities
.cap_eeprom
;
468 * Get values for all modes
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
);
474 ee
->ee_turbo_max_power
[AR5K_EEPROM_MODE_11A
] =
475 AR5K_EEPROM_HDR_T_5GHZ_DBM(ee
->ee_header
);
477 for (mode
= AR5K_EEPROM_MODE_11A
; mode
<= AR5K_EEPROM_MODE_11G
; mode
++) {
478 offset
= mode_offset
[mode
];
480 ret
= ath5k_eeprom_read_ants(ah
, &offset
, mode
);
484 ret
= ath5k_eeprom_read_modes(ah
, &offset
, mode
);
488 ret
= ath5k_eeprom_read_turbo_modes(ah
, &offset
, mode
);
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;
503 /* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff
506 ath5k_eeprom_read_freq_list(struct ath5k_hw
*ah
, int *offset
, int max
,
507 struct ath5k_chan_pcal_info
*pc
, unsigned int mode
)
509 struct ath5k_eeprom_info
*ee
= &ah
->ah_capabilities
.cap_eeprom
;
516 ee
->ee_n_piers
[mode
] = 0;
518 AR5K_EEPROM_READ(o
++, val
);
524 pc
[i
++].freq
= ath5k_eeprom_bin2freq(ee
,
526 ee
->ee_n_piers
[mode
]++;
528 freq2
= (val
>> 8) & 0xff;
532 pc
[i
++].freq
= ath5k_eeprom_bin2freq(ee
,
534 ee
->ee_n_piers
[mode
]++;
537 /* return new offset */
543 /* Read frequency piers for 802.11a */
545 ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw
*ah
, int offset
)
547 struct ath5k_eeprom_info
*ee
= &ah
->ah_capabilities
.cap_eeprom
;
548 struct ath5k_chan_pcal_info
*pcal
= ee
->ee_pwr_cal_a
;
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
);
558 mask
= AR5K_EEPROM_FREQ_M(ah
->ah_ee_version
);
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
;
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
;
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
;
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
;
581 AR5K_EEPROM_READ(offset
++, val
);
582 pcal
[9].freq
|= (val
>> 10) & 0x3f;
584 /* Fixed number of piers */
585 ee
->ee_n_piers
[AR5K_EEPROM_MODE_11A
] = 10;
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
);
596 /* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */
598 ath5k_eeprom_init_11bg_2413(struct ath5k_hw
*ah
, unsigned int mode
, int offset
)
600 struct ath5k_eeprom_info
*ee
= &ah
->ah_capabilities
.cap_eeprom
;
601 struct ath5k_chan_pcal_info
*pcal
;
604 case AR5K_EEPROM_MODE_11B
:
605 pcal
= ee
->ee_pwr_cal_b
;
607 case AR5K_EEPROM_MODE_11G
:
608 pcal
= ee
->ee_pwr_cal_g
;
614 ath5k_eeprom_read_freq_list(ah
, &offset
,
615 AR5K_EEPROM_N_2GHZ_CHAN_2413
, pcal
,
622 * Read power calibration for RF5111 chips
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.
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.
642 ath5k_get_pcdac_intercepts(struct ath5k_hw
*ah
, u8 min
, u8 max
, u8
*vp
)
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 };
651 if (ah
->ah_ee_version
>= AR5K_EEPROM_VERSION_3_2
)
656 for (i
= 0; i
< ARRAY_SIZE(intercepts3
); i
++)
657 vp
[i
] = (ip
[i
] * max
+ (100 - ip
[i
]) * min
) / 100;
660 /* Convert RF5111 specific data to generic raw data
661 * used by interpolation code */
663 ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw
*ah
, int mode
,
664 struct ath5k_chan_pcal_info
*chinfo
)
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
;
670 u8
*pdgain_idx
= ee
->ee_pdc_to_idx
[mode
];
672 /* Fill raw data for each calibration pier */
673 for (pier
= 0; pier
< ee
->ee_n_piers
[mode
]; pier
++) {
675 pcinfo
= &chinfo
[pier
].rf5111_info
;
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
));
682 if (!chinfo
[pier
].pd_curves
)
685 /* Only one curve for RF5111
686 * find out which one and place
688 * Note: ee_x_gain is reversed here */
689 for (idx
= 0; idx
< AR5K_EEPROM_N_PD_CURVES
; idx
++) {
691 if (!((ee
->ee_x_gain
[mode
] >> idx
) & 0x1)) {
697 ee
->ee_pd_gains
[mode
] = 1;
699 pd
= &chinfo
[pier
].pd_curves
[idx
];
701 pd
->pd_points
= AR5K_EEPROM_N_PWR_POINTS_5111
;
703 /* Allocate pd points for this curve */
704 pd
->pd_step
= calloc(AR5K_EEPROM_N_PWR_POINTS_5111
, sizeof(u8
));
708 pd
->pd_pwr
= calloc(AR5K_EEPROM_N_PWR_POINTS_5111
, sizeof(s16
));
713 * (convert power to 0.25dB units
714 * for RF5112 combatibility) */
715 for (point
= 0; point
< pd
->pd_points
; point
++) {
717 /* Absolute values */
718 pd
->pd_pwr
[point
] = 2 * pcinfo
->pwr
[point
];
721 pd
->pd_step
[point
] = pcinfo
->pcdac
[point
];
724 /* Set min/max pwr */
725 chinfo
[pier
].min_pwr
= pd
->pd_pwr
[0];
726 chinfo
[pier
].max_pwr
= pd
->pd_pwr
[10];
733 /* Parse EEPROM data */
735 ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw
*ah
, int mode
)
737 struct ath5k_eeprom_info
*ee
= &ah
->ah_capabilities
.cap_eeprom
;
738 struct ath5k_chan_pcal_info
*pcal
;
743 offset
= AR5K_EEPROM_GROUPS_START(ee
->ee_version
);
745 case AR5K_EEPROM_MODE_11A
:
746 if (!AR5K_EEPROM_HDR_11A(ee
->ee_header
))
749 ret
= ath5k_eeprom_init_11a_pcal_freq(ah
,
750 offset
+ AR5K_EEPROM_GROUP1_OFFSET
);
754 offset
+= AR5K_EEPROM_GROUP2_OFFSET
;
755 pcal
= ee
->ee_pwr_cal_a
;
757 case AR5K_EEPROM_MODE_11B
:
758 if (!AR5K_EEPROM_HDR_11B(ee
->ee_header
) &&
759 !AR5K_EEPROM_HDR_11G(ee
->ee_header
))
762 pcal
= ee
->ee_pwr_cal_b
;
763 offset
+= AR5K_EEPROM_GROUP3_OFFSET
;
769 ee
->ee_n_piers
[mode
] = 3;
771 case AR5K_EEPROM_MODE_11G
:
772 if (!AR5K_EEPROM_HDR_11G(ee
->ee_header
))
775 pcal
= ee
->ee_pwr_cal_g
;
776 offset
+= AR5K_EEPROM_GROUP4_OFFSET
;
782 ee
->ee_n_piers
[mode
] = 3;
788 for (i
= 0; i
< ee
->ee_n_piers
[mode
]; i
++) {
789 struct ath5k_chan_pcal_info_rf5111
*cdata
=
790 &pcal
[i
].rf5111_info
;
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
);
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
);
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
);
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
);
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
);
818 ath5k_get_pcdac_intercepts(ah
, cdata
->pcdac_min
,
819 cdata
->pcdac_max
, cdata
->pcdac
);
822 return ath5k_eeprom_convert_pcal_info_5111(ah
, mode
, pcal
);
827 * Read power calibration for RF5112 chips
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
838 * Note: Many vendors just use xpd 0 so xpd 3 is zeroed.
841 /* Convert RF5112 specific data to generic raw data
842 * used by interpolation code */
844 ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw
*ah
, int mode
,
845 struct ath5k_chan_pcal_info
*chinfo
)
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
;
852 /* Fill raw data for each calibration pier */
853 for (pier
= 0; pier
< ee
->ee_n_piers
[mode
]; pier
++) {
855 pcinfo
= &chinfo
[pier
].rf5112_info
;
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
));
862 if (!chinfo
[pier
].pd_curves
)
866 for (pdg
= 0; pdg
< ee
->ee_pd_gains
[mode
]; pdg
++) {
868 u8 idx
= pdgain_idx
[pdg
];
869 struct ath5k_pdgain_info
*pd
=
870 &chinfo
[pier
].pd_curves
[idx
];
872 /* Lowest gain curve (max power) */
874 /* One more point for better accuracy */
875 pd
->pd_points
= AR5K_EEPROM_N_XPD0_POINTS
;
877 /* Allocate pd points for this curve */
878 pd
->pd_step
= calloc(pd
->pd_points
, sizeof(u8
));
883 pd
->pd_pwr
= calloc(pd
->pd_points
, sizeof(s16
));
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];
894 for (point
= 1; point
< pd
->pd_points
;
896 /* Absolute values */
898 pcinfo
->pwr_x0
[point
];
902 pd
->pd_step
[point
- 1] +
903 pcinfo
->pcdac_x0
[point
];
906 /* Set min power for this frequency */
907 chinfo
[pier
].min_pwr
= pd
->pd_pwr
[0];
909 /* Highest gain curve (min power) */
910 } else if (pdg
== 1) {
912 pd
->pd_points
= AR5K_EEPROM_N_XPD3_POINTS
;
914 /* Allocate pd points for this curve */
915 pd
->pd_step
= calloc(pd
->pd_points
, sizeof(u8
));
920 pd
->pd_pwr
= calloc(pd
->pd_points
, sizeof(s16
));
926 * (all power levels are in 0.25dB units) */
927 for (point
= 0; point
< pd
->pd_points
;
929 /* Absolute values */
931 pcinfo
->pwr_x3
[point
];
935 pcinfo
->pcdac_x3
[point
];
938 /* Since we have a higher gain curve
939 * override min power */
940 chinfo
[pier
].min_pwr
= pd
->pd_pwr
[0];
948 /* Parse EEPROM data */
950 ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw
*ah
, int mode
)
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
];
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
;
972 ee
->ee_pd_gains
[mode
] = pd_gains
;
974 if (pd_gains
== 0 || pd_gains
> 2)
978 case AR5K_EEPROM_MODE_11A
:
980 * Read 5GHz EEPROM channels
982 offset
= AR5K_EEPROM_GROUPS_START(ee
->ee_version
);
983 ath5k_eeprom_init_11a_pcal_freq(ah
, offset
);
985 offset
+= AR5K_EEPROM_GROUP2_OFFSET
;
986 gen_chan_info
= ee
->ee_pwr_cal_a
;
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
;
993 /* NB: frequency piers parsed during mode init */
994 gen_chan_info
= ee
->ee_pwr_cal_b
;
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
;
1003 /* NB: frequency piers parsed during mode init */
1004 gen_chan_info
= ee
->ee_pwr_cal_g
;
1010 for (i
= 0; i
< ee
->ee_n_piers
[mode
]; i
++) {
1011 chan_pcal_info
= &gen_chan_info
[i
].rf5112_info
;
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);
1023 * corresponding to the above power
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);
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);
1037 AR5K_EEPROM_READ(offset
++, val
);
1038 chan_pcal_info
->pwr_x3
[2] = (val
& 0xff);
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;
1047 if (ee
->ee_version
>= AR5K_EEPROM_VERSION_4_3
) {
1048 chan_pcal_info
->pcdac_x0
[0] = ((val
>> 8) & 0x3f);
1050 /* Last xpd0 power level is also channel maximum */
1051 gen_chan_info
[i
].max_pwr
= chan_pcal_info
->pwr_x0
[3];
1053 chan_pcal_info
->pcdac_x0
[0] = 1;
1054 gen_chan_info
[i
].max_pwr
= (s8
) ((val
>> 8) & 0xff);
1059 return ath5k_eeprom_convert_pcal_info_5112(ah
, mode
, gen_chan_info
);
1064 * Read power calibration for RF2413 chips
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.
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.
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 */
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
)
1088 static const unsigned int pdgains_size
[] = { 4, 6, 9, 12 };
1091 sz
= pdgains_size
[ee
->ee_pd_gains
[mode
] - 1];
1092 sz
*= ee
->ee_n_piers
[mode
];
1097 /* Return the starting offset for a section based on the modes supported
1098 * and each section's size. */
1100 ath5k_cal_data_offset_2413(struct ath5k_eeprom_info
*ee
, int mode
)
1102 u32 offset
= AR5K_EEPROM_CAL_DATA_START(ee
->ee_misc4
);
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;
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;
1117 case AR5K_EEPROM_MODE_11A
:
1126 /* Convert RF2413 specific data to generic raw data
1127 * used by interpolation code */
1129 ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw
*ah
, int mode
,
1130 struct ath5k_chan_pcal_info
*chinfo
)
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
;
1138 /* Fill raw data for each calibration pier */
1139 for (pier
= 0; pier
< ee
->ee_n_piers
[mode
]; pier
++) {
1141 pcinfo
= &chinfo
[pier
].rf2413_info
;
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
));
1148 if (!chinfo
[pier
].pd_curves
)
1151 /* Fill pd_curves */
1152 for (pdg
= 0; pdg
< ee
->ee_pd_gains
[mode
]; pdg
++) {
1154 u8 idx
= pdgain_idx
[pdg
];
1155 struct ath5k_pdgain_info
*pd
=
1156 &chinfo
[pier
].pd_curves
[idx
];
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
;
1163 pd
->pd_points
= AR5K_EEPROM_N_PD_POINTS
- 1;
1165 /* Allocate pd points for this curve */
1166 pd
->pd_step
= calloc(pd
->pd_points
, sizeof(u8
));
1171 pd
->pd_pwr
= calloc(pd
->pd_points
, sizeof(s16
));
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
];
1182 for (point
= 1; point
< pd
->pd_points
; point
++) {
1184 pd
->pd_pwr
[point
] = pd
->pd_pwr
[point
- 1] +
1185 2 * pcinfo
->pwr
[pdg
][point
- 1];
1187 pd
->pd_step
[point
] = pd
->pd_step
[point
- 1] +
1188 pcinfo
->pddac
[pdg
][point
- 1];
1192 /* Highest gain curve -> min power */
1194 chinfo
[pier
].min_pwr
= pd
->pd_pwr
[0];
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];
1206 /* Parse EEPROM data */
1208 ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw
*ah
, int mode
)
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
];
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
;
1230 ee
->ee_pd_gains
[mode
] = pd_gains
;
1235 offset
= ath5k_cal_data_offset_2413(ee
, mode
);
1237 case AR5K_EEPROM_MODE_11A
:
1238 if (!AR5K_EEPROM_HDR_11A(ee
->ee_header
))
1241 ath5k_eeprom_init_11a_pcal_freq(ah
, offset
);
1242 offset
+= AR5K_EEPROM_N_5GHZ_CHAN
/ 2;
1243 chinfo
= ee
->ee_pwr_cal_a
;
1245 case AR5K_EEPROM_MODE_11B
:
1246 if (!AR5K_EEPROM_HDR_11B(ee
->ee_header
))
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
;
1253 case AR5K_EEPROM_MODE_11G
:
1254 if (!AR5K_EEPROM_HDR_11G(ee
->ee_header
))
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
;
1265 for (i
= 0; i
< ee
->ee_n_piers
[mode
]; i
++) {
1266 pcinfo
= &chinfo
[i
].rf2413_info
;
1269 * Read pwr_i, pddac_i and the first
1270 * 2 pd points (pwr, pddac)
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;
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;
1282 AR5K_EEPROM_READ(offset
++, val
);
1283 pcinfo
->pwr
[0][2] = val
& 0xf;
1284 pcinfo
->pddac
[0][2] = (val
>> 4) & 0x3f;
1286 pcinfo
->pwr
[0][3] = 0;
1287 pcinfo
->pddac
[0][3] = 0;
1291 * Pd gain 0 is not the last pd gain
1292 * so it only has 2 pd points.
1293 * Continue wih pd gain 1.
1295 pcinfo
->pwr_i
[1] = (val
>> 10) & 0x1f;
1297 pcinfo
->pddac_i
[1] = (val
>> 15) & 0x1;
1298 AR5K_EEPROM_READ(offset
++, val
);
1299 pcinfo
->pddac_i
[1] |= (val
& 0x3F) << 1;
1301 pcinfo
->pwr
[1][0] = (val
>> 6) & 0xf;
1302 pcinfo
->pddac
[1][0] = (val
>> 10) & 0x3f;
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;
1309 pcinfo
->pddac
[1][2] = (val
>> 14) & 0x3;
1310 AR5K_EEPROM_READ(offset
++, val
);
1311 pcinfo
->pddac
[1][2] |= (val
& 0xF) << 2;
1313 pcinfo
->pwr
[1][3] = 0;
1314 pcinfo
->pddac
[1][3] = 0;
1315 } else if (pd_gains
== 1) {
1317 * Pd gain 0 is the last one so
1318 * read the extra point.
1320 pcinfo
->pwr
[0][3] = (val
>> 10) & 0xf;
1322 pcinfo
->pddac
[0][3] = (val
>> 14) & 0x3;
1323 AR5K_EEPROM_READ(offset
++, val
);
1324 pcinfo
->pddac
[0][3] |= (val
& 0xF) << 2;
1328 * Proceed with the other pd_gains
1332 pcinfo
->pwr_i
[2] = (val
>> 4) & 0x1f;
1333 pcinfo
->pddac_i
[2] = (val
>> 9) & 0x7f;
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;
1340 pcinfo
->pddac
[2][1] = (val
>> 14) & 0x3;
1341 AR5K_EEPROM_READ(offset
++, val
);
1342 pcinfo
->pddac
[2][1] |= (val
& 0xF) << 2;
1344 pcinfo
->pwr
[2][2] = (val
>> 4) & 0xf;
1345 pcinfo
->pddac
[2][2] = (val
>> 8) & 0x3f;
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;
1355 pcinfo
->pwr_i
[3] = (val
>> 14) & 0x3;
1356 AR5K_EEPROM_READ(offset
++, val
);
1357 pcinfo
->pwr_i
[3] |= ((val
>> 0) & 0x7) << 2;
1359 pcinfo
->pddac_i
[3] = (val
>> 3) & 0x7f;
1360 pcinfo
->pwr
[3][0] = (val
>> 10) & 0xf;
1361 pcinfo
->pddac
[3][0] = (val
>> 14) & 0x3;
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;
1368 pcinfo
->pwr
[3][2] = (val
>> 14) & 0x3;
1369 AR5K_EEPROM_READ(offset
++, val
);
1370 pcinfo
->pwr
[3][2] |= ((val
>> 0) & 0x3) << 2;
1372 pcinfo
->pddac
[3][2] = (val
>> 2) & 0x3f;
1373 pcinfo
->pwr
[3][3] = (val
>> 8) & 0xf;
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;
1383 pcinfo
->pddac
[2][3] = (val
>> 2) & 0x3f;
1387 return ath5k_eeprom_convert_pcal_info_2413(ah
, mode
, chinfo
);
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.
1396 * This also works for v5 EEPROMs.
1399 ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw
*ah
, unsigned int mode
)
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
;
1408 offset
= AR5K_EEPROM_TARGET_PWRSTART(ee
->ee_misc1
);
1409 rate_target_pwr_num
= &ee
->ee_rate_target_pwr_num
[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
;
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 */
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
;
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
);
1437 rate_pcal_info
[i
].target_power_6to24
= ((val
>> 3) & 0x3f);
1438 rate_pcal_info
[i
].target_power_36
= (val
<< 3) & 0x3f;
1440 AR5K_EEPROM_READ(offset
++, val
);
1442 if (rate_pcal_info
[i
].freq
== AR5K_EEPROM_CHANNEL_DIS
||
1444 (*rate_target_pwr_num
) = i
;
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);
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
);
1458 rate_pcal_info
[i
].target_power_6to24
= ((val
>> 2) & 0x3f);
1459 rate_pcal_info
[i
].target_power_36
= (val
<< 4) & 0x3f;
1461 AR5K_EEPROM_READ(offset
++, val
);
1463 if (rate_pcal_info
[i
].freq
== AR5K_EEPROM_CHANNEL_DIS
||
1465 (*rate_target_pwr_num
) = i
;
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);
1479 * Read per channel calibration info from EEPROM
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).
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.
1493 ath5k_eeprom_read_pcal_info(struct ath5k_hw
*ah
)
1495 struct ath5k_eeprom_info
*ee
= &ah
->ah_capabilities
.cap_eeprom
;
1496 int (*read_pcal
)(struct ath5k_hw
*hw
, int mode
);
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
;
1507 read_pcal
= ath5k_eeprom_read_pcal_info_5111
;
1510 for (mode
= AR5K_EEPROM_MODE_11A
; mode
<= AR5K_EEPROM_MODE_11G
;
1512 err
= read_pcal(ah
, mode
);
1516 err
= ath5k_eeprom_read_target_rate_pwr_info(ah
, mode
);
1525 ath5k_eeprom_free_pcal_info(struct ath5k_hw
*ah
, int mode
)
1527 struct ath5k_eeprom_info
*ee
= &ah
->ah_capabilities
.cap_eeprom
;
1528 struct ath5k_chan_pcal_info
*chinfo
;
1532 case AR5K_EEPROM_MODE_11A
:
1533 if (!AR5K_EEPROM_HDR_11A(ee
->ee_header
))
1535 chinfo
= ee
->ee_pwr_cal_a
;
1537 case AR5K_EEPROM_MODE_11B
:
1538 if (!AR5K_EEPROM_HDR_11B(ee
->ee_header
))
1540 chinfo
= ee
->ee_pwr_cal_b
;
1542 case AR5K_EEPROM_MODE_11G
:
1543 if (!AR5K_EEPROM_HDR_11G(ee
->ee_header
))
1545 chinfo
= ee
->ee_pwr_cal_g
;
1551 for (pier
= 0; pier
< ee
->ee_n_piers
[mode
]; pier
++) {
1552 if (!chinfo
[pier
].pd_curves
)
1555 for (pdg
= 0; pdg
< ee
->ee_pd_gains
[mode
]; pdg
++) {
1556 struct ath5k_pdgain_info
*pd
=
1557 &chinfo
[pier
].pd_curves
[pdg
];
1565 free(chinfo
[pier
].pd_curves
);
1572 ath5k_eeprom_detach(struct ath5k_hw
*ah
)
1576 for (mode
= AR5K_EEPROM_MODE_11A
; mode
<= AR5K_EEPROM_MODE_11G
; mode
++)
1577 ath5k_eeprom_free_pcal_info(ah
, mode
);
1580 /* Read conformance test limits used for regulatory control */
1582 ath5k_eeprom_read_ctl_info(struct ath5k_hw
*ah
)
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
;
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;
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
;
1607 offset
+= AR5K_EEPROM_GROUPS_START(ee
->ee_version
);
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
) {
1613 case AR5K_CTL_TURBO
:
1614 ctl_mode
= AR5K_EEPROM_MODE_11A
;
1617 ctl_mode
= AR5K_EEPROM_MODE_11G
;
1620 if (ee
->ee_ctl
[i
] == 0) {
1621 if (ee
->ee_version
>= AR5K_EEPROM_VERSION_3_3
)
1625 rep
+= AR5K_EEPROM_N_EDGES
;
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
;
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;
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
;
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
;
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
;
1657 AR5K_EEPROM_READ(offset
++, val
);
1658 rep
[6].freq
|= (val
>> 15) & 0x1;
1659 rep
[7].freq
= (val
>> 8) & fmask
;
1661 rep
[0].edge
= (val
>> 2) & pmask
;
1662 rep
[1].edge
= (val
<< 4) & pmask
;
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
;
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
;
1674 AR5K_EEPROM_READ(offset
++, val
);
1675 rep
[6].edge
|= (val
>> 14) & 0x3;
1676 rep
[7].edge
= (val
>> 8) & pmask
;
1678 for (j
= 0; j
< AR5K_EEPROM_N_EDGES
; j
++) {
1679 rep
[j
].freq
= ath5k_eeprom_bin2freq(ee
,
1680 rep
[j
].freq
, ctl_mode
);
1682 rep
+= AR5K_EEPROM_N_EDGES
;
1690 * Initialize eeprom power tables
1693 ath5k_eeprom_init(struct ath5k_hw
*ah
)
1697 err
= ath5k_eeprom_init_header(ah
);
1701 err
= ath5k_eeprom_init_modes(ah
);
1705 err
= ath5k_eeprom_read_pcal_info(ah
);
1709 err
= ath5k_eeprom_read_ctl_info(ah
);
1717 * Read the MAC address from eeprom
1719 int ath5k_eeprom_read_mac(struct ath5k_hw
*ah
, u8
*mac
)
1721 u8 mac_d
[ETH_ALEN
] = {};
1726 ret
= ath5k_hw_eeprom_read(ah
, 0x20, &data
);
1730 for (offset
= 0x1f, octet
= 0, total
= 0; offset
>= 0x1d; offset
--) {
1731 ret
= ath5k_hw_eeprom_read(ah
, offset
, &data
);
1736 mac_d
[octet
+ 1] = data
& 0xff;
1737 mac_d
[octet
] = data
>> 8;
1741 if (!total
|| total
== 3 * 0xffff)
1744 memcpy(mac
, mac_d
, ETH_ALEN
);
1749 int ath5k_eeprom_is_hb63(struct ath5k_hw
*ah
)
1753 ath5k_hw_eeprom_read(ah
, AR5K_EEPROM_IS_HB63
, &data
);
1755 if ((ah
->ah_mac_version
== (AR5K_SREV_AR2425
>> 4)) && data
)