ath9k: improve reliability of the noise floor calibration
[openwrt/svn-archive/archive.git] / package / mac80211 / patches / 526-ath9k_improve_nf_cal.patch
1 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
2 +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
3 @@ -1518,77 +1518,6 @@ static void ar5008_hw_do_getnf(struct at
4 nfarray[5] = sign_extend(nf, 9);
5 }
6
7 -static void ar5008_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
8 -{
9 - struct ath9k_nfcal_hist *h;
10 - int i, j;
11 - int32_t val;
12 - const u32 ar5416_cca_regs[6] = {
13 - AR_PHY_CCA,
14 - AR_PHY_CH1_CCA,
15 - AR_PHY_CH2_CCA,
16 - AR_PHY_EXT_CCA,
17 - AR_PHY_CH1_EXT_CCA,
18 - AR_PHY_CH2_EXT_CCA
19 - };
20 - u8 chainmask, rx_chain_status;
21 -
22 - rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK);
23 - if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
24 - chainmask = 0x9;
25 - else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
26 - if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4))
27 - chainmask = 0x1B;
28 - else
29 - chainmask = 0x09;
30 - } else {
31 - if (rx_chain_status & 0x4)
32 - chainmask = 0x3F;
33 - else if (rx_chain_status & 0x2)
34 - chainmask = 0x1B;
35 - else
36 - chainmask = 0x09;
37 - }
38 -
39 - h = ah->nfCalHist;
40 -
41 - for (i = 0; i < NUM_NF_READINGS; i++) {
42 - if (chainmask & (1 << i)) {
43 - val = REG_READ(ah, ar5416_cca_regs[i]);
44 - val &= 0xFFFFFE00;
45 - val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
46 - REG_WRITE(ah, ar5416_cca_regs[i], val);
47 - }
48 - }
49 -
50 - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
51 - AR_PHY_AGC_CONTROL_ENABLE_NF);
52 - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
53 - AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
54 - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
55 -
56 - for (j = 0; j < 5; j++) {
57 - if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
58 - AR_PHY_AGC_CONTROL_NF) == 0)
59 - break;
60 - udelay(50);
61 - }
62 -
63 - ENABLE_REGWRITE_BUFFER(ah);
64 -
65 - for (i = 0; i < NUM_NF_READINGS; i++) {
66 - if (chainmask & (1 << i)) {
67 - val = REG_READ(ah, ar5416_cca_regs[i]);
68 - val &= 0xFFFFFE00;
69 - val |= (((u32) (-50) << 1) & 0x1ff);
70 - REG_WRITE(ah, ar5416_cca_regs[i], val);
71 - }
72 - }
73 -
74 - REGWRITE_BUFFER_FLUSH(ah);
75 - DISABLE_REGWRITE_BUFFER(ah);
76 -}
77 -
78 /*
79 * Initialize the ANI register values with default (ini) values.
80 * This routine is called during a (full) hardware reset after
81 @@ -1666,6 +1595,14 @@ static void ar5008_hw_set_nf_limits(stru
82 void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
83 {
84 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
85 + const u32 ar5416_cca_regs[6] = {
86 + AR_PHY_CCA,
87 + AR_PHY_CH1_CCA,
88 + AR_PHY_CH2_CCA,
89 + AR_PHY_EXT_CCA,
90 + AR_PHY_CH1_EXT_CCA,
91 + AR_PHY_CH2_EXT_CCA
92 + };
93
94 priv_ops->rf_set_freq = ar5008_hw_set_channel;
95 priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;
96 @@ -1685,7 +1622,6 @@ void ar5008_hw_attach_phy_ops(struct ath
97 priv_ops->restore_chainmask = ar5008_restore_chainmask;
98 priv_ops->set_diversity = ar5008_set_diversity;
99 priv_ops->do_getnf = ar5008_hw_do_getnf;
100 - priv_ops->loadnf = ar5008_hw_loadnf;
101
102 if (modparam_force_new_ani) {
103 priv_ops->ani_control = ar5008_hw_ani_control_new;
104 @@ -1701,4 +1637,5 @@ void ar5008_hw_attach_phy_ops(struct ath
105 priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
106
107 ar5008_hw_set_nf_limits(ah);
108 + memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs));
109 }
110 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
111 +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
112 @@ -1050,106 +1050,6 @@ static void ar9003_hw_set_nf_limits(stru
113 }
114
115 /*
116 - * Find out which of the RX chains are enabled
117 - */
118 -static u32 ar9003_hw_get_rx_chainmask(struct ath_hw *ah)
119 -{
120 - u32 chain = REG_READ(ah, AR_PHY_RX_CHAINMASK);
121 - /*
122 - * The bits [2:0] indicate the rx chain mask and are to be
123 - * interpreted as follows:
124 - * 00x => Only chain 0 is enabled
125 - * 01x => Chain 1 and 0 enabled
126 - * 1xx => Chain 2,1 and 0 enabled
127 - */
128 - return chain & 0x7;
129 -}
130 -
131 -static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
132 -{
133 - struct ath9k_nfcal_hist *h;
134 - unsigned i, j;
135 - int32_t val;
136 - const u32 ar9300_cca_regs[6] = {
137 - AR_PHY_CCA_0,
138 - AR_PHY_CCA_1,
139 - AR_PHY_CCA_2,
140 - AR_PHY_EXT_CCA,
141 - AR_PHY_EXT_CCA_1,
142 - AR_PHY_EXT_CCA_2,
143 - };
144 - u8 chainmask, rx_chain_status;
145 - struct ath_common *common = ath9k_hw_common(ah);
146 -
147 - rx_chain_status = ar9003_hw_get_rx_chainmask(ah);
148 -
149 - chainmask = 0x3F;
150 - h = ah->nfCalHist;
151 -
152 - for (i = 0; i < NUM_NF_READINGS; i++) {
153 - if (chainmask & (1 << i)) {
154 - val = REG_READ(ah, ar9300_cca_regs[i]);
155 - val &= 0xFFFFFE00;
156 - val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
157 - REG_WRITE(ah, ar9300_cca_regs[i], val);
158 - }
159 - }
160 -
161 - /*
162 - * Load software filtered NF value into baseband internal minCCApwr
163 - * variable.
164 - */
165 - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
166 - AR_PHY_AGC_CONTROL_ENABLE_NF);
167 - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
168 - AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
169 - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
170 -
171 - /*
172 - * Wait for load to complete, should be fast, a few 10s of us.
173 - * The max delay was changed from an original 250us to 10000us
174 - * since 250us often results in NF load timeout and causes deaf
175 - * condition during stress testing 12/12/2009
176 - */
177 - for (j = 0; j < 1000; j++) {
178 - if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
179 - AR_PHY_AGC_CONTROL_NF) == 0)
180 - break;
181 - udelay(10);
182 - }
183 -
184 - /*
185 - * We timed out waiting for the noisefloor to load, probably due to an
186 - * in-progress rx. Simply return here and allow the load plenty of time
187 - * to complete before the next calibration interval. We need to avoid
188 - * trying to load -50 (which happens below) while the previous load is
189 - * still in progress as this can cause rx deafness. Instead by returning
190 - * here, the baseband nf cal will just be capped by our present
191 - * noisefloor until the next calibration timer.
192 - */
193 - if (j == 1000) {
194 - ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf "
195 - "to load: AR_PHY_AGC_CONTROL=0x%x\n",
196 - REG_READ(ah, AR_PHY_AGC_CONTROL));
197 - return;
198 - }
199 -
200 - /*
201 - * Restore maxCCAPower register parameter again so that we're not capped
202 - * by the median we just loaded. This will be initial (and max) value
203 - * of next noise floor calibration the baseband does.
204 - */
205 - for (i = 0; i < NUM_NF_READINGS; i++) {
206 - if (chainmask & (1 << i)) {
207 - val = REG_READ(ah, ar9300_cca_regs[i]);
208 - val &= 0xFFFFFE00;
209 - val |= (((u32) (-50) << 1) & 0x1ff);
210 - REG_WRITE(ah, ar9300_cca_regs[i], val);
211 - }
212 - }
213 -}
214 -
215 -/*
216 * Initialize the ANI register values with default (ini) values.
217 * This routine is called during a (full) hardware reset after
218 * all the registers are initialised from the INI.
219 @@ -1216,6 +1116,14 @@ static void ar9003_hw_ani_cache_ini_regs
220 void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
221 {
222 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
223 + const u32 ar9300_cca_regs[6] = {
224 + AR_PHY_CCA_0,
225 + AR_PHY_CCA_1,
226 + AR_PHY_CCA_2,
227 + AR_PHY_EXT_CCA,
228 + AR_PHY_EXT_CCA_1,
229 + AR_PHY_EXT_CCA_2,
230 + };
231
232 priv_ops->rf_set_freq = ar9003_hw_set_channel;
233 priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate;
234 @@ -1232,10 +1140,10 @@ void ar9003_hw_attach_phy_ops(struct ath
235 priv_ops->set_diversity = ar9003_hw_set_diversity;
236 priv_ops->ani_control = ar9003_hw_ani_control;
237 priv_ops->do_getnf = ar9003_hw_do_getnf;
238 - priv_ops->loadnf = ar9003_hw_loadnf;
239 priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
240
241 ar9003_hw_set_nf_limits(ah);
242 + memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs));
243 }
244
245 void ar9003_hw_bb_watchdog_config(struct ath_hw *ah)
246 --- a/drivers/net/wireless/ath/ath9k/calib.c
247 +++ b/drivers/net/wireless/ath/ath9k/calib.c
248 @@ -167,6 +167,100 @@ void ath9k_hw_start_nfcal(struct ath_hw
249 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
250 }
251
252 +void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
253 +{
254 + struct ath9k_nfcal_hist *h;
255 + unsigned i, j;
256 + int32_t val;
257 + u8 chainmask;
258 + struct ath_common *common = ath9k_hw_common(ah);
259 +
260 + if (AR_SREV_9300_20_OR_LATER(ah))
261 + chainmask = 0x3F;
262 + else if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
263 + chainmask = 0x9;
264 + else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
265 + if ((ah->rxchainmask & 0x2) || (ah->rxchainmask & 0x4))
266 + chainmask = 0x1B;
267 + else
268 + chainmask = 0x09;
269 + } else {
270 + if (ah->rxchainmask & 0x4)
271 + chainmask = 0x3F;
272 + else if (ah->rxchainmask & 0x2)
273 + chainmask = 0x1B;
274 + else
275 + chainmask = 0x09;
276 + }
277 + h = ah->nfCalHist;
278 +
279 + for (i = 0; i < NUM_NF_READINGS; i++) {
280 + if (chainmask & (1 << i)) {
281 + val = REG_READ(ah, ah->nf_regs[i]);
282 + val &= 0xFFFFFE00;
283 + val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
284 + REG_WRITE(ah, ah->nf_regs[i], val);
285 + }
286 + }
287 +
288 + /*
289 + * Load software filtered NF value into baseband internal minCCApwr
290 + * variable.
291 + */
292 + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
293 + AR_PHY_AGC_CONTROL_ENABLE_NF);
294 + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
295 + AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
296 + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
297 +
298 + /*
299 + * Wait for load to complete, should be fast, a few 10s of us.
300 + * The max delay was changed from an original 250us to 10000us
301 + * since 250us often results in NF load timeout and causes deaf
302 + * condition during stress testing 12/12/2009
303 + */
304 + for (j = 0; j < 1000; j++) {
305 + if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
306 + AR_PHY_AGC_CONTROL_NF) == 0)
307 + break;
308 + udelay(10);
309 + }
310 +
311 + /*
312 + * We timed out waiting for the noisefloor to load, probably due to an
313 + * in-progress rx. Simply return here and allow the load plenty of time
314 + * to complete before the next calibration interval. We need to avoid
315 + * trying to load -50 (which happens below) while the previous load is
316 + * still in progress as this can cause rx deafness. Instead by returning
317 + * here, the baseband nf cal will just be capped by our present
318 + * noisefloor until the next calibration timer.
319 + */
320 + if (j == 1000) {
321 + ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf "
322 + "to load: AR_PHY_AGC_CONTROL=0x%x\n",
323 + REG_READ(ah, AR_PHY_AGC_CONTROL));
324 + return;
325 + }
326 +
327 + /*
328 + * Restore maxCCAPower register parameter again so that we're not capped
329 + * by the median we just loaded. This will be initial (and max) value
330 + * of next noise floor calibration the baseband does.
331 + */
332 + ENABLE_REGWRITE_BUFFER(ah);
333 + for (i = 0; i < NUM_NF_READINGS; i++) {
334 + if (chainmask & (1 << i)) {
335 + val = REG_READ(ah, ah->nf_regs[i]);
336 + val &= 0xFFFFFE00;
337 + val |= (((u32) (-50) << 1) & 0x1ff);
338 + REG_WRITE(ah, ah->nf_regs[i], val);
339 + }
340 + }
341 + REGWRITE_BUFFER_FLUSH(ah);
342 + DISABLE_REGWRITE_BUFFER(ah);
343 +}
344 +
345 +
346 static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
347 {
348 struct ath_common *common = ath9k_hw_common(ah);
349 --- a/drivers/net/wireless/ath/ath9k/calib.h
350 +++ b/drivers/net/wireless/ath/ath9k/calib.h
351 @@ -109,6 +109,7 @@ struct ath9k_pacal_info{
352
353 bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
354 void ath9k_hw_start_nfcal(struct ath_hw *ah);
355 +void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
356 int16_t ath9k_hw_getnf(struct ath_hw *ah,
357 struct ath9k_channel *chan);
358 void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah);
359 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h
360 +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
361 @@ -264,12 +264,6 @@ static inline void ath9k_hw_do_getnf(str
362 ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray);
363 }
364
365 -static inline void ath9k_hw_loadnf(struct ath_hw *ah,
366 - struct ath9k_channel *chan)
367 -{
368 - ath9k_hw_private_ops(ah)->loadnf(ah, chan);
369 -}
370 -
371 static inline bool ath9k_hw_init_cal(struct ath_hw *ah,
372 struct ath9k_channel *chan)
373 {
374 --- a/drivers/net/wireless/ath/ath9k/hw.h
375 +++ b/drivers/net/wireless/ath/ath9k/hw.h
376 @@ -510,7 +510,6 @@ struct ath_gen_timer_table {
377 * AR_RTC_PLL_CONTROL for a given channel
378 * @setup_calibration: set up calibration
379 * @iscal_supported: used to query if a type of calibration is supported
380 - * @loadnf: load noise floor read from each chain on the CCA registers
381 *
382 * @ani_reset: reset ANI parameters to default values
383 * @ani_lower_immunity: lower the noise immunity level. The level controls
384 @@ -564,7 +563,6 @@ struct ath_hw_private_ops {
385 bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
386 int param);
387 void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
388 - void (*loadnf)(struct ath_hw *ah, struct ath9k_channel *chan);
389
390 /* ANI */
391 void (*ani_reset)(struct ath_hw *ah, bool is_scanning);
392 @@ -658,6 +656,7 @@ struct ath_hw {
393 bool need_an_top2_fixup;
394 u16 tx_trig_level;
395
396 + u32 nf_regs[6];
397 struct ath_nf_limits nf_2g;
398 struct ath_nf_limits nf_5g;
399 u16 rfsilent;