blob: 5021749a439e1a818261b4316e5a0712ff8f9f29 [file] [log] [blame]
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001/*
2 * PHY functions
3 *
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03004 * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
Nick Kossifidis33a31822009-02-09 06:00:34 +02005 * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03006 * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
Jiri Slabyfa1c1142007-08-12 17:33:16 +02007 *
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.
11 *
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.
19 *
20 */
21
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030022#define _ATH5K_PHY
23
Jiri Slabyfa1c1142007-08-12 17:33:16 +020024#include <linux/delay.h>
25
26#include "ath5k.h"
27#include "reg.h"
28#include "base.h"
Nick Kossifidis33a31822009-02-09 06:00:34 +020029#include "rfbuffer.h"
30#include "rfgain.h"
Jiri Slabyfa1c1142007-08-12 17:33:16 +020031
32/*
33 * Used to modify RF Banks before writing them to AR5K_RF_BUFFER
34 */
35static unsigned int ath5k_hw_rfregs_op(u32 *rf, u32 offset, u32 reg, u32 bits,
36 u32 first, u32 col, bool set)
37{
38 u32 mask, entry, last, data, shift, position;
39 s32 left;
40 int i;
41
42 data = 0;
43
44 if (rf == NULL)
45 /* should not happen */
46 return 0;
47
48 if (!(col <= 3 && bits <= 32 && first + bits <= 319)) {
49 ATH5K_PRINTF("invalid values at offset %u\n", offset);
50 return 0;
51 }
52
53 entry = ((first - 1) / 8) + offset;
54 position = (first - 1) % 8;
55
Joe Perchese9010e22008-03-07 14:21:16 -080056 if (set)
Jiri Slabyfa1c1142007-08-12 17:33:16 +020057 data = ath5k_hw_bitswap(reg, bits);
58
59 for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) {
60 last = (position + left > 8) ? 8 : position + left;
61 mask = (((1 << last) - 1) ^ ((1 << position) - 1)) << (col * 8);
62
Joe Perchese9010e22008-03-07 14:21:16 -080063 if (set) {
Jiri Slabyfa1c1142007-08-12 17:33:16 +020064 rf[entry] &= ~mask;
65 rf[entry] |= ((data << position) << (col * 8)) & mask;
66 data >>= (8 - position);
67 } else {
68 data = (((rf[entry] & mask) >> (col * 8)) >> position)
69 << shift;
70 shift += last - position;
71 }
72
73 left -= 8 - position;
74 }
75
Joe Perchese9010e22008-03-07 14:21:16 -080076 data = set ? 1 : ath5k_hw_bitswap(data, bits);
Jiri Slabyfa1c1142007-08-12 17:33:16 +020077
78 return data;
79}
80
81static u32 ath5k_hw_rfregs_gainf_corr(struct ath5k_hw *ah)
82{
83 u32 mix, step;
84 u32 *rf;
85
86 if (ah->ah_rf_banks == NULL)
87 return 0;
88
89 rf = ah->ah_rf_banks;
90 ah->ah_gain.g_f_corr = 0;
91
92 if (ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 1, 36, 0, false) != 1)
93 return 0;
94
95 step = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 4, 32, 0, false);
96 mix = ah->ah_gain.g_step->gos_param[0];
97
98 switch (mix) {
99 case 3:
100 ah->ah_gain.g_f_corr = step * 2;
101 break;
102 case 2:
103 ah->ah_gain.g_f_corr = (step - 5) * 2;
104 break;
105 case 1:
106 ah->ah_gain.g_f_corr = step;
107 break;
108 default:
109 ah->ah_gain.g_f_corr = 0;
110 break;
111 }
112
113 return ah->ah_gain.g_f_corr;
114}
115
116static bool ath5k_hw_rfregs_gain_readback(struct ath5k_hw *ah)
117{
118 u32 step, mix, level[4];
119 u32 *rf;
120
121 if (ah->ah_rf_banks == NULL)
122 return false;
123
124 rf = ah->ah_rf_banks;
125
126 if (ah->ah_radio == AR5K_RF5111) {
127 step = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 6, 37, 0,
128 false);
129 level[0] = 0;
130 level[1] = (step == 0x3f) ? 0x32 : step + 4;
131 level[2] = (step != 0x3f) ? 0x40 : level[0];
132 level[3] = level[2] + 0x32;
133
134 ah->ah_gain.g_high = level[3] -
135 (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
136 ah->ah_gain.g_low = level[0] +
137 (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
138 } else {
139 mix = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 1, 36, 0,
140 false);
141 level[0] = level[2] = 0;
142
143 if (mix == 1) {
144 level[1] = level[3] = 83;
145 } else {
146 level[1] = level[3] = 107;
147 ah->ah_gain.g_high = 55;
148 }
149 }
150
151 return (ah->ah_gain.g_current >= level[0] &&
152 ah->ah_gain.g_current <= level[1]) ||
153 (ah->ah_gain.g_current >= level[2] &&
154 ah->ah_gain.g_current <= level[3]);
155}
156
157static s32 ath5k_hw_rfregs_gain_adjust(struct ath5k_hw *ah)
158{
159 const struct ath5k_gain_opt *go;
160 int ret = 0;
161
162 switch (ah->ah_radio) {
163 case AR5K_RF5111:
164 go = &rfgain_opt_5111;
165 break;
166 case AR5K_RF5112:
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200167 go = &rfgain_opt_5112;
168 break;
169 default:
170 return 0;
171 }
172
173 ah->ah_gain.g_step = &go->go_step[ah->ah_gain.g_step_idx];
174
175 if (ah->ah_gain.g_current >= ah->ah_gain.g_high) {
176 if (ah->ah_gain.g_step_idx == 0)
177 return -1;
178 for (ah->ah_gain.g_target = ah->ah_gain.g_current;
179 ah->ah_gain.g_target >= ah->ah_gain.g_high &&
180 ah->ah_gain.g_step_idx > 0;
181 ah->ah_gain.g_step =
182 &go->go_step[ah->ah_gain.g_step_idx])
183 ah->ah_gain.g_target -= 2 *
184 (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain -
185 ah->ah_gain.g_step->gos_gain);
186
187 ret = 1;
188 goto done;
189 }
190
191 if (ah->ah_gain.g_current <= ah->ah_gain.g_low) {
192 if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1))
193 return -2;
194 for (ah->ah_gain.g_target = ah->ah_gain.g_current;
195 ah->ah_gain.g_target <= ah->ah_gain.g_low &&
196 ah->ah_gain.g_step_idx < go->go_steps_count-1;
197 ah->ah_gain.g_step =
198 &go->go_step[ah->ah_gain.g_step_idx])
199 ah->ah_gain.g_target -= 2 *
200 (go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
201 ah->ah_gain.g_step->gos_gain);
202
203 ret = 2;
204 goto done;
205 }
206
207done:
208 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
209 "ret %d, gain step %u, current gain %u, target gain %u\n",
210 ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current,
211 ah->ah_gain.g_target);
212
213 return ret;
214}
215
216/*
217 * Read EEPROM Calibration data, modify RF Banks and Initialize RF5111
218 */
219static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
220 struct ieee80211_channel *channel, unsigned int mode)
221{
222 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
223 u32 *rf;
Nick Kossifidis33a31822009-02-09 06:00:34 +0200224 const unsigned int rf_size = ARRAY_SIZE(rfb_5111);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200225 unsigned int i;
226 int obdb = -1, bank = -1;
227 u32 ee_mode;
228
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -0500229 AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200230
231 rf = ah->ah_rf_banks;
232
233 /* Copy values to modify them */
234 for (i = 0; i < rf_size; i++) {
Nick Kossifidis33a31822009-02-09 06:00:34 +0200235 if (rfb_5111[i].rfb_bank >= AR5K_RF5111_INI_RF_MAX_BANKS) {
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200236 ATH5K_ERR(ah->ah_sc, "invalid bank\n");
237 return -EINVAL;
238 }
239
Nick Kossifidis33a31822009-02-09 06:00:34 +0200240 if (bank != rfb_5111[i].rfb_bank) {
241 bank = rfb_5111[i].rfb_bank;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200242 ah->ah_offset[bank] = i;
243 }
244
Nick Kossifidis33a31822009-02-09 06:00:34 +0200245 rf[i] = rfb_5111[i].rfb_mode_data[mode];
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200246 }
247
248 /* Modify bank 0 */
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -0500249 if (channel->hw_value & CHANNEL_2GHZ) {
250 if (channel->hw_value & CHANNEL_CCK)
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200251 ee_mode = AR5K_EEPROM_MODE_11B;
252 else
253 ee_mode = AR5K_EEPROM_MODE_11G;
254 obdb = 0;
255
256 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[0],
257 ee->ee_ob[ee_mode][obdb], 3, 119, 0, true))
258 return -EINVAL;
259
260 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[0],
261 ee->ee_ob[ee_mode][obdb], 3, 122, 0, true))
262 return -EINVAL;
263
264 obdb = 1;
265 /* Modify bank 6 */
266 } else {
267 /* For 11a, Turbo and XR */
268 ee_mode = AR5K_EEPROM_MODE_11A;
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -0500269 obdb = channel->center_freq >= 5725 ? 3 :
270 (channel->center_freq >= 5500 ? 2 :
271 (channel->center_freq >= 5260 ? 1 :
272 (channel->center_freq > 4000 ? 0 : -1)));
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200273
274 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
275 ee->ee_pwd_84, 1, 51, 3, true))
276 return -EINVAL;
277
278 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
279 ee->ee_pwd_90, 1, 45, 3, true))
280 return -EINVAL;
281 }
282
283 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
284 !ee->ee_xpd[ee_mode], 1, 95, 0, true))
285 return -EINVAL;
286
287 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
288 ee->ee_x_gain[ee_mode], 4, 96, 0, true))
289 return -EINVAL;
290
291 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], obdb >= 0 ?
292 ee->ee_ob[ee_mode][obdb] : 0, 3, 104, 0, true))
293 return -EINVAL;
294
295 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], obdb >= 0 ?
296 ee->ee_db[ee_mode][obdb] : 0, 3, 107, 0, true))
297 return -EINVAL;
298
299 /* Modify bank 7 */
300 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7],
301 ee->ee_i_gain[ee_mode], 6, 29, 0, true))
302 return -EINVAL;
303
304 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7],
305 ee->ee_xpd[ee_mode], 1, 4, 0, true))
306 return -EINVAL;
307
308 /* Write RF values */
309 for (i = 0; i < rf_size; i++) {
310 AR5K_REG_WAIT(i);
Nick Kossifidis33a31822009-02-09 06:00:34 +0200311 ath5k_hw_reg_write(ah, rf[i], rfb_5111[i].rfb_ctrl_register);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200312 }
313
314 return 0;
315}
316
317/*
318 * Read EEPROM Calibration data, modify RF Banks and Initialize RF5112
319 */
320static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
321 struct ieee80211_channel *channel, unsigned int mode)
322{
Nick Kossifidis33a31822009-02-09 06:00:34 +0200323 const struct ath5k_ini_rfbuffer *rf_ini;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200324 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
325 u32 *rf;
326 unsigned int rf_size, i;
327 int obdb = -1, bank = -1;
328 u32 ee_mode;
329
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -0500330 AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200331
332 rf = ah->ah_rf_banks;
333
Nick Kossifidis33a31822009-02-09 06:00:34 +0200334 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
335 rf_ini = rfb_5112a;
336 rf_size = ARRAY_SIZE(rfb_5112a);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200337 } else {
Nick Kossifidis33a31822009-02-09 06:00:34 +0200338 rf_ini = rfb_5112;
339 rf_size = ARRAY_SIZE(rfb_5112);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200340 }
341
342 /* Copy values to modify them */
343 for (i = 0; i < rf_size; i++) {
Nick Kossifidis33a31822009-02-09 06:00:34 +0200344 if (rf_ini[i].rfb_bank >= AR5K_RF5112_INI_RF_MAX_BANKS) {
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200345 ATH5K_ERR(ah->ah_sc, "invalid bank\n");
346 return -EINVAL;
347 }
348
Nick Kossifidis33a31822009-02-09 06:00:34 +0200349 if (bank != rf_ini[i].rfb_bank) {
350 bank = rf_ini[i].rfb_bank;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200351 ah->ah_offset[bank] = i;
352 }
353
Nick Kossifidis33a31822009-02-09 06:00:34 +0200354 rf[i] = rf_ini[i].rfb_mode_data[mode];
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200355 }
356
357 /* Modify bank 6 */
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -0500358 if (channel->hw_value & CHANNEL_2GHZ) {
359 if (channel->hw_value & CHANNEL_OFDM)
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200360 ee_mode = AR5K_EEPROM_MODE_11G;
361 else
362 ee_mode = AR5K_EEPROM_MODE_11B;
363 obdb = 0;
364
365 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
366 ee->ee_ob[ee_mode][obdb], 3, 287, 0, true))
367 return -EINVAL;
368
369 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
370 ee->ee_ob[ee_mode][obdb], 3, 290, 0, true))
371 return -EINVAL;
372 } else {
373 /* For 11a, Turbo and XR */
374 ee_mode = AR5K_EEPROM_MODE_11A;
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -0500375 obdb = channel->center_freq >= 5725 ? 3 :
376 (channel->center_freq >= 5500 ? 2 :
377 (channel->center_freq >= 5260 ? 1 :
378 (channel->center_freq > 4000 ? 0 : -1)));
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200379
Luis R. Rodrigueze71c9fa2008-02-03 21:53:51 -0500380 if (obdb == -1)
381 return -EINVAL;
382
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200383 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
384 ee->ee_ob[ee_mode][obdb], 3, 279, 0, true))
385 return -EINVAL;
386
387 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
388 ee->ee_ob[ee_mode][obdb], 3, 282, 0, true))
389 return -EINVAL;
390 }
391
392 ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
393 ee->ee_x_gain[ee_mode], 2, 270, 0, true);
394 ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
395 ee->ee_x_gain[ee_mode], 2, 257, 0, true);
396
397 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
398 ee->ee_xpd[ee_mode], 1, 302, 0, true))
399 return -EINVAL;
400
401 /* Modify bank 7 */
402 if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7],
403 ee->ee_i_gain[ee_mode], 6, 14, 0, true))
404 return -EINVAL;
405
406 /* Write RF values */
407 for (i = 0; i < rf_size; i++)
Nick Kossifidis33a31822009-02-09 06:00:34 +0200408 ath5k_hw_reg_write(ah, rf[i], rf_ini[i].rfb_ctrl_register);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200409
410 return 0;
411}
412
413/*
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300414 * Initialize RF5413/5414 and future chips
415 * (until we come up with a better solution)
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200416 */
417static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah,
418 struct ieee80211_channel *channel, unsigned int mode)
419{
Nick Kossifidis33a31822009-02-09 06:00:34 +0200420 const struct ath5k_ini_rfbuffer *rf_ini;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200421 u32 *rf;
422 unsigned int rf_size, i;
423 int bank = -1;
424
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -0500425 AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200426
427 rf = ah->ah_rf_banks;
428
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300429 switch (ah->ah_radio) {
430 case AR5K_RF5413:
Nick Kossifidis33a31822009-02-09 06:00:34 +0200431 rf_ini = rfb_5413;
432 rf_size = ARRAY_SIZE(rfb_5413);
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300433 break;
434 case AR5K_RF2413:
Nick Kossifidis33a31822009-02-09 06:00:34 +0200435 rf_ini = rfb_2413;
436 rf_size = ARRAY_SIZE(rfb_2413);
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300437
Nick Kossifidisf714dd62008-02-28 14:43:51 -0500438 if (mode < 2) {
439 ATH5K_ERR(ah->ah_sc,
440 "invalid channel mode: %i\n", mode);
441 return -EINVAL;
442 }
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300443
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300444 break;
445 case AR5K_RF2425:
Nick Kossifidis33a31822009-02-09 06:00:34 +0200446 rf_ini = rfb_2425;
447 rf_size = ARRAY_SIZE(rfb_2425);
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300448
449 if (mode < 2) {
450 ATH5K_ERR(ah->ah_sc,
451 "invalid channel mode: %i\n", mode);
452 return -EINVAL;
453 }
454
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300455 break;
456 default:
Nick Kossifidisf714dd62008-02-28 14:43:51 -0500457 return -EINVAL;
458 }
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200459
460 /* Copy values to modify them */
461 for (i = 0; i < rf_size; i++) {
Nick Kossifidis33a31822009-02-09 06:00:34 +0200462 if (rf_ini[i].rfb_bank >= AR5K_RF5112_INI_RF_MAX_BANKS) {
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200463 ATH5K_ERR(ah->ah_sc, "invalid bank\n");
464 return -EINVAL;
465 }
466
Nick Kossifidis33a31822009-02-09 06:00:34 +0200467 if (bank != rf_ini[i].rfb_bank) {
468 bank = rf_ini[i].rfb_bank;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200469 ah->ah_offset[bank] = i;
470 }
471
Nick Kossifidis33a31822009-02-09 06:00:34 +0200472 rf[i] = rf_ini[i].rfb_mode_data[mode];
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200473 }
474
475 /*
476 * After compairing dumps from different cards
477 * we get the same RF_BUFFER settings (diff returns
478 * 0 lines). It seems that RF_BUFFER settings are static
479 * and are written unmodified (no EEPROM stuff
480 * is used because calibration data would be
481 * different between different cards and would result
482 * different RF_BUFFER settings)
483 */
484
485 /* Write RF values */
486 for (i = 0; i < rf_size; i++)
Nick Kossifidis33a31822009-02-09 06:00:34 +0200487 ath5k_hw_reg_write(ah, rf[i], rf_ini[i].rfb_ctrl_register);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200488
489 return 0;
490}
491
492/*
493 * Initialize RF
494 */
495int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel,
496 unsigned int mode)
497{
498 int (*func)(struct ath5k_hw *, struct ieee80211_channel *, unsigned int);
499 int ret;
500
501 switch (ah->ah_radio) {
502 case AR5K_RF5111:
Nick Kossifidis33a31822009-02-09 06:00:34 +0200503 ah->ah_rf_banks_size = sizeof(rfb_5111);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200504 func = ath5k_hw_rf5111_rfregs;
505 break;
506 case AR5K_RF5112:
507 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
Nick Kossifidis33a31822009-02-09 06:00:34 +0200508 ah->ah_rf_banks_size = sizeof(rfb_5112a);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200509 else
Nick Kossifidis33a31822009-02-09 06:00:34 +0200510 ah->ah_rf_banks_size = sizeof(rfb_5112);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200511 func = ath5k_hw_rf5112_rfregs;
512 break;
513 case AR5K_RF5413:
Nick Kossifidis33a31822009-02-09 06:00:34 +0200514 ah->ah_rf_banks_size = sizeof(rfb_5413);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200515 func = ath5k_hw_rf5413_rfregs;
516 break;
Nick Kossifidisf714dd62008-02-28 14:43:51 -0500517 case AR5K_RF2413:
Nick Kossifidis33a31822009-02-09 06:00:34 +0200518 ah->ah_rf_banks_size = sizeof(rfb_2413);
Nick Kossifidisf714dd62008-02-28 14:43:51 -0500519 func = ath5k_hw_rf5413_rfregs;
520 break;
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300521 case AR5K_RF2425:
Nick Kossifidis33a31822009-02-09 06:00:34 +0200522 ah->ah_rf_banks_size = sizeof(rfb_2425);
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300523 func = ath5k_hw_rf5413_rfregs;
524 break;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200525 default:
526 return -EINVAL;
527 }
528
529 if (ah->ah_rf_banks == NULL) {
530 /* XXX do extra checks? */
531 ah->ah_rf_banks = kmalloc(ah->ah_rf_banks_size, GFP_KERNEL);
532 if (ah->ah_rf_banks == NULL) {
533 ATH5K_ERR(ah->ah_sc, "out of memory\n");
534 return -ENOMEM;
535 }
536 }
537
538 ret = func(ah, channel, mode);
539 if (!ret)
540 ah->ah_rf_gain = AR5K_RFGAIN_INACTIVE;
541
542 return ret;
543}
544
545int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq)
546{
547 const struct ath5k_ini_rfgain *ath5k_rfg;
548 unsigned int i, size;
549
550 switch (ah->ah_radio) {
551 case AR5K_RF5111:
552 ath5k_rfg = rfgain_5111;
553 size = ARRAY_SIZE(rfgain_5111);
554 break;
555 case AR5K_RF5112:
556 ath5k_rfg = rfgain_5112;
557 size = ARRAY_SIZE(rfgain_5112);
558 break;
559 case AR5K_RF5413:
560 ath5k_rfg = rfgain_5413;
561 size = ARRAY_SIZE(rfgain_5413);
562 break;
Nick Kossifidisf714dd62008-02-28 14:43:51 -0500563 case AR5K_RF2413:
564 ath5k_rfg = rfgain_2413;
565 size = ARRAY_SIZE(rfgain_2413);
Nick Kossifidisf714dd62008-02-28 14:43:51 -0500566 break;
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300567 case AR5K_RF2425:
Nick Kossifidis27bcdee2008-07-20 06:42:47 +0300568 ath5k_rfg = rfgain_2425;
569 size = ARRAY_SIZE(rfgain_2425);
Nick Kossifidis136bfc72008-04-16 18:42:48 +0300570 break;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200571 default:
572 return -EINVAL;
573 }
574
575 switch (freq) {
576 case AR5K_INI_RFGAIN_2GHZ:
577 case AR5K_INI_RFGAIN_5GHZ:
578 break;
579 default:
580 return -EINVAL;
581 }
582
583 for (i = 0; i < size; i++) {
584 AR5K_REG_WAIT(i);
585 ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
586 (u32)ath5k_rfg[i].rfg_register);
587 }
588
589 return 0;
590}
591
592enum ath5k_rfgain ath5k_hw_get_rf_gain(struct ath5k_hw *ah)
593{
594 u32 data, type;
595
596 ATH5K_TRACE(ah->ah_sc);
597
598 if (ah->ah_rf_banks == NULL || !ah->ah_gain.g_active ||
599 ah->ah_version <= AR5K_AR5211)
600 return AR5K_RFGAIN_INACTIVE;
601
602 if (ah->ah_rf_gain != AR5K_RFGAIN_READ_REQUESTED)
603 goto done;
604
605 data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE);
606
607 if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) {
608 ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S;
609 type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE);
610
611 if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK)
612 ah->ah_gain.g_current += AR5K_GAIN_CCK_PROBE_CORR;
613
614 if (ah->ah_radio >= AR5K_RF5112) {
615 ath5k_hw_rfregs_gainf_corr(ah);
616 ah->ah_gain.g_current =
John Daiker0bbac082008-10-17 12:16:00 -0700617 ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200618 (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
619 0;
620 }
621
622 if (ath5k_hw_rfregs_gain_readback(ah) &&
623 AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
624 ath5k_hw_rfregs_gain_adjust(ah))
625 ah->ah_rf_gain = AR5K_RFGAIN_NEED_CHANGE;
626 }
627
628done:
629 return ah->ah_rf_gain;
630}
631
632int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah)
633{
634 /* Initialize the gain optimization values */
635 switch (ah->ah_radio) {
636 case AR5K_RF5111:
637 ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default;
638 ah->ah_gain.g_step =
639 &rfgain_opt_5111.go_step[ah->ah_gain.g_step_idx];
640 ah->ah_gain.g_low = 20;
641 ah->ah_gain.g_high = 35;
642 ah->ah_gain.g_active = 1;
643 break;
644 case AR5K_RF5112:
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200645 ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
646 ah->ah_gain.g_step =
647 &rfgain_opt_5112.go_step[ah->ah_gain.g_step_idx];
648 ah->ah_gain.g_low = 20;
649 ah->ah_gain.g_high = 85;
650 ah->ah_gain.g_active = 1;
651 break;
652 default:
653 return -EINVAL;
654 }
655
656 return 0;
657}
658
659/**************************\
660 PHY/RF channel functions
661\**************************/
662
663/*
664 * Check if a channel is supported
665 */
666bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
667{
668 /* Check if the channel is in our supported range */
669 if (flags & CHANNEL_2GHZ) {
670 if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
671 (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
672 return true;
673 } else if (flags & CHANNEL_5GHZ)
674 if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
675 (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
676 return true;
677
678 return false;
679}
680
681/*
682 * Convertion needed for RF5110
683 */
684static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
685{
686 u32 athchan;
687
688 /*
689 * Convert IEEE channel/MHz to an internal channel value used
690 * by the AR5210 chipset. This has not been verified with
691 * newer chipsets like the AR5212A who have a completely
692 * different RF/PHY part.
693 */
Luis R. Rodriguez400ec452008-02-03 21:51:49 -0500694 athchan = (ath5k_hw_bitswap(
695 (ieee80211_frequency_to_channel(
696 channel->center_freq) - 24) / 2, 5)
697 << 1) | (1 << 6) | 0x1;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200698 return athchan;
699}
700
701/*
702 * Set channel on RF5110
703 */
704static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah,
705 struct ieee80211_channel *channel)
706{
707 u32 data;
708
709 /*
710 * Set the channel and wait
711 */
712 data = ath5k_hw_rf5110_chan2athchan(channel);
713 ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER);
714 ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0);
715 mdelay(1);
716
717 return 0;
718}
719
720/*
721 * Convertion needed for 5111
722 */
723static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee,
724 struct ath5k_athchan_2ghz *athchan)
725{
726 int channel;
727
728 /* Cast this value to catch negative channel numbers (>= -19) */
729 channel = (int)ieee;
730
731 /*
732 * Map 2GHz IEEE channel to 5GHz Atheros channel
733 */
734 if (channel <= 13) {
735 athchan->a2_athchan = 115 + channel;
736 athchan->a2_flags = 0x46;
737 } else if (channel == 14) {
738 athchan->a2_athchan = 124;
739 athchan->a2_flags = 0x44;
740 } else if (channel >= 15 && channel <= 26) {
741 athchan->a2_athchan = ((channel - 14) * 4) + 132;
742 athchan->a2_flags = 0x46;
743 } else
744 return -EINVAL;
745
746 return 0;
747}
748
749/*
750 * Set channel on 5111
751 */
752static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
753 struct ieee80211_channel *channel)
754{
755 struct ath5k_athchan_2ghz ath5k_channel_2ghz;
Luis R. Rodriguez400ec452008-02-03 21:51:49 -0500756 unsigned int ath5k_channel =
757 ieee80211_frequency_to_channel(channel->center_freq);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200758 u32 data0, data1, clock;
759 int ret;
760
761 /*
762 * Set the channel on the RF5111 radio
763 */
764 data0 = data1 = 0;
765
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -0500766 if (channel->hw_value & CHANNEL_2GHZ) {
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200767 /* Map 2GHz channel to 5GHz Atheros channel ID */
Luis R. Rodriguez400ec452008-02-03 21:51:49 -0500768 ret = ath5k_hw_rf5111_chan2athchan(
769 ieee80211_frequency_to_channel(channel->center_freq),
770 &ath5k_channel_2ghz);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200771 if (ret)
772 return ret;
773
774 ath5k_channel = ath5k_channel_2ghz.a2_athchan;
775 data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff)
776 << 5) | (1 << 4);
777 }
778
779 if (ath5k_channel < 145 || !(ath5k_channel & 1)) {
780 clock = 1;
781 data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) |
782 (clock << 1) | (1 << 10) | 1;
783 } else {
784 clock = 0;
785 data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff)
786 << 2) | (clock << 1) | (1 << 10) | 1;
787 }
788
789 ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8),
790 AR5K_RF_BUFFER);
791 ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00),
792 AR5K_RF_BUFFER_CONTROL_3);
793
794 return 0;
795}
796
797/*
798 * Set channel on 5112 and newer
799 */
800static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
801 struct ieee80211_channel *channel)
802{
803 u32 data, data0, data1, data2;
804 u16 c;
805
806 data = data0 = data1 = data2 = 0;
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -0500807 c = channel->center_freq;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200808
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200809 if (c < 4800) {
810 if (!((c - 2224) % 5)) {
811 data0 = ((2 * (c - 704)) - 3040) / 10;
812 data1 = 1;
813 } else if (!((c - 2192) % 5)) {
814 data0 = ((2 * (c - 672)) - 3040) / 10;
815 data1 = 0;
816 } else
817 return -EINVAL;
818
819 data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
Nick Kossifidiscc6323c2008-07-20 06:44:43 +0300820 } else if ((c - (c % 5)) != 2 || c > 5435) {
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200821 if (!(c % 20) && c >= 5120) {
822 data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
823 data2 = ath5k_hw_bitswap(3, 2);
824 } else if (!(c % 10)) {
825 data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
826 data2 = ath5k_hw_bitswap(2, 2);
827 } else if (!(c % 5)) {
828 data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
829 data2 = ath5k_hw_bitswap(1, 2);
830 } else
831 return -EINVAL;
Nick Kossifidiscc6323c2008-07-20 06:44:43 +0300832 } else {
833 data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
834 data2 = ath5k_hw_bitswap(0, 2);
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200835 }
836
837 data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
838
839 ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
840 ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
841
842 return 0;
843}
844
845/*
Nick Kossifidiscc6323c2008-07-20 06:44:43 +0300846 * Set the channel on the RF2425
847 */
848static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah,
849 struct ieee80211_channel *channel)
850{
851 u32 data, data0, data2;
852 u16 c;
853
854 data = data0 = data2 = 0;
855 c = channel->center_freq;
856
857 if (c < 4800) {
858 data0 = ath5k_hw_bitswap((c - 2272), 8);
859 data2 = 0;
860 /* ? 5GHz ? */
861 } else if ((c - (c % 5)) != 2 || c > 5435) {
862 if (!(c % 20) && c < 5120)
863 data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
864 else if (!(c % 10))
865 data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
866 else if (!(c % 5))
867 data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
868 else
869 return -EINVAL;
870 data2 = ath5k_hw_bitswap(1, 2);
871 } else {
872 data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
873 data2 = ath5k_hw_bitswap(0, 2);
874 }
875
876 data = (data0 << 4) | data2 << 2 | 0x1001;
877
878 ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
879 ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
880
881 return 0;
882}
883
884/*
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200885 * Set a channel on the radio chip
886 */
887int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
888{
889 int ret;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200890 /*
Luis R. Rodriguez400ec452008-02-03 21:51:49 -0500891 * Check bounds supported by the PHY (we don't care about regultory
892 * restrictions at this point). Note: hw_value already has the band
893 * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
894 * of the band by that */
895 if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200896 ATH5K_ERR(ah->ah_sc,
Luis R. Rodriguez400ec452008-02-03 21:51:49 -0500897 "channel frequency (%u MHz) out of supported "
898 "band range\n",
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -0500899 channel->center_freq);
Luis R. Rodriguez400ec452008-02-03 21:51:49 -0500900 return -EINVAL;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200901 }
902
903 /*
904 * Set the channel and wait
905 */
906 switch (ah->ah_radio) {
907 case AR5K_RF5110:
908 ret = ath5k_hw_rf5110_channel(ah, channel);
909 break;
910 case AR5K_RF5111:
911 ret = ath5k_hw_rf5111_channel(ah, channel);
912 break;
Nick Kossifidiscc6323c2008-07-20 06:44:43 +0300913 case AR5K_RF2425:
914 ret = ath5k_hw_rf2425_channel(ah, channel);
915 break;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200916 default:
917 ret = ath5k_hw_rf5112_channel(ah, channel);
918 break;
919 }
920
921 if (ret)
922 return ret;
923
Nick Kossifidiscc6323c2008-07-20 06:44:43 +0300924 /* Set JAPAN setting for channel 14 */
925 if (channel->center_freq == 2484) {
926 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
927 AR5K_PHY_CCKTXCTL_JAPAN);
928 } else {
929 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
930 AR5K_PHY_CCKTXCTL_WORLD);
931 }
932
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -0500933 ah->ah_current_channel.center_freq = channel->center_freq;
934 ah->ah_current_channel.hw_value = channel->hw_value;
935 ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200936
937 return 0;
938}
939
940/*****************\
941 PHY calibration
942\*****************/
943
944/**
945 * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
946 *
947 * @ah: struct ath5k_hw pointer we are operating on
948 * @freq: the channel frequency, just used for error logging
949 *
950 * This function performs a noise floor calibration of the PHY and waits for
951 * it to complete. Then the noise floor value is compared to some maximum
952 * noise floor we consider valid.
953 *
954 * Note that this is different from what the madwifi HAL does: it reads the
955 * noise floor and afterwards initiates the calibration. Since the noise floor
956 * calibration can take some time to finish, depending on the current channel
957 * use, that avoids the occasional timeout warnings we are seeing now.
958 *
959 * See the following link for an Atheros patent on noise floor calibration:
960 * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
961 * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
962 *
Nick Kossifidisf860ee22008-07-20 06:47:12 +0300963 * XXX: Since during noise floor calibration antennas are detached according to
964 * the patent, we should stop tx queues here.
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200965 */
966int
967ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
968{
969 int ret;
970 unsigned int i;
971 s32 noise_floor;
972
973 /*
Nick Kossifidisf860ee22008-07-20 06:47:12 +0300974 * Enable noise floor calibration
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200975 */
976 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
977 AR5K_PHY_AGCCTL_NF);
978
979 ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
980 AR5K_PHY_AGCCTL_NF, 0, false);
981 if (ret) {
982 ATH5K_ERR(ah->ah_sc,
983 "noise floor calibration timeout (%uMHz)\n", freq);
Nick Kossifidisf860ee22008-07-20 06:47:12 +0300984 return -EAGAIN;
Jiri Slabyfa1c1142007-08-12 17:33:16 +0200985 }
986
987 /* Wait until the noise floor is calibrated and read the value */
988 for (i = 20; i > 0; i--) {
989 mdelay(1);
990 noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
991 noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
992 if (noise_floor & AR5K_PHY_NF_ACTIVE) {
993 noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
994
995 if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
996 break;
997 }
998 }
999
1000 ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
1001 "noise floor %d\n", noise_floor);
1002
1003 if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
1004 ATH5K_ERR(ah->ah_sc,
1005 "noise floor calibration failed (%uMHz)\n", freq);
Nick Kossifidisf860ee22008-07-20 06:47:12 +03001006 return -EAGAIN;
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001007 }
1008
1009 ah->ah_noise_floor = noise_floor;
1010
1011 return 0;
1012}
1013
1014/*
1015 * Perform a PHY calibration on RF5110
1016 * -Fix BPSK/QAM Constellation (I/Q correction)
1017 * -Calculate Noise Floor
1018 */
1019static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
1020 struct ieee80211_channel *channel)
1021{
1022 u32 phy_sig, phy_agc, phy_sat, beacon;
1023 int ret;
1024
1025 /*
1026 * Disable beacons and RX/TX queues, wait
1027 */
1028 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
1029 AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
1030 beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
1031 ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
1032
Nick Kossifidis84e463f2008-09-17 03:33:19 +03001033 mdelay(2);
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001034
1035 /*
1036 * Set the channel (with AGC turned off)
1037 */
1038 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
1039 udelay(10);
1040 ret = ath5k_hw_channel(ah, channel);
1041
1042 /*
1043 * Activate PHY and wait
1044 */
1045 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
1046 mdelay(1);
1047
1048 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
1049
1050 if (ret)
1051 return ret;
1052
1053 /*
1054 * Calibrate the radio chip
1055 */
1056
1057 /* Remember normal state */
1058 phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG);
1059 phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE);
1060 phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT);
1061
1062 /* Update radio registers */
1063 ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) |
1064 AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG);
1065
1066 ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI |
1067 AR5K_PHY_AGCCOARSE_LO)) |
1068 AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) |
1069 AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE);
1070
1071 ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT |
1072 AR5K_PHY_ADCSAT_THR)) |
1073 AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) |
1074 AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT);
1075
1076 udelay(20);
1077
1078 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
1079 udelay(10);
1080 ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG);
1081 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
1082
1083 mdelay(1);
1084
1085 /*
1086 * Enable calibration and wait until completion
1087 */
1088 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL);
1089
1090 ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
1091 AR5K_PHY_AGCCTL_CAL, 0, false);
1092
1093 /* Reset to normal state */
1094 ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG);
1095 ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE);
1096 ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
1097
1098 if (ret) {
1099 ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -05001100 channel->center_freq);
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001101 return ret;
1102 }
1103
Felix Fietkau8b0162a2008-11-03 11:27:38 +01001104 ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001105
1106 /*
1107 * Re-enable RX/TX and beacons
1108 */
1109 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
1110 AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
1111 ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
1112
1113 return 0;
1114}
1115
1116/*
Nick Kossifidisf860ee22008-07-20 06:47:12 +03001117 * Perform a PHY calibration on RF5111/5112 and newer chips
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001118 */
1119static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
1120 struct ieee80211_channel *channel)
1121{
1122 u32 i_pwr, q_pwr;
1123 s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
Nick Kossifidisf860ee22008-07-20 06:47:12 +03001124 int i;
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001125 ATH5K_TRACE(ah->ah_sc);
1126
Joe Perchese9010e22008-03-07 14:21:16 -08001127 if (!ah->ah_calibration ||
Nick Kossifidisf860ee22008-07-20 06:47:12 +03001128 ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001129 goto done;
1130
Nick Kossifidisf860ee22008-07-20 06:47:12 +03001131 /* Calibration has finished, get the results and re-run */
1132 for (i = 0; i <= 10; i++) {
1133 iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
1134 i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
1135 q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
1136 }
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001137
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001138 i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
Nick Kossifidisf860ee22008-07-20 06:47:12 +03001139 q_coffd = q_pwr >> 7;
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001140
Nick Kossifidisf860ee22008-07-20 06:47:12 +03001141 /* No correction */
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001142 if (i_coffd == 0 || q_coffd == 0)
1143 goto done;
1144
1145 i_coff = ((-iq_corr) / i_coffd) & 0x3f;
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001146
Nick Kossifidisf860ee22008-07-20 06:47:12 +03001147 /* Boundary check */
1148 if (i_coff > 31)
1149 i_coff = 31;
1150 if (i_coff < -32)
1151 i_coff = -32;
1152
1153 q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f;
1154
1155 /* Boundary check */
1156 if (q_coff > 15)
1157 q_coff = 15;
1158 if (q_coff < -16)
1159 q_coff = -16;
1160
1161 /* Commit new I/Q value */
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001162 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE |
1163 ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
1164
Nick Kossifidisf860ee22008-07-20 06:47:12 +03001165 /* Re-enable calibration -if we don't we'll commit
1166 * the same values again and again */
1167 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
1168 AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
1169 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN);
1170
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001171done:
Nick Kossifidisf860ee22008-07-20 06:47:12 +03001172
1173 /* TODO: Separate noise floor calibration from I/Q calibration
1174 * since noise floor calibration interrupts rx path while I/Q
1175 * calibration doesn't. We don't need to run noise floor calibration
1176 * as often as I/Q calibration.*/
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -05001177 ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001178
1179 /* Request RF gain */
Luis R. Rodriguezd8ee3982008-02-03 21:51:04 -05001180 if (channel->hw_value & CHANNEL_5GHZ) {
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001181 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max,
1182 AR5K_PHY_PAPD_PROBE_TXPOWER) |
1183 AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
1184 ah->ah_rf_gain = AR5K_RFGAIN_READ_REQUESTED;
1185 }
1186
1187 return 0;
1188}
1189
1190/*
1191 * Perform a PHY calibration
1192 */
1193int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
1194 struct ieee80211_channel *channel)
1195{
1196 int ret;
1197
1198 if (ah->ah_radio == AR5K_RF5110)
1199 ret = ath5k_hw_rf5110_calibrate(ah, channel);
1200 else
1201 ret = ath5k_hw_rf511x_calibrate(ah, channel);
1202
1203 return ret;
1204}
1205
1206int ath5k_hw_phy_disable(struct ath5k_hw *ah)
1207{
1208 ATH5K_TRACE(ah->ah_sc);
1209 /*Just a try M.F.*/
1210 ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
1211
1212 return 0;
1213}
1214
1215/********************\
1216 Misc PHY functions
1217\********************/
1218
1219/*
1220 * Get the PHY Chip revision
1221 */
1222u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
1223{
1224 unsigned int i;
1225 u32 srev;
1226 u16 ret;
1227
1228 ATH5K_TRACE(ah->ah_sc);
1229
1230 /*
1231 * Set the radio chip access register
1232 */
1233 switch (chan) {
1234 case CHANNEL_2GHZ:
1235 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
1236 break;
1237 case CHANNEL_5GHZ:
1238 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
1239 break;
1240 default:
1241 return 0;
1242 }
1243
1244 mdelay(2);
1245
1246 /* ...wait until PHY is ready and read the selected radio revision */
1247 ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
1248
1249 for (i = 0; i < 8; i++)
1250 ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
1251
1252 if (ah->ah_version == AR5K_AR5210) {
1253 srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
1254 ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
1255 } else {
1256 srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
1257 ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
1258 ((srev & 0x0f) << 4), 8);
1259 }
1260
1261 /* Reset to the 5GHz mode */
1262 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
1263
1264 return ret;
1265}
1266
1267void /*TODO:Boundary check*/
1268ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant)
1269{
1270 ATH5K_TRACE(ah->ah_sc);
1271 /*Just a try M.F.*/
1272 if (ah->ah_version != AR5K_AR5210)
1273 ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA);
1274}
1275
1276unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah)
1277{
1278 ATH5K_TRACE(ah->ah_sc);
1279 /*Just a try M.F.*/
1280 if (ah->ah_version != AR5K_AR5210)
1281 return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
1282
1283 return false; /*XXX: What do we return for 5210 ?*/
1284}
1285
1286/*
1287 * TX power setup
1288 */
1289
1290/*
1291 * Initialize the tx power table (not fully implemented)
1292 */
1293static void ath5k_txpower_table(struct ath5k_hw *ah,
1294 struct ieee80211_channel *channel, s16 max_power)
1295{
1296 unsigned int i, min, max, n;
1297 u16 txpower, *rates;
1298
1299 rates = ah->ah_txpower.txp_rates;
1300
1301 txpower = AR5K_TUNE_DEFAULT_TXPOWER * 2;
1302 if (max_power > txpower)
1303 txpower = max_power > AR5K_TUNE_MAX_TXPOWER ?
1304 AR5K_TUNE_MAX_TXPOWER : max_power;
1305
1306 for (i = 0; i < AR5K_MAX_RATES; i++)
1307 rates[i] = txpower;
1308
1309 /* XXX setup target powers by rate */
1310
1311 ah->ah_txpower.txp_min = rates[7];
1312 ah->ah_txpower.txp_max = rates[0];
1313 ah->ah_txpower.txp_ofdm = rates[0];
1314
1315 /* Calculate the power table */
1316 n = ARRAY_SIZE(ah->ah_txpower.txp_pcdac);
1317 min = AR5K_EEPROM_PCDAC_START;
1318 max = AR5K_EEPROM_PCDAC_STOP;
1319 for (i = 0; i < n; i += AR5K_EEPROM_PCDAC_STEP)
1320 ah->ah_txpower.txp_pcdac[i] =
1321#ifdef notyet
1322 min + ((i * (max - min)) / n);
1323#else
1324 min;
1325#endif
1326}
1327
1328/*
1329 * Set transmition power
1330 */
1331int /*O.K. - txpower_table is unimplemented so this doesn't work*/
1332ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
1333 unsigned int txpower)
1334{
1335 bool tpc = ah->ah_txpower.txp_tpc;
1336 unsigned int i;
1337
1338 ATH5K_TRACE(ah->ah_sc);
1339 if (txpower > AR5K_TUNE_MAX_TXPOWER) {
1340 ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
1341 return -EINVAL;
1342 }
1343
Nick Kossifidis903b4742008-02-28 14:50:50 -05001344 /*
1345 * RF2413 for some reason can't
1346 * transmit anything if we call
1347 * this funtion, so we skip it
1348 * until we fix txpower.
Nick Kossifidis136bfc72008-04-16 18:42:48 +03001349 *
1350 * XXX: Assume same for RF2425
1351 * to be safe.
Nick Kossifidis903b4742008-02-28 14:50:50 -05001352 */
Nick Kossifidis136bfc72008-04-16 18:42:48 +03001353 if ((ah->ah_radio == AR5K_RF2413) || (ah->ah_radio == AR5K_RF2425))
Nick Kossifidis903b4742008-02-28 14:50:50 -05001354 return 0;
1355
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001356 /* Reset TX power values */
1357 memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
1358 ah->ah_txpower.txp_tpc = tpc;
1359
1360 /* Initialize TX power table */
1361 ath5k_txpower_table(ah, channel, txpower);
1362
1363 /*
1364 * Write TX power values
1365 */
1366 for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
1367 ath5k_hw_reg_write(ah,
1368 ((((ah->ah_txpower.txp_pcdac[(i << 1) + 1] << 8) | 0xff) & 0xffff) << 16) |
1369 (((ah->ah_txpower.txp_pcdac[(i << 1) ] << 8) | 0xff) & 0xffff),
1370 AR5K_PHY_PCDAC_TXPOWER(i));
1371 }
1372
1373 ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) |
1374 AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) |
1375 AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1);
1376
1377 ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) |
1378 AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) |
1379 AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2);
1380
1381 ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) |
1382 AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) |
1383 AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3);
1384
1385 ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) |
1386 AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
1387 AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
1388
Joe Perchese9010e22008-03-07 14:21:16 -08001389 if (ah->ah_txpower.txp_tpc)
Jiri Slabyfa1c1142007-08-12 17:33:16 +02001390 ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
1391 AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
1392 else
1393 ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
1394 AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
1395
1396 return 0;
1397}
1398
1399int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power)
1400{
1401 /*Just a try M.F.*/
1402 struct ieee80211_channel *channel = &ah->ah_current_channel;
1403
1404 ATH5K_TRACE(ah->ah_sc);
1405 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
1406 "changing txpower to %d\n", power);
1407
1408 return ath5k_hw_txpower(ah, channel, power);
1409}
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001410
1411#undef _ATH5K_PHY