aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2014-02-06 23:59:53 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-02-12 15:36:07 -0500
commit97fe6420c9a362ac9d0749db44b7b6629583813b (patch)
treeb7fd07af7b1436ace4046baece39f277ba7b1987
parentadddc0d20bf4476380da94bfda8c591c49bb6cde (diff)
ath9k: Modify IQ calibration for AR955x
IQ calibration post-processing for AR955x is different from other chips - instead of just doing it as part of AGC calibration once, it is triggered 3 times and a median is determined. This patch adds initial support for changing the calibration behavior for AR955x. Also, to simplify things, a helper routine to issue/poll AGC calibration is used. For non-AR955x chips, the iqcal_idx (which will be used in subsequent patches) is set to zero. Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c81
1 files changed, 59 insertions, 22 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 12310e19275d..327befa06699 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -23,6 +23,7 @@
23#define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT 23#define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
24#define MAX_MAG_DELTA 11 24#define MAX_MAG_DELTA 11
25#define MAX_PHS_DELTA 10 25#define MAX_PHS_DELTA 10
26#define MAXIQCAL 3
26 27
27struct coeff { 28struct coeff {
28 int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; 29 int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
@@ -797,7 +798,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
797 if (q_q_coff > 63) 798 if (q_q_coff > 63)
798 q_q_coff = 63; 799 q_q_coff = 63;
799 800
800 iqc_coeff[0] = (q_q_coff * 128) + q_i_coff; 801 iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
801 802
802 ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n", 803 ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
803 chain_idx, iqc_coeff[0]); 804 chain_idx, iqc_coeff[0]);
@@ -828,7 +829,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
828 if (q_q_coff > 63) 829 if (q_q_coff > 63)
829 q_q_coff = 63; 830 q_q_coff = 63;
830 831
831 iqc_coeff[1] = (q_q_coff * 128) + q_i_coff; 832 iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
832 833
833 ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n", 834 ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
834 chain_idx, iqc_coeff[1]); 835 chain_idx, iqc_coeff[1]);
@@ -991,7 +992,9 @@ static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
991 return true; 992 return true;
992} 993}
993 994
994static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable) 995static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
996 int iqcal_idx,
997 bool is_reusable)
995{ 998{
996 struct ath_common *common = ath9k_hw_common(ah); 999 struct ath_common *common = ath9k_hw_common(ah);
997 const u32 txiqcal_status[AR9300_MAX_CHAINS] = { 1000 const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
@@ -1410,7 +1413,7 @@ skip_tx_iqcal:
1410 } 1413 }
1411 1414
1412 if (txiqcal_done) 1415 if (txiqcal_done)
1413 ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); 1416 ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
1414 else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags)) 1417 else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
1415 ar9003_hw_tx_iq_cal_reload(ah); 1418 ar9003_hw_tx_iq_cal_reload(ah);
1416 1419
@@ -1456,6 +1459,29 @@ skip_tx_iqcal:
1456 return true; 1459 return true;
1457} 1460}
1458 1461
1462static bool do_ar9003_agc_cal(struct ath_hw *ah)
1463{
1464 struct ath_common *common = ath9k_hw_common(ah);
1465 bool status;
1466
1467 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1468 REG_READ(ah, AR_PHY_AGC_CONTROL) |
1469 AR_PHY_AGC_CONTROL_CAL);
1470
1471 status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
1472 AR_PHY_AGC_CONTROL_CAL,
1473 0, AH_WAIT_TIMEOUT);
1474 if (!status) {
1475 ath_dbg(common, CALIBRATE,
1476 "offset calibration failed to complete in %d ms,"
1477 "noisy environment?\n",
1478 AH_WAIT_TIMEOUT / 1000);
1479 return false;
1480 }
1481
1482 return true;
1483}
1484
1459static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, 1485static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
1460 struct ath9k_channel *chan) 1486 struct ath9k_channel *chan)
1461{ 1487{
@@ -1464,6 +1490,7 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
1464 bool txiqcal_done = false; 1490 bool txiqcal_done = false;
1465 bool status = true; 1491 bool status = true;
1466 bool run_agc_cal = false, sep_iq_cal = false; 1492 bool run_agc_cal = false, sep_iq_cal = false;
1493 int i = 0;
1467 1494
1468 /* Use chip chainmask only for calibration */ 1495 /* Use chip chainmask only for calibration */
1469 ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); 1496 ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
@@ -1518,27 +1545,37 @@ skip_tx_iqcal:
1518 if (AR_SREV_9330_11(ah)) 1545 if (AR_SREV_9330_11(ah))
1519 ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan)); 1546 ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan));
1520 1547
1521 /* Calibrate the AGC */ 1548 /*
1522 REG_WRITE(ah, AR_PHY_AGC_CONTROL, 1549 * For non-AR9550 chips, we just trigger AGC calibration
1523 REG_READ(ah, AR_PHY_AGC_CONTROL) | 1550 * in the HW, poll for completion and then process
1524 AR_PHY_AGC_CONTROL_CAL); 1551 * the results.
1525 1552 *
1526 /* Poll for offset calibration complete */ 1553 * For AR955x, we run it multiple times and use
1527 status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, 1554 * median IQ correction.
1528 AR_PHY_AGC_CONTROL_CAL, 1555 */
1529 0, AH_WAIT_TIMEOUT); 1556 if (!AR_SREV_9550(ah)) {
1530 } 1557 status = do_ar9003_agc_cal(ah);
1558 if (!status)
1559 return false;
1531 1560
1532 if (!status) { 1561 if (txiqcal_done)
1533 ath_dbg(common, CALIBRATE, 1562 ar9003_hw_tx_iq_cal_post_proc(ah, 0, false);
1534 "offset calibration failed to complete in %d ms; noisy environment?\n", 1563 } else {
1535 AH_WAIT_TIMEOUT / 1000); 1564 if (!txiqcal_done) {
1536 return false; 1565 status = do_ar9003_agc_cal(ah);
1566 if (!status)
1567 return false;
1568 } else {
1569 for (i = 0; i < MAXIQCAL; i++) {
1570 status = do_ar9003_agc_cal(ah);
1571 if (!status)
1572 return false;
1573 ar9003_hw_tx_iq_cal_post_proc(ah, i, false);
1574 }
1575 }
1576 }
1537 } 1577 }
1538 1578
1539 if (txiqcal_done)
1540 ar9003_hw_tx_iq_cal_post_proc(ah, false);
1541
1542 /* Revert chainmask to runtime parameters */ 1579 /* Revert chainmask to runtime parameters */
1543 ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); 1580 ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
1544 1581