1 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
2 +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
3 @@ -786,6 +786,102 @@ int ar9003_paprd_setup_gain_table(struct
5 EXPORT_SYMBOL(ar9003_paprd_setup_gain_table);
7 +static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah,
8 + struct ath9k_hw_cal_data *caldata,
11 + u32 *pa_in = caldata->pa_table[chain];
12 + int capdiv_offset, quick_drop_offset;
13 + int capdiv2g, quick_drop;
17 + if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah))
20 + capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
21 + AR_PHY_65NM_CH0_TXRF3_CAPDIV2G);
23 + quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
24 + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP);
29 + for (i = 0; i < NUM_BIN + 1; i++) {
30 + if (pa_in[i] == 1400)
34 + if (AR_SREV_9485(ah)) {
35 + if (pa_in[23] < 800) {
36 + capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150);
37 + capdiv2g += capdiv_offset;
40 + if (pa_in[23] < 600) {
46 + } else if (pa_in[23] == 1400) {
47 + quick_drop_offset = min_t(int, count / 3, 2);
48 + quick_drop += quick_drop_offset;
49 + capdiv2g += quick_drop_offset / 2;
54 + if (quick_drop > 0) {
56 + capdiv2g -= quick_drop_offset;
63 + } else if (AR_SREV_9330(ah)) {
64 + if (pa_in[23] < 1000) {
65 + capdiv_offset = (1000 - pa_in[23]) / 100;
66 + capdiv2g += capdiv_offset;
67 + if (capdiv_offset > 3) {
72 + capdiv2g += capdiv_offset;
75 + if (quick_drop < -4)
77 + } else if (pa_in[23] == 1400) {
80 + capdiv2g -= count / 4;
81 + if (quick_drop > -2)
94 + REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
95 + AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g);
96 + REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
97 + AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
103 int ar9003_paprd_create_curve(struct ath_hw *ah,
104 struct ath9k_hw_cal_data *caldata, int chain)
106 @@ -821,6 +917,9 @@ int ar9003_paprd_create_curve(struct ath
107 if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))
110 + if (ar9003_paprd_retrain_pa_in(ah, caldata, chain))
111 + status = -EINPROGRESS;
113 REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
114 AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
116 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
117 +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
119 #define AR_PHY_AIC_CTRL_4_B0 (AR_SM_BASE + 0x4c0)
120 #define AR_PHY_AIC_STAT_2_B0 (AR_SM_BASE + 0x4cc)
122 +#define AR_PHY_65NM_CH0_TXRF3 0x16048
123 +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G 0x0000001e
124 +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S 1
126 #define AR_PHY_65NM_CH0_SYNTH4 0x1608c
127 #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002)
128 #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1)
129 --- a/drivers/net/wireless/ath/ath9k/link.c
130 +++ b/drivers/net/wireless/ath/ath9k/link.c
131 @@ -254,6 +254,7 @@ void ath_paprd_calibrate(struct work_str
139 @@ -302,7 +303,13 @@ void ath_paprd_calibrate(struct work_str
143 - if (ar9003_paprd_create_curve(ah, caldata, chain)) {
144 + ret = ar9003_paprd_create_curve(ah, caldata, chain);
145 + if (ret == -EINPROGRESS) {
146 + ath_dbg(common, CALIBRATE,
147 + "PAPRD curve on chain %d needs to be re-trained\n",
151 ath_dbg(common, CALIBRATE,
152 "PAPRD create curve failed on chain %d\n",