Commit | Line | Data |
---|---|---|
c6e387a2 NK |
1 | /* |
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | |
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | |
4 | * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu> | |
5 | * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org> | |
6 | * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com> | |
7 | * | |
8 | * Permission to use, copy, modify, and distribute this software for any | |
9 | * purpose with or without fee is hereby granted, provided that the above | |
10 | * copyright notice and this permission notice appear in all copies. | |
11 | * | |
12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
19 | * | |
20 | */ | |
21 | ||
c6e387a2 NK |
22 | /*****************************\ |
23 | Reset functions and helpers | |
24 | \*****************************/ | |
25 | ||
bcd8f54a LR |
26 | #include <asm/unaligned.h> |
27 | ||
e8f055f0 | 28 | #include <linux/pci.h> /* To determine if a card is pci-e */ |
a54be5d4 | 29 | #include <linux/log2.h> |
c6e387a2 NK |
30 | #include "ath5k.h" |
31 | #include "reg.h" | |
32 | #include "base.h" | |
33 | #include "debug.h" | |
34 | ||
ec182d97 PR |
35 | /* |
36 | * Check if a register write has been completed | |
37 | */ | |
38 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | |
39 | bool is_set) | |
40 | { | |
41 | int i; | |
42 | u32 data; | |
43 | ||
44 | for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { | |
45 | data = ath5k_hw_reg_read(ah, reg); | |
46 | if (is_set && (data & flag)) | |
47 | break; | |
48 | else if ((data & flag) == val) | |
49 | break; | |
50 | udelay(15); | |
51 | } | |
52 | ||
53 | return (i <= 0) ? -EAGAIN : 0; | |
54 | } | |
55 | ||
c6e387a2 NK |
56 | /** |
57 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | |
58 | * | |
59 | * @ah: the &struct ath5k_hw | |
60 | * @channel: the currently set channel upon reset | |
61 | * | |
e8f055f0 NK |
62 | * Write the delta slope coefficient (used on pilot tracking ?) for OFDM |
63 | * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset(). | |
c6e387a2 | 64 | * |
e8f055f0 NK |
65 | * Since delta slope is floating point we split it on its exponent and |
66 | * mantissa and provide these values on hw. | |
67 | * | |
68 | * For more infos i think this patent is related | |
69 | * http://www.freepatentsonline.com/7184495.html | |
c6e387a2 NK |
70 | */ |
71 | static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | |
72 | struct ieee80211_channel *channel) | |
73 | { | |
74 | /* Get exponent and mantissa and set it */ | |
75 | u32 coef_scaled, coef_exp, coef_man, | |
76 | ds_coef_exp, ds_coef_man, clock; | |
77 | ||
0ee904c3 AB |
78 | BUG_ON(!(ah->ah_version == AR5K_AR5212) || |
79 | !(channel->hw_value & CHANNEL_OFDM)); | |
c6e387a2 | 80 | |
e8f055f0 | 81 | /* Get coefficient |
3578e6eb | 82 | * ALGO: coef = (5 * clock / carrier_freq) / 2 |
e8f055f0 NK |
83 | * we scale coef by shifting clock value by 24 for |
84 | * better precision since we use integers */ | |
85 | /* TODO: Half/quarter rate */ | |
3578e6eb | 86 | clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40; |
e8f055f0 NK |
87 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; |
88 | ||
89 | /* Get exponent | |
90 | * ALGO: coef_exp = 14 - highest set bit position */ | |
a54be5d4 | 91 | coef_exp = ilog2(coef_scaled); |
c6e387a2 | 92 | |
e8f055f0 | 93 | /* Doesn't make sense if it's zero*/ |
a54be5d4 | 94 | if (!coef_scaled || !coef_exp) |
c6e387a2 NK |
95 | return -EINVAL; |
96 | ||
e8f055f0 | 97 | /* Note: we've shifted coef_scaled by 24 */ |
c6e387a2 | 98 | coef_exp = 14 - (coef_exp - 24); |
e8f055f0 NK |
99 | |
100 | ||
101 | /* Get mantissa (significant digits) | |
102 | * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ | |
c6e387a2 NK |
103 | coef_man = coef_scaled + |
104 | (1 << (24 - coef_exp - 1)); | |
e8f055f0 NK |
105 | |
106 | /* Calculate delta slope coefficient exponent | |
107 | * and mantissa (remove scaling) and set them on hw */ | |
c6e387a2 NK |
108 | ds_coef_man = coef_man >> (24 - coef_exp); |
109 | ds_coef_exp = coef_exp - 16; | |
110 | ||
111 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | |
112 | AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); | |
113 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | |
114 | AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); | |
115 | ||
116 | return 0; | |
117 | } | |
118 | ||
119 | ||
120 | /* | |
121 | * index into rates for control rates, we can set it up like this because | |
122 | * this is only used for AR5212 and we know it supports G mode | |
123 | */ | |
2c91108c | 124 | static const unsigned int control_rates[] = |
c6e387a2 NK |
125 | { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; |
126 | ||
127 | /** | |
e8f055f0 | 128 | * ath5k_hw_write_rate_duration - fill rate code to duration table |
c6e387a2 NK |
129 | * |
130 | * @ah: the &struct ath5k_hw | |
131 | * @mode: one of enum ath5k_driver_mode | |
132 | * | |
e8f055f0 NK |
133 | * Write the rate code to duration table upon hw reset. This is a helper for |
134 | * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on | |
135 | * the hardware, based on current mode, for each rate. The rates which are | |
136 | * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have | |
137 | * different rate code so we write their value twice (one for long preample | |
138 | * and one for short). | |
139 | * | |
140 | * Note: Band doesn't matter here, if we set the values for OFDM it works | |
141 | * on both a and g modes. So all we have to do is set values for all g rates | |
142 | * that include all OFDM and CCK rates. If we operate in turbo or xr/half/ | |
143 | * quarter rate mode, we need to use another set of bitrates (that's why we | |
144 | * need the mode parameter) but we don't handle these proprietary modes yet. | |
c6e387a2 NK |
145 | */ |
146 | static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, | |
147 | unsigned int mode) | |
148 | { | |
149 | struct ath5k_softc *sc = ah->ah_sc; | |
150 | struct ieee80211_rate *rate; | |
151 | unsigned int i; | |
152 | ||
153 | /* Write rate duration table */ | |
154 | for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { | |
155 | u32 reg; | |
156 | u16 tx_time; | |
157 | ||
158 | rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; | |
159 | ||
160 | /* Set ACK timeout */ | |
161 | reg = AR5K_RATE_DUR(rate->hw_value); | |
162 | ||
163 | /* An ACK frame consists of 10 bytes. If you add the FCS, | |
164 | * which ieee80211_generic_frame_duration() adds, | |
165 | * its 14 bytes. Note we use the control rate and not the | |
166 | * actual rate for this rate. See mac80211 tx.c | |
167 | * ieee80211_duration() for a brief description of | |
168 | * what rate we should choose to TX ACKs. */ | |
169 | tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, | |
170 | sc->vif, 10, rate)); | |
171 | ||
172 | ath5k_hw_reg_write(ah, tx_time, reg); | |
173 | ||
174 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) | |
175 | continue; | |
176 | ||
177 | /* | |
178 | * We're not distinguishing short preamble here, | |
179 | * This is true, all we'll get is a longer value here | |
180 | * which is not necessarilly bad. We could use | |
181 | * export ieee80211_frame_duration() but that needs to be | |
182 | * fixed first to be properly used by mac802111 drivers: | |
183 | * | |
184 | * - remove erp stuff and let the routine figure ofdm | |
185 | * erp rates | |
186 | * - remove passing argument ieee80211_local as | |
187 | * drivers don't have access to it | |
188 | * - move drivers using ieee80211_generic_frame_duration() | |
189 | * to this | |
190 | */ | |
191 | ath5k_hw_reg_write(ah, tx_time, | |
192 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); | |
193 | } | |
194 | } | |
195 | ||
196 | /* | |
197 | * Reset chipset | |
198 | */ | |
199 | static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | |
200 | { | |
201 | int ret; | |
202 | u32 mask = val ? val : ~0U; | |
203 | ||
c6e387a2 NK |
204 | /* Read-and-clear RX Descriptor Pointer*/ |
205 | ath5k_hw_reg_read(ah, AR5K_RXDP); | |
206 | ||
207 | /* | |
208 | * Reset the device and wait until success | |
209 | */ | |
210 | ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL); | |
211 | ||
212 | /* Wait at least 128 PCI clocks */ | |
213 | udelay(15); | |
214 | ||
215 | if (ah->ah_version == AR5K_AR5210) { | |
84e463fa NK |
216 | val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA |
217 | | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; | |
218 | mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA | |
219 | | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; | |
c6e387a2 NK |
220 | } else { |
221 | val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; | |
222 | mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; | |
223 | } | |
224 | ||
225 | ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false); | |
226 | ||
227 | /* | |
228 | * Reset configuration register (for hw byte-swap). Note that this | |
229 | * is only set for big endian. We do the necessary magic in | |
230 | * AR5K_INIT_CFG. | |
231 | */ | |
232 | if ((val & AR5K_RESET_CTL_PCU) == 0) | |
233 | ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); | |
234 | ||
235 | return ret; | |
236 | } | |
237 | ||
238 | /* | |
239 | * Sleep control | |
240 | */ | |
626ede6b PR |
241 | static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, |
242 | bool set_chip, u16 sleep_duration) | |
c6e387a2 NK |
243 | { |
244 | unsigned int i; | |
245 | u32 staid, data; | |
246 | ||
c6e387a2 NK |
247 | staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); |
248 | ||
249 | switch (mode) { | |
250 | case AR5K_PM_AUTO: | |
251 | staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA; | |
252 | /* fallthrough */ | |
253 | case AR5K_PM_NETWORK_SLEEP: | |
254 | if (set_chip) | |
255 | ath5k_hw_reg_write(ah, | |
256 | AR5K_SLEEP_CTL_SLE_ALLOW | | |
257 | sleep_duration, | |
258 | AR5K_SLEEP_CTL); | |
259 | ||
260 | staid |= AR5K_STA_ID1_PWR_SV; | |
261 | break; | |
262 | ||
263 | case AR5K_PM_FULL_SLEEP: | |
264 | if (set_chip) | |
265 | ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP, | |
266 | AR5K_SLEEP_CTL); | |
267 | ||
268 | staid |= AR5K_STA_ID1_PWR_SV; | |
269 | break; | |
270 | ||
271 | case AR5K_PM_AWAKE: | |
272 | ||
273 | staid &= ~AR5K_STA_ID1_PWR_SV; | |
274 | ||
275 | if (!set_chip) | |
276 | goto commit; | |
277 | ||
c6e387a2 | 278 | data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL); |
edd7fc70 NK |
279 | |
280 | /* If card is down we 'll get 0xffff... so we | |
281 | * need to clean this up before we write the register | |
282 | */ | |
c6e387a2 NK |
283 | if (data & 0xffc00000) |
284 | data = 0; | |
285 | else | |
edd7fc70 NK |
286 | /* Preserve sleep duration etc */ |
287 | data = data & ~AR5K_SLEEP_CTL_SLE; | |
c6e387a2 | 288 | |
edd7fc70 NK |
289 | ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, |
290 | AR5K_SLEEP_CTL); | |
c6e387a2 NK |
291 | udelay(15); |
292 | ||
edd7fc70 | 293 | for (i = 200; i > 0; i--) { |
c6e387a2 NK |
294 | /* Check if the chip did wake up */ |
295 | if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & | |
296 | AR5K_PCICFG_SPWR_DN) == 0) | |
297 | break; | |
298 | ||
299 | /* Wait a bit and retry */ | |
edd7fc70 NK |
300 | udelay(50); |
301 | ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, | |
302 | AR5K_SLEEP_CTL); | |
c6e387a2 NK |
303 | } |
304 | ||
305 | /* Fail if the chip didn't wake up */ | |
edd7fc70 | 306 | if (i == 0) |
c6e387a2 NK |
307 | return -EIO; |
308 | ||
309 | break; | |
310 | ||
311 | default: | |
312 | return -EINVAL; | |
313 | } | |
314 | ||
315 | commit: | |
c6e387a2 NK |
316 | ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1); |
317 | ||
318 | return 0; | |
319 | } | |
320 | ||
edd7fc70 NK |
321 | /* |
322 | * Put device on hold | |
323 | * | |
324 | * Put MAC and Baseband on warm reset and | |
325 | * keep that state (don't clean sleep control | |
326 | * register). After this MAC and Baseband are | |
327 | * disabled and a full reset is needed to come | |
328 | * back. This way we save as much power as possible | |
329 | * without puting the card on full sleep. | |
330 | */ | |
331 | int ath5k_hw_on_hold(struct ath5k_hw *ah) | |
332 | { | |
333 | struct pci_dev *pdev = ah->ah_sc->pdev; | |
334 | u32 bus_flags; | |
335 | int ret; | |
336 | ||
337 | /* Make sure device is awake */ | |
338 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | |
339 | if (ret) { | |
340 | ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); | |
341 | return ret; | |
342 | } | |
343 | ||
344 | /* | |
345 | * Put chipset on warm reset... | |
346 | * | |
347 | * Note: puting PCI core on warm reset on PCI-E cards | |
348 | * results card to hang and always return 0xffff... so | |
349 | * we ingore that flag for PCI-E cards. On PCI cards | |
350 | * this flag gets cleared after 64 PCI clocks. | |
351 | */ | |
352 | bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; | |
353 | ||
354 | if (ah->ah_version == AR5K_AR5210) { | |
355 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | |
356 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | | |
357 | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); | |
358 | mdelay(2); | |
359 | } else { | |
360 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | |
361 | AR5K_RESET_CTL_BASEBAND | bus_flags); | |
362 | } | |
363 | ||
364 | if (ret) { | |
365 | ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n"); | |
366 | return -EIO; | |
367 | } | |
368 | ||
369 | /* ...wakeup again!*/ | |
370 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | |
371 | if (ret) { | |
372 | ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n"); | |
373 | return ret; | |
374 | } | |
375 | ||
376 | return ret; | |
377 | } | |
378 | ||
c6e387a2 | 379 | /* |
e8f055f0 NK |
380 | * Bring up MAC + PHY Chips and program PLL |
381 | * TODO: Half/Quarter rate support | |
c6e387a2 NK |
382 | */ |
383 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |
384 | { | |
385 | struct pci_dev *pdev = ah->ah_sc->pdev; | |
386 | u32 turbo, mode, clock, bus_flags; | |
387 | int ret; | |
388 | ||
389 | turbo = 0; | |
390 | mode = 0; | |
391 | clock = 0; | |
392 | ||
c6e387a2 NK |
393 | /* Wakeup the device */ |
394 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | |
395 | if (ret) { | |
396 | ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); | |
397 | return ret; | |
398 | } | |
399 | ||
edd7fc70 NK |
400 | /* |
401 | * Put chipset on warm reset... | |
402 | * | |
403 | * Note: puting PCI core on warm reset on PCI-E cards | |
404 | * results card to hang and always return 0xffff... so | |
405 | * we ingore that flag for PCI-E cards. On PCI cards | |
406 | * this flag gets cleared after 64 PCI clocks. | |
407 | */ | |
408 | bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; | |
409 | ||
410 | if (ah->ah_version == AR5K_AR5210) { | |
411 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | |
412 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | | |
413 | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); | |
414 | mdelay(2); | |
415 | } else { | |
416 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | |
417 | AR5K_RESET_CTL_BASEBAND | bus_flags); | |
418 | } | |
419 | ||
420 | if (ret) { | |
421 | ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); | |
422 | return -EIO; | |
423 | } | |
424 | ||
425 | /* ...wakeup again!...*/ | |
426 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | |
427 | if (ret) { | |
428 | ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n"); | |
429 | return ret; | |
430 | } | |
431 | ||
432 | /* ...clear reset control register and pull device out of | |
433 | * warm reset */ | |
434 | if (ath5k_hw_nic_reset(ah, 0)) { | |
435 | ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); | |
436 | return -EIO; | |
437 | } | |
438 | ||
439 | /* On initialization skip PLL programming since we don't have | |
440 | * a channel / mode set yet */ | |
441 | if (initial) | |
442 | return 0; | |
443 | ||
c6e387a2 NK |
444 | if (ah->ah_version != AR5K_AR5210) { |
445 | /* | |
446 | * Get channel mode flags | |
447 | */ | |
448 | ||
449 | if (ah->ah_radio >= AR5K_RF5112) { | |
450 | mode = AR5K_PHY_MODE_RAD_RF5112; | |
451 | clock = AR5K_PHY_PLL_RF5112; | |
452 | } else { | |
453 | mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/ | |
454 | clock = AR5K_PHY_PLL_RF5111; /*Zero*/ | |
455 | } | |
456 | ||
457 | if (flags & CHANNEL_2GHZ) { | |
458 | mode |= AR5K_PHY_MODE_FREQ_2GHZ; | |
459 | clock |= AR5K_PHY_PLL_44MHZ; | |
460 | ||
461 | if (flags & CHANNEL_CCK) { | |
462 | mode |= AR5K_PHY_MODE_MOD_CCK; | |
463 | } else if (flags & CHANNEL_OFDM) { | |
464 | /* XXX Dynamic OFDM/CCK is not supported by the | |
465 | * AR5211 so we set MOD_OFDM for plain g (no | |
466 | * CCK headers) operation. We need to test | |
467 | * this, 5211 might support ofdm-only g after | |
468 | * all, there are also initial register values | |
469 | * in the code for g mode (see initvals.c). */ | |
470 | if (ah->ah_version == AR5K_AR5211) | |
471 | mode |= AR5K_PHY_MODE_MOD_OFDM; | |
472 | else | |
473 | mode |= AR5K_PHY_MODE_MOD_DYN; | |
474 | } else { | |
475 | ATH5K_ERR(ah->ah_sc, | |
476 | "invalid radio modulation mode\n"); | |
477 | return -EINVAL; | |
478 | } | |
479 | } else if (flags & CHANNEL_5GHZ) { | |
480 | mode |= AR5K_PHY_MODE_FREQ_5GHZ; | |
e8f055f0 NK |
481 | |
482 | if (ah->ah_radio == AR5K_RF5413) | |
807e3739 | 483 | clock = AR5K_PHY_PLL_40MHZ_5413; |
e8f055f0 NK |
484 | else |
485 | clock |= AR5K_PHY_PLL_40MHZ; | |
c6e387a2 NK |
486 | |
487 | if (flags & CHANNEL_OFDM) | |
488 | mode |= AR5K_PHY_MODE_MOD_OFDM; | |
489 | else { | |
490 | ATH5K_ERR(ah->ah_sc, | |
491 | "invalid radio modulation mode\n"); | |
492 | return -EINVAL; | |
493 | } | |
494 | } else { | |
495 | ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n"); | |
496 | return -EINVAL; | |
497 | } | |
498 | ||
499 | if (flags & CHANNEL_TURBO) | |
500 | turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT; | |
501 | } else { /* Reset the device */ | |
502 | ||
503 | /* ...enable Atheros turbo mode if requested */ | |
504 | if (flags & CHANNEL_TURBO) | |
505 | ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, | |
506 | AR5K_PHY_TURBO); | |
507 | } | |
508 | ||
c6e387a2 | 509 | if (ah->ah_version != AR5K_AR5210) { |
c6e387a2 | 510 | |
e8f055f0 NK |
511 | /* ...update PLL if needed */ |
512 | if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) { | |
513 | ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); | |
514 | udelay(300); | |
515 | } | |
516 | ||
517 | /* ...set the PHY operating mode */ | |
c6e387a2 NK |
518 | ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE); |
519 | ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO); | |
520 | } | |
521 | ||
522 | return 0; | |
523 | } | |
524 | ||
e8f055f0 NK |
525 | /* |
526 | * If there is an external 32KHz crystal available, use it | |
527 | * as ref. clock instead of 32/40MHz clock and baseband clocks | |
528 | * to save power during sleep or restore normal 32/40MHz | |
529 | * operation. | |
530 | * | |
531 | * XXX: When operating on 32KHz certain PHY registers (27 - 31, | |
532 | * 123 - 127) require delay on access. | |
533 | */ | |
534 | static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) | |
535 | { | |
536 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | |
537 | u32 scal, spending, usec32; | |
538 | ||
539 | /* Only set 32KHz settings if we have an external | |
540 | * 32KHz crystal present */ | |
541 | if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || | |
542 | AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && | |
543 | enable) { | |
544 | ||
545 | /* 1 usec/cycle */ | |
546 | AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); | |
547 | /* Set up tsf increment on each cycle */ | |
548 | AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); | |
549 | ||
550 | /* Set baseband sleep control registers | |
551 | * and sleep control rate */ | |
552 | ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); | |
553 | ||
554 | if ((ah->ah_radio == AR5K_RF5112) || | |
555 | (ah->ah_radio == AR5K_RF5413) || | |
556 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | |
557 | spending = 0x14; | |
558 | else | |
559 | spending = 0x18; | |
560 | ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); | |
561 | ||
562 | if ((ah->ah_radio == AR5K_RF5112) || | |
563 | (ah->ah_radio == AR5K_RF5413) || | |
564 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { | |
565 | ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); | |
566 | ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); | |
567 | ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); | |
568 | ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); | |
569 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | |
570 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); | |
571 | } else { | |
572 | ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); | |
573 | ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); | |
574 | ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); | |
575 | ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); | |
576 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | |
577 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); | |
578 | } | |
579 | ||
580 | /* Enable sleep clock operation */ | |
581 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, | |
582 | AR5K_PCICFG_SLEEP_CLOCK_EN); | |
583 | ||
584 | } else { | |
585 | ||
586 | /* Disable sleep clock operation and | |
587 | * restore default parameters */ | |
588 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, | |
589 | AR5K_PCICFG_SLEEP_CLOCK_EN); | |
590 | ||
591 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | |
592 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); | |
593 | ||
594 | ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); | |
595 | ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); | |
596 | ||
597 | if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) | |
598 | scal = AR5K_PHY_SCAL_32MHZ_2417; | |
1889ba0a | 599 | else if (ee->ee_is_hb63) |
e8f055f0 NK |
600 | scal = AR5K_PHY_SCAL_32MHZ_HB63; |
601 | else | |
602 | scal = AR5K_PHY_SCAL_32MHZ; | |
603 | ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); | |
604 | ||
605 | ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); | |
606 | ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); | |
607 | ||
608 | if ((ah->ah_radio == AR5K_RF5112) || | |
609 | (ah->ah_radio == AR5K_RF5413) || | |
610 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | |
611 | spending = 0x14; | |
612 | else | |
613 | spending = 0x18; | |
614 | ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); | |
615 | ||
616 | if ((ah->ah_radio == AR5K_RF5112) || | |
617 | (ah->ah_radio == AR5K_RF5413)) | |
618 | usec32 = 39; | |
619 | else | |
620 | usec32 = 31; | |
621 | AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32); | |
622 | ||
623 | AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); | |
624 | } | |
e8f055f0 NK |
625 | } |
626 | ||
e8f055f0 NK |
627 | /* TODO: Half/Quarter rate */ |
628 | static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | |
629 | struct ieee80211_channel *channel) | |
630 | { | |
631 | if (ah->ah_version == AR5K_AR5212 && | |
632 | ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { | |
633 | ||
634 | /* Setup ADC control */ | |
635 | ath5k_hw_reg_write(ah, | |
636 | (AR5K_REG_SM(2, | |
637 | AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) | | |
638 | AR5K_REG_SM(2, | |
639 | AR5K_PHY_ADC_CTL_INBUFGAIN_ON) | | |
640 | AR5K_PHY_ADC_CTL_PWD_DAC_OFF | | |
641 | AR5K_PHY_ADC_CTL_PWD_ADC_OFF), | |
642 | AR5K_PHY_ADC_CTL); | |
643 | ||
644 | ||
645 | ||
646 | /* Disable barker RSSI threshold */ | |
647 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL, | |
648 | AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR); | |
649 | ||
650 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL, | |
651 | AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2); | |
652 | ||
653 | /* Set the mute mask */ | |
654 | ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK); | |
655 | } | |
656 | ||
657 | /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */ | |
658 | if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B) | |
659 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH); | |
660 | ||
661 | /* Enable DCU double buffering */ | |
662 | if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B) | |
663 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | |
664 | AR5K_TXCFG_DCU_DBL_BUF_DIS); | |
665 | ||
666 | /* Set DAC/ADC delays */ | |
667 | if (ah->ah_version == AR5K_AR5212) { | |
668 | u32 scal; | |
1889ba0a | 669 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
e8f055f0 NK |
670 | if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) |
671 | scal = AR5K_PHY_SCAL_32MHZ_2417; | |
1889ba0a | 672 | else if (ee->ee_is_hb63) |
e8f055f0 NK |
673 | scal = AR5K_PHY_SCAL_32MHZ_HB63; |
674 | else | |
675 | scal = AR5K_PHY_SCAL_32MHZ; | |
676 | ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); | |
677 | } | |
678 | ||
679 | /* Set fast ADC */ | |
680 | if ((ah->ah_radio == AR5K_RF5413) || | |
681 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { | |
682 | u32 fast_adc = true; | |
683 | ||
684 | if (channel->center_freq == 2462 || | |
685 | channel->center_freq == 2467) | |
686 | fast_adc = 0; | |
687 | ||
688 | /* Only update if needed */ | |
689 | if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc) | |
690 | ath5k_hw_reg_write(ah, fast_adc, | |
691 | AR5K_PHY_FAST_ADC); | |
692 | } | |
693 | ||
694 | /* Fix for first revision of the RF5112 RF chipset */ | |
695 | if (ah->ah_radio == AR5K_RF5112 && | |
696 | ah->ah_radio_5ghz_revision < | |
697 | AR5K_SREV_RAD_5112A) { | |
698 | u32 data; | |
699 | ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD, | |
700 | AR5K_PHY_CCKTXCTL); | |
701 | if (channel->hw_value & CHANNEL_5GHZ) | |
702 | data = 0xffb81020; | |
703 | else | |
704 | data = 0xffb80d20; | |
705 | ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); | |
706 | } | |
707 | ||
708 | if (ah->ah_mac_srev < AR5K_SREV_AR5211) { | |
709 | u32 usec_reg; | |
710 | /* 5311 has different tx/rx latency masks | |
711 | * from 5211, since we deal 5311 the same | |
712 | * as 5211 when setting initvals, shift | |
713 | * values here to their proper locations */ | |
714 | usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211); | |
715 | ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 | | |
716 | AR5K_USEC_32 | | |
717 | AR5K_USEC_TX_LATENCY_5211 | | |
718 | AR5K_REG_SM(29, | |
719 | AR5K_USEC_RX_LATENCY_5210)), | |
720 | AR5K_USEC_5211); | |
721 | /* Clear QCU/DCU clock gating register */ | |
722 | ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT); | |
723 | /* Set DAC/ADC delays */ | |
724 | ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL); | |
725 | /* Enable PCU FIFO corruption ECO */ | |
726 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, | |
727 | AR5K_DIAG_SW_ECO_ENABLE); | |
728 | } | |
729 | } | |
730 | ||
731 | static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |
732 | struct ieee80211_channel *channel, u8 *ant, u8 ee_mode) | |
733 | { | |
734 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | |
8f655dde | 735 | s16 cck_ofdm_pwr_delta; |
e8f055f0 | 736 | |
8f655dde NK |
737 | /* Adjust power delta for channel 14 */ |
738 | if (channel->center_freq == 2484) | |
739 | cck_ofdm_pwr_delta = | |
740 | ((ee->ee_cck_ofdm_power_delta - | |
741 | ee->ee_scaled_cck_delta) * 2) / 10; | |
742 | else | |
743 | cck_ofdm_pwr_delta = | |
744 | (ee->ee_cck_ofdm_power_delta * 2) / 10; | |
e8f055f0 | 745 | |
8f655dde NK |
746 | /* Set CCK to OFDM power delta on tx power |
747 | * adjustment register */ | |
748 | if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { | |
e8f055f0 NK |
749 | if (channel->hw_value == CHANNEL_G) |
750 | ath5k_hw_reg_write(ah, | |
8f655dde | 751 | AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1), |
e8f055f0 NK |
752 | AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) | |
753 | AR5K_REG_SM((cck_ofdm_pwr_delta * -1), | |
754 | AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX), | |
755 | AR5K_PHY_TX_PWR_ADJ); | |
756 | else | |
757 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ); | |
8f655dde NK |
758 | } else { |
759 | /* For older revs we scale power on sw during tx power | |
760 | * setup */ | |
761 | ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta; | |
762 | ah->ah_txpower.txp_cck_ofdm_gainf_delta = | |
763 | ee->ee_cck_ofdm_gain_delta; | |
e8f055f0 NK |
764 | } |
765 | ||
766 | /* Set antenna idle switch table */ | |
767 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, | |
768 | AR5K_PHY_ANT_CTL_SWTABLE_IDLE, | |
2bed03eb | 769 | (ah->ah_ant_ctl[ee_mode][0] | |
e8f055f0 NK |
770 | AR5K_PHY_ANT_CTL_TXRX_EN)); |
771 | ||
2bed03eb NK |
772 | /* Set antenna switch tables */ |
773 | ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[0]], | |
e8f055f0 | 774 | AR5K_PHY_ANT_SWITCH_TABLE_0); |
2bed03eb | 775 | ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[1]], |
e8f055f0 NK |
776 | AR5K_PHY_ANT_SWITCH_TABLE_1); |
777 | ||
778 | /* Noise floor threshold */ | |
779 | ath5k_hw_reg_write(ah, | |
780 | AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), | |
781 | AR5K_PHY_NFTHRES); | |
782 | ||
783 | if ((channel->hw_value & CHANNEL_TURBO) && | |
784 | (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) { | |
785 | /* Switch settling time (Turbo) */ | |
786 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, | |
787 | AR5K_PHY_SETTLING_SWITCH, | |
788 | ee->ee_switch_settling_turbo[ee_mode]); | |
789 | ||
790 | /* Tx/Rx attenuation (Turbo) */ | |
791 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN, | |
792 | AR5K_PHY_GAIN_TXRX_ATTEN, | |
793 | ee->ee_atn_tx_rx_turbo[ee_mode]); | |
794 | ||
795 | /* ADC/PGA desired size (Turbo) */ | |
796 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, | |
797 | AR5K_PHY_DESIRED_SIZE_ADC, | |
798 | ee->ee_adc_desired_size_turbo[ee_mode]); | |
799 | ||
800 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, | |
801 | AR5K_PHY_DESIRED_SIZE_PGA, | |
802 | ee->ee_pga_desired_size_turbo[ee_mode]); | |
803 | ||
804 | /* Tx/Rx margin (Turbo) */ | |
805 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, | |
806 | AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, | |
807 | ee->ee_margin_tx_rx_turbo[ee_mode]); | |
808 | ||
809 | } else { | |
810 | /* Switch settling time */ | |
811 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, | |
812 | AR5K_PHY_SETTLING_SWITCH, | |
813 | ee->ee_switch_settling[ee_mode]); | |
814 | ||
815 | /* Tx/Rx attenuation */ | |
816 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN, | |
817 | AR5K_PHY_GAIN_TXRX_ATTEN, | |
818 | ee->ee_atn_tx_rx[ee_mode]); | |
819 | ||
820 | /* ADC/PGA desired size */ | |
821 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, | |
822 | AR5K_PHY_DESIRED_SIZE_ADC, | |
823 | ee->ee_adc_desired_size[ee_mode]); | |
824 | ||
825 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, | |
826 | AR5K_PHY_DESIRED_SIZE_PGA, | |
827 | ee->ee_pga_desired_size[ee_mode]); | |
828 | ||
829 | /* Tx/Rx margin */ | |
830 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | |
831 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, | |
832 | AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, | |
833 | ee->ee_margin_tx_rx[ee_mode]); | |
834 | } | |
835 | ||
836 | /* XPA delays */ | |
837 | ath5k_hw_reg_write(ah, | |
838 | (ee->ee_tx_end2xpa_disable[ee_mode] << 24) | | |
839 | (ee->ee_tx_end2xpa_disable[ee_mode] << 16) | | |
840 | (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) | | |
841 | (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4); | |
842 | ||
843 | /* XLNA delay */ | |
844 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3, | |
845 | AR5K_PHY_RF_CTL3_TXE2XLNA_ON, | |
846 | ee->ee_tx_end2xlna_enable[ee_mode]); | |
847 | ||
848 | /* Thresh64 (ANI) */ | |
849 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF, | |
850 | AR5K_PHY_NF_THRESH62, | |
851 | ee->ee_thr_62[ee_mode]); | |
852 | ||
e8f055f0 NK |
853 | /* False detect backoff for channels |
854 | * that have spur noise. Write the new | |
855 | * cyclic power RSSI threshold. */ | |
856 | if (ath5k_hw_chan_has_spur_noise(ah, channel)) | |
857 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, | |
858 | AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, | |
859 | AR5K_INIT_CYCRSSI_THR1 + | |
860 | ee->ee_false_detect[ee_mode]); | |
861 | else | |
862 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, | |
863 | AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, | |
864 | AR5K_INIT_CYCRSSI_THR1); | |
865 | ||
5f13bfac BR |
866 | /* I/Q correction (set enable bit last to match HAL sources) */ |
867 | /* TODO: Per channel i/q infos ? */ | |
868 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | |
869 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF, | |
870 | ee->ee_i_cal[ee_mode]); | |
871 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF, | |
872 | ee->ee_q_cal[ee_mode]); | |
873 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE); | |
874 | } | |
e8f055f0 NK |
875 | |
876 | /* Heavy clipping -disable for now */ | |
877 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1) | |
878 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); | |
e8f055f0 NK |
879 | } |
880 | ||
c6e387a2 NK |
881 | /* |
882 | * Main reset function | |
883 | */ | |
05c914fe | 884 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
c6e387a2 NK |
885 | struct ieee80211_channel *channel, bool change_channel) |
886 | { | |
954fecea | 887 | struct ath_common *common = ath5k_hw_common(ah); |
e8f055f0 NK |
888 | u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; |
889 | u32 phy_tst1; | |
890 | u8 mode, freq, ee_mode, ant[2]; | |
891 | int i, ret; | |
c6e387a2 | 892 | |
c6e387a2 NK |
893 | s_ant = 0; |
894 | ee_mode = 0; | |
e8f055f0 NK |
895 | staid1_flags = 0; |
896 | tsf_up = 0; | |
897 | tsf_lo = 0; | |
c6e387a2 NK |
898 | freq = 0; |
899 | mode = 0; | |
900 | ||
901 | /* | |
902 | * Save some registers before a reset | |
903 | */ | |
904 | /*DCU/Antenna selection not available on 5210*/ | |
c6e387a2 | 905 | if (ah->ah_version != AR5K_AR5210) { |
c6e387a2 NK |
906 | |
907 | switch (channel->hw_value & CHANNEL_MODES) { | |
908 | case CHANNEL_A: | |
909 | mode = AR5K_MODE_11A; | |
910 | freq = AR5K_INI_RFGAIN_5GHZ; | |
911 | ee_mode = AR5K_EEPROM_MODE_11A; | |
912 | break; | |
913 | case CHANNEL_G: | |
914 | mode = AR5K_MODE_11G; | |
915 | freq = AR5K_INI_RFGAIN_2GHZ; | |
916 | ee_mode = AR5K_EEPROM_MODE_11G; | |
917 | break; | |
918 | case CHANNEL_B: | |
919 | mode = AR5K_MODE_11B; | |
920 | freq = AR5K_INI_RFGAIN_2GHZ; | |
921 | ee_mode = AR5K_EEPROM_MODE_11B; | |
922 | break; | |
923 | case CHANNEL_T: | |
924 | mode = AR5K_MODE_11A_TURBO; | |
925 | freq = AR5K_INI_RFGAIN_5GHZ; | |
926 | ee_mode = AR5K_EEPROM_MODE_11A; | |
927 | break; | |
c6e387a2 | 928 | case CHANNEL_TG: |
e8f055f0 NK |
929 | if (ah->ah_version == AR5K_AR5211) { |
930 | ATH5K_ERR(ah->ah_sc, | |
931 | "TurboG mode not available on 5211"); | |
932 | return -EINVAL; | |
933 | } | |
c6e387a2 NK |
934 | mode = AR5K_MODE_11G_TURBO; |
935 | freq = AR5K_INI_RFGAIN_2GHZ; | |
936 | ee_mode = AR5K_EEPROM_MODE_11G; | |
937 | break; | |
938 | case CHANNEL_XR: | |
939 | if (ah->ah_version == AR5K_AR5211) { | |
940 | ATH5K_ERR(ah->ah_sc, | |
941 | "XR mode not available on 5211"); | |
942 | return -EINVAL; | |
943 | } | |
944 | mode = AR5K_MODE_XR; | |
945 | freq = AR5K_INI_RFGAIN_5GHZ; | |
946 | ee_mode = AR5K_EEPROM_MODE_11A; | |
947 | break; | |
948 | default: | |
949 | ATH5K_ERR(ah->ah_sc, | |
950 | "invalid channel: %d\n", channel->center_freq); | |
951 | return -EINVAL; | |
952 | } | |
953 | ||
e8f055f0 NK |
954 | if (change_channel) { |
955 | /* | |
956 | * Save frame sequence count | |
957 | * For revs. after Oahu, only save | |
958 | * seq num for DCU 0 (Global seq num) | |
959 | */ | |
960 | if (ah->ah_mac_srev < AR5K_SREV_AR5211) { | |
961 | ||
962 | for (i = 0; i < 10; i++) | |
963 | s_seq[i] = ath5k_hw_reg_read(ah, | |
964 | AR5K_QUEUE_DCU_SEQNUM(i)); | |
965 | ||
966 | } else { | |
967 | s_seq[0] = ath5k_hw_reg_read(ah, | |
968 | AR5K_QUEUE_DCU_SEQNUM(0)); | |
969 | } | |
970 | ||
971 | /* TSF accelerates on AR5211 durring reset | |
972 | * As a workaround save it here and restore | |
973 | * it later so that it's back in time after | |
974 | * reset. This way it'll get re-synced on the | |
975 | * next beacon without breaking ad-hoc. | |
976 | * | |
977 | * On AR5212 TSF is almost preserved across a | |
978 | * reset so it stays back in time anyway and | |
979 | * we don't have to save/restore it. | |
980 | * | |
981 | * XXX: Since this breaks power saving we have | |
982 | * to disable power saving until we receive the | |
983 | * next beacon, so we can resync beacon timers */ | |
984 | if (ah->ah_version == AR5K_AR5211) { | |
985 | tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); | |
986 | tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); | |
987 | } | |
988 | } | |
989 | ||
990 | /* Save default antenna */ | |
991 | s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); | |
992 | ||
993 | if (ah->ah_version == AR5K_AR5212) { | |
994 | /* Restore normal 32/40MHz clock operation | |
995 | * to avoid register access delay on certain | |
996 | * PHY registers */ | |
997 | ath5k_hw_set_sleep_clock(ah, false); | |
998 | ||
999 | /* Since we are going to write rf buffer | |
1000 | * check if we have any pending gain_F | |
1001 | * optimization settings */ | |
1002 | if (change_channel && ah->ah_rf_banks != NULL) | |
1003 | ath5k_hw_gainf_calibrate(ah); | |
1004 | } | |
c6e387a2 NK |
1005 | } |
1006 | ||
e8f055f0 NK |
1007 | /*GPIOs*/ |
1008 | s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & | |
1009 | AR5K_PCICFG_LEDSTATE; | |
1010 | s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); | |
1011 | s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); | |
1012 | ||
1013 | /* AR5K_STA_ID1 flags, only preserve antenna | |
1014 | * settings and ack/cts rate mode */ | |
1015 | staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & | |
1016 | (AR5K_STA_ID1_DEFAULT_ANTENNA | | |
1017 | AR5K_STA_ID1_DESC_ANTENNA | | |
1018 | AR5K_STA_ID1_RTS_DEF_ANTENNA | | |
1019 | AR5K_STA_ID1_ACKCTS_6MB | | |
1020 | AR5K_STA_ID1_BASE_RATE_11B | | |
1021 | AR5K_STA_ID1_SELFGEN_DEF_ANT); | |
1022 | ||
1023 | /* Wakeup the device */ | |
1024 | ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); | |
1025 | if (ret) | |
1026 | return ret; | |
1027 | ||
a406c139 | 1028 | /* PHY access enable */ |
e8f055f0 NK |
1029 | if (ah->ah_mac_srev >= AR5K_SREV_AR5211) |
1030 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | |
1031 | else | |
1032 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40, | |
1033 | AR5K_PHY(0)); | |
a406c139 | 1034 | |
e8f055f0 | 1035 | /* Write initial settings */ |
c6e387a2 NK |
1036 | ret = ath5k_hw_write_initvals(ah, mode, change_channel); |
1037 | if (ret) | |
1038 | return ret; | |
1039 | ||
1040 | /* | |
1041 | * 5211/5212 Specific | |
1042 | */ | |
1043 | if (ah->ah_version != AR5K_AR5210) { | |
e8f055f0 | 1044 | |
c6e387a2 NK |
1045 | /* |
1046 | * Write initial RF gain settings | |
1047 | * This should work for both 5111/5112 | |
1048 | */ | |
6f3b414a | 1049 | ret = ath5k_hw_rfgain_init(ah, freq); |
c6e387a2 NK |
1050 | if (ret) |
1051 | return ret; | |
1052 | ||
1053 | mdelay(1); | |
1054 | ||
1055 | /* | |
e8f055f0 NK |
1056 | * Tweak initval settings for revised |
1057 | * chipsets and add some more config | |
1058 | * bits | |
c6e387a2 | 1059 | */ |
e8f055f0 | 1060 | ath5k_hw_tweak_initval_settings(ah, channel); |
c6e387a2 NK |
1061 | |
1062 | /* | |
57e6c56d | 1063 | * Set TX power |
c6e387a2 | 1064 | */ |
8f655dde | 1065 | ret = ath5k_hw_txpower(ah, channel, ee_mode, |
a0823810 | 1066 | ah->ah_txpower.txp_max_pwr / 2); |
c6e387a2 NK |
1067 | if (ret) |
1068 | return ret; | |
1069 | ||
1070 | /* Write rate duration table only on AR5212 and if | |
1071 | * virtual interface has already been brought up | |
1072 | * XXX: rethink this after new mode changes to | |
1073 | * mac80211 are integrated */ | |
1074 | if (ah->ah_version == AR5K_AR5212 && | |
1075 | ah->ah_sc->vif != NULL) | |
1076 | ath5k_hw_write_rate_duration(ah, mode); | |
1077 | ||
1078 | /* | |
e8f055f0 | 1079 | * Write RF buffer |
c6e387a2 | 1080 | */ |
8892e4ec | 1081 | ret = ath5k_hw_rfregs_init(ah, channel, mode); |
c6e387a2 NK |
1082 | if (ret) |
1083 | return ret; | |
1084 | ||
c6e387a2 NK |
1085 | |
1086 | /* Write OFDM timings on 5212*/ | |
1087 | if (ah->ah_version == AR5K_AR5212 && | |
1088 | channel->hw_value & CHANNEL_OFDM) { | |
57e6c56d | 1089 | |
c6e387a2 NK |
1090 | ret = ath5k_hw_write_ofdm_timings(ah, channel); |
1091 | if (ret) | |
1092 | return ret; | |
57e6c56d | 1093 | |
30bd3a30 BR |
1094 | /* Spur info is available only from EEPROM versions |
1095 | * bigger than 5.3 but but the EEPOM routines will use | |
1096 | * static values for older versions */ | |
1097 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) | |
57e6c56d | 1098 | ath5k_hw_set_spur_mitigation_filter(ah, |
30bd3a30 | 1099 | channel); |
c6e387a2 NK |
1100 | } |
1101 | ||
1102 | /*Enable/disable 802.11b mode on 5111 | |
1103 | (enable 2111 frequency converter + CCK)*/ | |
1104 | if (ah->ah_radio == AR5K_RF5111) { | |
1105 | if (mode == AR5K_MODE_11B) | |
1106 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, | |
1107 | AR5K_TXCFG_B_MODE); | |
1108 | else | |
1109 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | |
1110 | AR5K_TXCFG_B_MODE); | |
1111 | } | |
1112 | ||
c6e387a2 NK |
1113 | /* |
1114 | * In case a fixed antenna was set as default | |
2bed03eb | 1115 | * use the same switch table twice. |
c6e387a2 | 1116 | */ |
2bed03eb NK |
1117 | if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A) |
1118 | ant[0] = ant[1] = AR5K_ANT_SWTABLE_A; | |
1119 | else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B) | |
1120 | ant[0] = ant[1] = AR5K_ANT_SWTABLE_B; | |
1121 | else { | |
1122 | ant[0] = AR5K_ANT_SWTABLE_A; | |
1123 | ant[1] = AR5K_ANT_SWTABLE_B; | |
c6e387a2 NK |
1124 | } |
1125 | ||
c6e387a2 | 1126 | /* Commit values from EEPROM */ |
e8f055f0 | 1127 | ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode); |
c6e387a2 NK |
1128 | |
1129 | } else { | |
e8f055f0 NK |
1130 | /* |
1131 | * For 5210 we do all initialization using | |
1132 | * initvals, so we don't have to modify | |
1133 | * any settings (5210 also only supports | |
1134 | * a/aturbo modes) | |
1135 | */ | |
c6e387a2 NK |
1136 | mdelay(1); |
1137 | /* Disable phy and wait */ | |
1138 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | |
1139 | mdelay(1); | |
1140 | } | |
1141 | ||
1142 | /* | |
1143 | * Restore saved values | |
1144 | */ | |
e8f055f0 | 1145 | |
c6e387a2 NK |
1146 | /*DCU/Antenna selection not available on 5210*/ |
1147 | if (ah->ah_version != AR5K_AR5210) { | |
e8f055f0 NK |
1148 | |
1149 | if (change_channel) { | |
1150 | if (ah->ah_mac_srev < AR5K_SREV_AR5211) { | |
1151 | for (i = 0; i < 10; i++) | |
1152 | ath5k_hw_reg_write(ah, s_seq[i], | |
1153 | AR5K_QUEUE_DCU_SEQNUM(i)); | |
1154 | } else { | |
1155 | ath5k_hw_reg_write(ah, s_seq[0], | |
1156 | AR5K_QUEUE_DCU_SEQNUM(0)); | |
1157 | } | |
1158 | ||
1159 | ||
1160 | if (ah->ah_version == AR5K_AR5211) { | |
1161 | ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); | |
1162 | ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); | |
1163 | } | |
1164 | } | |
1165 | ||
c6e387a2 NK |
1166 | ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA); |
1167 | } | |
e8f055f0 NK |
1168 | |
1169 | /* Ledstate */ | |
c6e387a2 | 1170 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]); |
e8f055f0 NK |
1171 | |
1172 | /* Gpio settings */ | |
c6e387a2 NK |
1173 | ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); |
1174 | ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); | |
1175 | ||
e8f055f0 | 1176 | /* Restore sta_id flags and preserve our mac address*/ |
954fecea LR |
1177 | ath5k_hw_reg_write(ah, |
1178 | get_unaligned_le32(common->macaddr), | |
1179 | AR5K_STA_ID0); | |
1180 | ath5k_hw_reg_write(ah, | |
91b9eb82 | 1181 | staid1_flags | get_unaligned_le16(common->macaddr + 4), |
954fecea | 1182 | AR5K_STA_ID1); |
e8f055f0 NK |
1183 | |
1184 | ||
c6e387a2 | 1185 | /* |
e8f055f0 | 1186 | * Configure PCU |
c6e387a2 | 1187 | */ |
e8f055f0 NK |
1188 | |
1189 | /* Restore bssid and bssid mask */ | |
be5d6b75 | 1190 | ath5k_hw_set_associd(ah); |
c6e387a2 | 1191 | |
e8f055f0 | 1192 | /* Set PCU config */ |
ccfe5552 | 1193 | ath5k_hw_set_opmode(ah, op_mode); |
e8f055f0 NK |
1194 | |
1195 | /* Clear any pending interrupts | |
1196 | * PISR/SISR Not available on 5210 */ | |
1197 | if (ah->ah_version != AR5K_AR5210) | |
c6e387a2 | 1198 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); |
e8f055f0 NK |
1199 | |
1200 | /* Set RSSI/BRSSI thresholds | |
1201 | * | |
1202 | * Note: If we decide to set this value | |
1203 | * dynamicaly, have in mind that when AR5K_RSSI_THR | |
1204 | * register is read it might return 0x40 if we haven't | |
1205 | * wrote anything to it plus BMISS RSSI threshold is zeroed. | |
1206 | * So doing a save/restore procedure here isn't the right | |
1207 | * choice. Instead store it on ath5k_hw */ | |
1208 | ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | | |
1209 | AR5K_TUNE_BMISS_THRES << | |
1210 | AR5K_RSSI_THR_BMISS_S), | |
1211 | AR5K_RSSI_THR); | |
1212 | ||
1213 | /* MIC QoS support */ | |
1214 | if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { | |
1215 | ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); | |
1216 | ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); | |
1217 | } | |
1218 | ||
1219 | /* QoS NOACK Policy */ | |
1220 | if (ah->ah_version == AR5K_AR5212) { | |
1221 | ath5k_hw_reg_write(ah, | |
1222 | AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | | |
1223 | AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | | |
1224 | AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), | |
1225 | AR5K_QOS_NOACK); | |
c6e387a2 NK |
1226 | } |
1227 | ||
e8f055f0 | 1228 | |
c6e387a2 | 1229 | /* |
e8f055f0 | 1230 | * Configure PHY |
c6e387a2 | 1231 | */ |
e8f055f0 NK |
1232 | |
1233 | /* Set channel on PHY */ | |
1234 | ret = ath5k_hw_channel(ah, channel); | |
1235 | if (ret) | |
1236 | return ret; | |
c6e387a2 NK |
1237 | |
1238 | /* | |
1239 | * Enable the PHY and wait until completion | |
e8f055f0 NK |
1240 | * This includes BaseBand and Synthesizer |
1241 | * activation. | |
c6e387a2 NK |
1242 | */ |
1243 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | |
1244 | ||
1245 | /* | |
1246 | * On 5211+ read activation -> rx delay | |
1247 | * and use it. | |
e8f055f0 NK |
1248 | * |
1249 | * TODO: Half/quarter rate support | |
c6e387a2 NK |
1250 | */ |
1251 | if (ah->ah_version != AR5K_AR5210) { | |
e8f055f0 NK |
1252 | u32 delay; |
1253 | delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | |
c6e387a2 | 1254 | AR5K_PHY_RX_DELAY_M; |
e8f055f0 NK |
1255 | delay = (channel->hw_value & CHANNEL_CCK) ? |
1256 | ((delay << 2) / 22) : (delay / 10); | |
c6e387a2 | 1257 | |
e8f055f0 | 1258 | udelay(100 + (2 * delay)); |
c6e387a2 NK |
1259 | } else { |
1260 | mdelay(1); | |
1261 | } | |
1262 | ||
1263 | /* | |
e8f055f0 NK |
1264 | * Perform ADC test to see if baseband is ready |
1265 | * Set tx hold and check adc test register | |
c6e387a2 | 1266 | */ |
e8f055f0 | 1267 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); |
c6e387a2 NK |
1268 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); |
1269 | for (i = 0; i <= 20; i++) { | |
1270 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) | |
1271 | break; | |
1272 | udelay(200); | |
1273 | } | |
e8f055f0 | 1274 | ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); |
c6e387a2 NK |
1275 | |
1276 | /* | |
e8f055f0 | 1277 | * Start automatic gain control calibration |
c6e387a2 NK |
1278 | * |
1279 | * During AGC calibration RX path is re-routed to | |
e8f055f0 | 1280 | * a power detector so we don't receive anything. |
c6e387a2 NK |
1281 | * |
1282 | * This method is used to calibrate some static offsets | |
1283 | * used together with on-the fly I/Q calibration (the | |
1284 | * one performed via ath5k_hw_phy_calibrate), that doesn't | |
1285 | * interrupt rx path. | |
1286 | * | |
e8f055f0 NK |
1287 | * While rx path is re-routed to the power detector we also |
1288 | * start a noise floor calibration, to measure the | |
1289 | * card's noise floor (the noise we measure when we are not | |
1290 | * transmiting or receiving anything). | |
1291 | * | |
c6e387a2 | 1292 | * If we are in a noisy environment AGC calibration may time |
e8f055f0 | 1293 | * out and/or noise floor calibration might timeout. |
c6e387a2 NK |
1294 | */ |
1295 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | |
e5e2647f | 1296 | AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); |
c6e387a2 NK |
1297 | |
1298 | /* At the same time start I/Q calibration for QAM constellation | |
1299 | * -no need for CCK- */ | |
1300 | ah->ah_calibration = false; | |
1301 | if (!(mode == AR5K_MODE_11B)) { | |
1302 | ah->ah_calibration = true; | |
1303 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | |
1304 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | |
1305 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | |
1306 | AR5K_PHY_IQ_RUN); | |
1307 | } | |
1308 | ||
1309 | /* Wait for gain calibration to finish (we check for I/Q calibration | |
1310 | * during ath5k_phy_calibrate) */ | |
1311 | if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | |
1312 | AR5K_PHY_AGCCTL_CAL, 0, false)) { | |
1313 | ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", | |
1314 | channel->center_freq); | |
c6e387a2 NK |
1315 | } |
1316 | ||
2bed03eb NK |
1317 | /* Restore antenna mode */ |
1318 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | |
e8f055f0 | 1319 | |
6e08d228 LT |
1320 | /* Restore slot time and ACK timeouts */ |
1321 | if (ah->ah_coverage_class > 0) | |
1322 | ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); | |
1323 | ||
e8f055f0 NK |
1324 | /* |
1325 | * Configure QCUs/DCUs | |
1326 | */ | |
1327 | ||
1328 | /* TODO: HW Compression support for data queues */ | |
1329 | /* TODO: Burst prefetch for data queues */ | |
1330 | ||
c6e387a2 NK |
1331 | /* |
1332 | * Reset queues and start beacon timers at the end of the reset routine | |
e8f055f0 NK |
1333 | * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping |
1334 | * Note: If we want we can assign multiple qcus on one dcu. | |
c6e387a2 NK |
1335 | */ |
1336 | for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { | |
c6e387a2 NK |
1337 | ret = ath5k_hw_reset_tx_queue(ah, i); |
1338 | if (ret) { | |
1339 | ATH5K_ERR(ah->ah_sc, | |
1340 | "failed to reset TX queue #%d\n", i); | |
1341 | return ret; | |
1342 | } | |
1343 | } | |
1344 | ||
e8f055f0 NK |
1345 | |
1346 | /* | |
1347 | * Configure DMA/Interrupts | |
1348 | */ | |
1349 | ||
1350 | /* | |
1351 | * Set Rx/Tx DMA Configuration | |
1352 | * | |
1353 | * Set standard DMA size (128). Note that | |
1354 | * a DMA size of 512 causes rx overruns and tx errors | |
1355 | * on pci-e cards (tested on 5424 but since rx overruns | |
1356 | * also occur on 5416/5418 with madwifi we set 128 | |
1357 | * for all PCI-E cards to be safe). | |
1358 | * | |
1359 | * XXX: need to check 5210 for this | |
1360 | * TODO: Check out tx triger level, it's always 64 on dumps but I | |
1361 | * guess we can tweak it and see how it goes ;-) | |
1362 | */ | |
1363 | if (ah->ah_version != AR5K_AR5210) { | |
1364 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, | |
1365 | AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); | |
1366 | AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, | |
1367 | AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); | |
1368 | } | |
1369 | ||
c6e387a2 NK |
1370 | /* Pre-enable interrupts on 5211/5212*/ |
1371 | if (ah->ah_version != AR5K_AR5210) | |
4c674c60 | 1372 | ath5k_hw_set_imr(ah, ah->ah_imr); |
c6e387a2 | 1373 | |
e8f055f0 NK |
1374 | /* Enable 32KHz clock function for AR5212+ chips |
1375 | * Set clocks to 32KHz operation and use an | |
1376 | * external 32KHz crystal when sleeping if one | |
1377 | * exists */ | |
5d6ce628 | 1378 | if (ah->ah_version == AR5K_AR5212 && |
ccfe5552 | 1379 | op_mode != NL80211_IFTYPE_AP) |
5d6ce628 | 1380 | ath5k_hw_set_sleep_clock(ah, true); |
c6e387a2 NK |
1381 | |
1382 | /* | |
a3b980fd | 1383 | * Disable beacons and reset the TSF |
c6e387a2 | 1384 | */ |
a3b980fd BR |
1385 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); |
1386 | ath5k_hw_reset_tsf(ah); | |
c6e387a2 NK |
1387 | return 0; |
1388 | } |