tools/firmware-utils: add tool for DIR-651-H1 firmware generation
[openwrt.git] / package / mac80211 / patches / 571-ath9k_paprd_retrain_pa_in.patch
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
4  }
5  EXPORT_SYMBOL(ar9003_paprd_setup_gain_table);
6  
7 +static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah,
8 +                                      struct ath9k_hw_cal_data *caldata,
9 +                                      int chain)
10 +{
11 +       u32 *pa_in = caldata->pa_table[chain];
12 +       int capdiv_offset, quick_drop_offset;
13 +       int capdiv2g, quick_drop;
14 +       int count = 0;
15 +       int i;
16 +
17 +       if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah))
18 +               return false;
19 +
20 +       capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
21 +                                 AR_PHY_65NM_CH0_TXRF3_CAPDIV2G);
22 +
23 +       quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
24 +                                   AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP);
25 +
26 +       if (quick_drop)
27 +               quick_drop -= 0x40;
28 +
29 +       for (i = 0; i < NUM_BIN + 1; i++) {
30 +               if (pa_in[i] == 1400)
31 +                       count++;
32 +       }
33 +
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;
38 +                       if (capdiv2g > 7) {
39 +                               capdiv2g = 7;
40 +                               if (pa_in[23] < 600) {
41 +                                       quick_drop++;
42 +                                       if (quick_drop > 0)
43 +                                               quick_drop = 0;
44 +                               }
45 +                       }
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;
50 +
51 +                       if (capdiv2g > 7)
52 +                               capdiv2g = 7;
53 +
54 +                       if (quick_drop > 0) {
55 +                               quick_drop = 0;
56 +                               capdiv2g -= quick_drop_offset;
57 +                               if (capdiv2g < 0)
58 +                                       capdiv2g = 0;
59 +                       }
60 +               } else {
61 +                       return false;
62 +               }
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) {
68 +                               capdiv_offset = 1;
69 +                               quick_drop--;
70 +                       }
71 +
72 +                       capdiv2g += capdiv_offset;
73 +                       if (capdiv2g > 6)
74 +                               capdiv2g = 6;
75 +                       if (quick_drop < -4)
76 +                               quick_drop = -4;
77 +               } else if (pa_in[23] == 1400) {
78 +                       if (count > 3) {
79 +                               quick_drop++;
80 +                               capdiv2g -= count / 4;
81 +                               if (quick_drop > -2)
82 +                                       quick_drop = -2;
83 +                       } else {
84 +                               capdiv2g--;
85 +                       }
86 +
87 +                       if (capdiv2g < 0)
88 +                               capdiv2g = 0;
89 +               } else {
90 +                       return false;
91 +               }
92 +       }
93 +
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,
98 +                     quick_drop);
99 +
100 +       return true;
101 +}
102 +
103  int ar9003_paprd_create_curve(struct ath_hw *ah,
104                               struct ath9k_hw_cal_data *caldata, int chain)
105  {
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))
108                 status = -2;
109  
110 +       if (ar9003_paprd_retrain_pa_in(ah, caldata, chain))
111 +               status = -EINPROGRESS;
112 +
113         REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
114                     AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
115  
116 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
117 +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
118 @@ -625,6 +625,10 @@
119  #define AR_PHY_AIC_CTRL_4_B0   (AR_SM_BASE + 0x4c0)
120  #define AR_PHY_AIC_STAT_2_B0   (AR_SM_BASE + 0x4cc)
121  
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
125 +
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
132         int chain_ok = 0;
133         int chain;
134         int len = 1800;
135 +       int ret;
136  
137         if (!caldata)
138                 return;
139 @@ -302,7 +303,13 @@ void ath_paprd_calibrate(struct work_str
140                         break;
141                 }
142  
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",
148 +                               chain);
149 +                       break;
150 +               } else if (ret) {
151                         ath_dbg(common, CALIBRATE,
152                                 "PAPRD create curve failed on chain %d\n",
153                                 chain);