aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c223
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.h10
2 files changed, 233 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 97e09d5f3a42..8c145cd98c1c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -326,6 +326,224 @@ static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
326 ah->supp_cals = IQ_MISMATCH_CAL; 326 ah->supp_cals = IQ_MISMATCH_CAL;
327} 327}
328 328
329#define OFF_UPPER_LT 24
330#define OFF_LOWER_LT 7
331
332static bool ar9003_hw_dynamic_osdac_selection(struct ath_hw *ah,
333 bool txiqcal_done)
334{
335 struct ath_common *common = ath9k_hw_common(ah);
336 int ch0_done, osdac_ch0, dc_off_ch0_i1, dc_off_ch0_q1, dc_off_ch0_i2,
337 dc_off_ch0_q2, dc_off_ch0_i3, dc_off_ch0_q3;
338 int ch1_done, osdac_ch1, dc_off_ch1_i1, dc_off_ch1_q1, dc_off_ch1_i2,
339 dc_off_ch1_q2, dc_off_ch1_i3, dc_off_ch1_q3;
340 int ch2_done, osdac_ch2, dc_off_ch2_i1, dc_off_ch2_q1, dc_off_ch2_i2,
341 dc_off_ch2_q2, dc_off_ch2_i3, dc_off_ch2_q3;
342 bool status;
343 u32 temp, val;
344
345 /*
346 * Clear offset and IQ calibration, run AGC cal.
347 */
348 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
349 AR_PHY_AGC_CONTROL_OFFSET_CAL);
350 REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
351 AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
352 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
353 REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
354
355 status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
356 AR_PHY_AGC_CONTROL_CAL,
357 0, AH_WAIT_TIMEOUT);
358 if (!status) {
359 ath_dbg(common, CALIBRATE,
360 "AGC cal without offset cal failed to complete in 1ms");
361 return false;
362 }
363
364 /*
365 * Allow only offset calibration and disable the others
366 * (Carrier Leak calibration, TX Filter calibration and
367 * Peak Detector offset calibration).
368 */
369 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
370 AR_PHY_AGC_CONTROL_OFFSET_CAL);
371 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL,
372 AR_PHY_CL_CAL_ENABLE);
373 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
374 AR_PHY_AGC_CONTROL_FLTR_CAL);
375 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
376 AR_PHY_AGC_CONTROL_PKDET_CAL);
377
378 ch0_done = 0;
379 ch1_done = 0;
380 ch2_done = 0;
381
382 while ((ch0_done == 0) || (ch1_done == 0) || (ch2_done == 0)) {
383 osdac_ch0 = (REG_READ(ah, AR_PHY_65NM_CH0_BB1) >> 30) & 0x3;
384 osdac_ch1 = (REG_READ(ah, AR_PHY_65NM_CH1_BB1) >> 30) & 0x3;
385 osdac_ch2 = (REG_READ(ah, AR_PHY_65NM_CH2_BB1) >> 30) & 0x3;
386
387 REG_SET_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
388
389 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
390 REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
391
392 status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
393 AR_PHY_AGC_CONTROL_CAL,
394 0, AH_WAIT_TIMEOUT);
395 if (!status) {
396 ath_dbg(common, CALIBRATE,
397 "DC offset cal failed to complete in 1ms");
398 return false;
399 }
400
401 REG_CLR_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
402
403 /*
404 * High gain.
405 */
406 REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
407 ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (1 << 8)));
408 REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
409 ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (1 << 8)));
410 REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
411 ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (1 << 8)));
412
413 temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
414 dc_off_ch0_i1 = (temp >> 26) & 0x1f;
415 dc_off_ch0_q1 = (temp >> 21) & 0x1f;
416
417 temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
418 dc_off_ch1_i1 = (temp >> 26) & 0x1f;
419 dc_off_ch1_q1 = (temp >> 21) & 0x1f;
420
421 temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
422 dc_off_ch2_i1 = (temp >> 26) & 0x1f;
423 dc_off_ch2_q1 = (temp >> 21) & 0x1f;
424
425 /*
426 * Low gain.
427 */
428 REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
429 ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (2 << 8)));
430 REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
431 ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (2 << 8)));
432 REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
433 ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (2 << 8)));
434
435 temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
436 dc_off_ch0_i2 = (temp >> 26) & 0x1f;
437 dc_off_ch0_q2 = (temp >> 21) & 0x1f;
438
439 temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
440 dc_off_ch1_i2 = (temp >> 26) & 0x1f;
441 dc_off_ch1_q2 = (temp >> 21) & 0x1f;
442
443 temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
444 dc_off_ch2_i2 = (temp >> 26) & 0x1f;
445 dc_off_ch2_q2 = (temp >> 21) & 0x1f;
446
447 /*
448 * Loopback.
449 */
450 REG_WRITE(ah, AR_PHY_65NM_CH0_BB3,
451 ((REG_READ(ah, AR_PHY_65NM_CH0_BB3) & 0xfffffcff) | (3 << 8)));
452 REG_WRITE(ah, AR_PHY_65NM_CH1_BB3,
453 ((REG_READ(ah, AR_PHY_65NM_CH1_BB3) & 0xfffffcff) | (3 << 8)));
454 REG_WRITE(ah, AR_PHY_65NM_CH2_BB3,
455 ((REG_READ(ah, AR_PHY_65NM_CH2_BB3) & 0xfffffcff) | (3 << 8)));
456
457 temp = REG_READ(ah, AR_PHY_65NM_CH0_BB3);
458 dc_off_ch0_i3 = (temp >> 26) & 0x1f;
459 dc_off_ch0_q3 = (temp >> 21) & 0x1f;
460
461 temp = REG_READ(ah, AR_PHY_65NM_CH1_BB3);
462 dc_off_ch1_i3 = (temp >> 26) & 0x1f;
463 dc_off_ch1_q3 = (temp >> 21) & 0x1f;
464
465 temp = REG_READ(ah, AR_PHY_65NM_CH2_BB3);
466 dc_off_ch2_i3 = (temp >> 26) & 0x1f;
467 dc_off_ch2_q3 = (temp >> 21) & 0x1f;
468
469 if ((dc_off_ch0_i1 > OFF_UPPER_LT) || (dc_off_ch0_i1 < OFF_LOWER_LT) ||
470 (dc_off_ch0_i2 > OFF_UPPER_LT) || (dc_off_ch0_i2 < OFF_LOWER_LT) ||
471 (dc_off_ch0_i3 > OFF_UPPER_LT) || (dc_off_ch0_i3 < OFF_LOWER_LT) ||
472 (dc_off_ch0_q1 > OFF_UPPER_LT) || (dc_off_ch0_q1 < OFF_LOWER_LT) ||
473 (dc_off_ch0_q2 > OFF_UPPER_LT) || (dc_off_ch0_q2 < OFF_LOWER_LT) ||
474 (dc_off_ch0_q3 > OFF_UPPER_LT) || (dc_off_ch0_q3 < OFF_LOWER_LT)) {
475 if (osdac_ch0 == 3) {
476 ch0_done = 1;
477 } else {
478 osdac_ch0++;
479
480 val = REG_READ(ah, AR_PHY_65NM_CH0_BB1) & 0x3fffffff;
481 val |= (osdac_ch0 << 30);
482 REG_WRITE(ah, AR_PHY_65NM_CH0_BB1, val);
483
484 ch0_done = 0;
485 }
486 } else {
487 ch0_done = 1;
488 }
489
490 if ((dc_off_ch1_i1 > OFF_UPPER_LT) || (dc_off_ch1_i1 < OFF_LOWER_LT) ||
491 (dc_off_ch1_i2 > OFF_UPPER_LT) || (dc_off_ch1_i2 < OFF_LOWER_LT) ||
492 (dc_off_ch1_i3 > OFF_UPPER_LT) || (dc_off_ch1_i3 < OFF_LOWER_LT) ||
493 (dc_off_ch1_q1 > OFF_UPPER_LT) || (dc_off_ch1_q1 < OFF_LOWER_LT) ||
494 (dc_off_ch1_q2 > OFF_UPPER_LT) || (dc_off_ch1_q2 < OFF_LOWER_LT) ||
495 (dc_off_ch1_q3 > OFF_UPPER_LT) || (dc_off_ch1_q3 < OFF_LOWER_LT)) {
496 if (osdac_ch1 == 3) {
497 ch1_done = 1;
498 } else {
499 osdac_ch1++;
500
501 val = REG_READ(ah, AR_PHY_65NM_CH1_BB1) & 0x3fffffff;
502 val |= (osdac_ch1 << 30);
503 REG_WRITE(ah, AR_PHY_65NM_CH1_BB1, val);
504
505 ch1_done = 0;
506 }
507 } else {
508 ch1_done = 1;
509 }
510
511 if ((dc_off_ch2_i1 > OFF_UPPER_LT) || (dc_off_ch2_i1 < OFF_LOWER_LT) ||
512 (dc_off_ch2_i2 > OFF_UPPER_LT) || (dc_off_ch2_i2 < OFF_LOWER_LT) ||
513 (dc_off_ch2_i3 > OFF_UPPER_LT) || (dc_off_ch2_i3 < OFF_LOWER_LT) ||
514 (dc_off_ch2_q1 > OFF_UPPER_LT) || (dc_off_ch2_q1 < OFF_LOWER_LT) ||
515 (dc_off_ch2_q2 > OFF_UPPER_LT) || (dc_off_ch2_q2 < OFF_LOWER_LT) ||
516 (dc_off_ch2_q3 > OFF_UPPER_LT) || (dc_off_ch2_q3 < OFF_LOWER_LT)) {
517 if (osdac_ch2 == 3) {
518 ch2_done = 1;
519 } else {
520 osdac_ch2++;
521
522 val = REG_READ(ah, AR_PHY_65NM_CH2_BB1) & 0x3fffffff;
523 val |= (osdac_ch2 << 30);
524 REG_WRITE(ah, AR_PHY_65NM_CH2_BB1, val);
525
526 ch2_done = 0;
527 }
528 } else {
529 ch2_done = 1;
530 }
531 }
532
533 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
534 AR_PHY_AGC_CONTROL_OFFSET_CAL);
535 REG_SET_BIT(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
536
537 /*
538 * We don't need to check txiqcal_done here since it is always
539 * set for AR9550.
540 */
541 REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
542 AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
543
544 return true;
545}
546
329/* 547/*
330 * solve 4x4 linear equation used in loopback iq cal. 548 * solve 4x4 linear equation used in loopback iq cal.
331 */ 549 */
@@ -1271,6 +1489,11 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
1271 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); 1489 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
1272 } 1490 }
1273 1491
1492 if (AR_SREV_9550(ah) && IS_CHAN_2GHZ(chan)) {
1493 if (!ar9003_hw_dynamic_osdac_selection(ah, txiqcal_done))
1494 return false;
1495 }
1496
1274skip_tx_iqcal: 1497skip_tx_iqcal:
1275 if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { 1498 if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
1276 if (AR_SREV_9330_11(ah)) 1499 if (AR_SREV_9330_11(ah))
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index 94a8598d0e95..50767155c05b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -670,6 +670,16 @@
670#define AR_PHY_65NM_CH1_RXTX4 0x1650c 670#define AR_PHY_65NM_CH1_RXTX4 0x1650c
671#define AR_PHY_65NM_CH2_RXTX4 0x1690c 671#define AR_PHY_65NM_CH2_RXTX4 0x1690c
672 672
673#define AR_PHY_65NM_CH0_BB1 0x16140
674#define AR_PHY_65NM_CH0_BB2 0x16144
675#define AR_PHY_65NM_CH0_BB3 0x16148
676#define AR_PHY_65NM_CH1_BB1 0x16540
677#define AR_PHY_65NM_CH1_BB2 0x16544
678#define AR_PHY_65NM_CH1_BB3 0x16548
679#define AR_PHY_65NM_CH2_BB1 0x16940
680#define AR_PHY_65NM_CH2_BB2 0x16944
681#define AR_PHY_65NM_CH2_BB3 0x16948
682
673#define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3 0x00780000 683#define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3 0x00780000
674#define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3_S 19 684#define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3_S 19
675#define AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK 0x00000004 685#define AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK 0x00000004