blob: 91a2b2166def2e65bc6bee3c0836b45c5bded958 [file] [log] [blame]
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001/*
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
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030022/*****************************\
23 Reset functions and helpers
24\*****************************/
25
Luis R. Rodriguezbcd8f542009-09-09 22:43:17 -070026#include <asm/unaligned.h>
27
Nick Kossifidise8f055f2009-02-09 06:12:58 +020028#include <linux/pci.h> /* To determine if a card is pci-e */
Forrest Zhanga54be5d2009-05-13 11:14:39 -040029#include <linux/log2.h>
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030030#include "ath5k.h"
31#include "reg.h"
32#include "base.h"
33#include "debug.h"
34
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020035
36/******************\
37* Helper functions *
38\******************/
39
Pavel Roskinec182d92010-02-18 20:28:41 -050040/*
41 * Check if a register write has been completed
42 */
43int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
44 bool is_set)
45{
46 int i;
47 u32 data;
48
49 for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
50 data = ath5k_hw_reg_read(ah, reg);
51 if (is_set && (data & flag))
52 break;
53 else if ((data & flag) == val)
54 break;
55 udelay(15);
56 }
57
58 return (i <= 0) ? -EAGAIN : 0;
59}
60
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020061
62/*************************\
63* Clock related functions *
64\*************************/
65
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030066/**
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020067 * ath5k_hw_htoclock - Translate usec to hw clock units
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030068 *
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020069 * @ah: The &struct ath5k_hw
70 * @usec: value in microseconds
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030071 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020072unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030073{
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020074 struct ath_common *common = ath5k_hw_common(ah);
75 return usec * common->clockrate;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030076}
77
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020078/**
79 * ath5k_hw_clocktoh - Translate hw clock units to usec
80 * @clock: value in hw clock units
81 */
82unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
83{
84 struct ath_common *common = ath5k_hw_common(ah);
85 return clock / common->clockrate;
86}
87
88/**
89 * ath5k_hw_set_clockrate - Set common->clockrate for the current channel
90 *
91 * @ah: The &struct ath5k_hw
92 */
93void ath5k_hw_set_clockrate(struct ath5k_hw *ah)
94{
95 struct ieee80211_channel *channel = ah->ah_current_channel;
96 struct ath_common *common = ath5k_hw_common(ah);
97 int clock;
98
99 if (channel->hw_value & CHANNEL_5GHZ)
100 clock = 40; /* 802.11a */
101 else if (channel->hw_value & CHANNEL_CCK)
102 clock = 22; /* 802.11b */
103 else
104 clock = 44; /* 802.11g */
105
106 /* Clock rate in turbo modes is twice the normal rate */
107 if (channel->hw_value & CHANNEL_TURBO)
108 clock *= 2;
109
110 common->clockrate = clock;
111}
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300112
113/*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200114 * If there is an external 32KHz crystal available, use it
115 * as ref. clock instead of 32/40MHz clock and baseband clocks
116 * to save power during sleep or restore normal 32/40MHz
117 * operation.
118 *
119 * XXX: When operating on 32KHz certain PHY registers (27 - 31,
120 * 123 - 127) require delay on access.
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300121 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200122static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300123{
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200124 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
125 u32 scal, spending, usec32;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300126
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200127 /* Only set 32KHz settings if we have an external
128 * 32KHz crystal present */
129 if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
130 AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
131 enable) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300132
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200133 /* 1 usec/cycle */
134 AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
135 /* Set up tsf increment on each cycle */
136 AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300137
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200138 /* Set baseband sleep control registers
139 * and sleep control rate */
140 ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300141
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200142 if ((ah->ah_radio == AR5K_RF5112) ||
143 (ah->ah_radio == AR5K_RF5413) ||
144 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
145 spending = 0x14;
146 else
147 spending = 0x18;
148 ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300149
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200150 if ((ah->ah_radio == AR5K_RF5112) ||
151 (ah->ah_radio == AR5K_RF5413) ||
152 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
153 ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
154 ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
155 ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
156 ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
157 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
158 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
159 } else {
160 ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
161 ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
162 ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
163 ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
164 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
165 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
166 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300167
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200168 /* Enable sleep clock operation */
169 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
170 AR5K_PCICFG_SLEEP_CLOCK_EN);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300171
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200172 } else {
173
174 /* Disable sleep clock operation and
175 * restore default parameters */
176 AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
177 AR5K_PCICFG_SLEEP_CLOCK_EN);
178
179 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
180 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
181
182 ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
183 ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
184
185 if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
186 scal = AR5K_PHY_SCAL_32MHZ_2417;
187 else if (ee->ee_is_hb63)
188 scal = AR5K_PHY_SCAL_32MHZ_HB63;
189 else
190 scal = AR5K_PHY_SCAL_32MHZ;
191 ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
192
193 ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
194 ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
195
196 if ((ah->ah_radio == AR5K_RF5112) ||
197 (ah->ah_radio == AR5K_RF5413) ||
198 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
199 spending = 0x14;
200 else
201 spending = 0x18;
202 ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
203
204 if ((ah->ah_radio == AR5K_RF5112) ||
205 (ah->ah_radio == AR5K_RF5413))
206 usec32 = 39;
207 else
208 usec32 = 31;
209 AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32);
210
211 AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300212 }
213}
214
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200215
216/*********************\
217* Reset/Sleep control *
218\*********************/
219
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300220/*
221 * Reset chipset
222 */
223static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
224{
225 int ret;
226 u32 mask = val ? val : ~0U;
227
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300228 /* Read-and-clear RX Descriptor Pointer*/
229 ath5k_hw_reg_read(ah, AR5K_RXDP);
230
231 /*
232 * Reset the device and wait until success
233 */
234 ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
235
236 /* Wait at least 128 PCI clocks */
237 udelay(15);
238
239 if (ah->ah_version == AR5K_AR5210) {
Nick Kossifidis84e463f2008-09-17 03:33:19 +0300240 val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
241 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
242 mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
243 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300244 } else {
245 val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
246 mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
247 }
248
249 ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false);
250
251 /*
252 * Reset configuration register (for hw byte-swap). Note that this
253 * is only set for big endian. We do the necessary magic in
254 * AR5K_INIT_CFG.
255 */
256 if ((val & AR5K_RESET_CTL_PCU) == 0)
257 ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
258
259 return ret;
260}
261
262/*
263 * Sleep control
264 */
Pavel Roskin626ede62010-02-18 20:28:02 -0500265static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
266 bool set_chip, u16 sleep_duration)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300267{
268 unsigned int i;
269 u32 staid, data;
270
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300271 staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
272
273 switch (mode) {
274 case AR5K_PM_AUTO:
275 staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
276 /* fallthrough */
277 case AR5K_PM_NETWORK_SLEEP:
278 if (set_chip)
279 ath5k_hw_reg_write(ah,
280 AR5K_SLEEP_CTL_SLE_ALLOW |
281 sleep_duration,
282 AR5K_SLEEP_CTL);
283
284 staid |= AR5K_STA_ID1_PWR_SV;
285 break;
286
287 case AR5K_PM_FULL_SLEEP:
288 if (set_chip)
289 ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
290 AR5K_SLEEP_CTL);
291
292 staid |= AR5K_STA_ID1_PWR_SV;
293 break;
294
295 case AR5K_PM_AWAKE:
296
297 staid &= ~AR5K_STA_ID1_PWR_SV;
298
299 if (!set_chip)
300 goto commit;
301
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300302 data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300303
304 /* If card is down we 'll get 0xffff... so we
305 * need to clean this up before we write the register
306 */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300307 if (data & 0xffc00000)
308 data = 0;
309 else
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300310 /* Preserve sleep duration etc */
311 data = data & ~AR5K_SLEEP_CTL_SLE;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300312
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300313 ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
314 AR5K_SLEEP_CTL);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300315 udelay(15);
316
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300317 for (i = 200; i > 0; i--) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300318 /* Check if the chip did wake up */
319 if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
320 AR5K_PCICFG_SPWR_DN) == 0)
321 break;
322
323 /* Wait a bit and retry */
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300324 udelay(50);
325 ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
326 AR5K_SLEEP_CTL);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300327 }
328
329 /* Fail if the chip didn't wake up */
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300330 if (i == 0)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300331 return -EIO;
332
333 break;
334
335 default:
336 return -EINVAL;
337 }
338
339commit:
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300340 ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
341
342 return 0;
343}
344
345/*
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300346 * Put device on hold
347 *
348 * Put MAC and Baseband on warm reset and
349 * keep that state (don't clean sleep control
350 * register). After this MAC and Baseband are
351 * disabled and a full reset is needed to come
352 * back. This way we save as much power as possible
Bob Copeland8801df82010-08-21 16:39:02 -0400353 * without putting the card on full sleep.
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300354 */
355int ath5k_hw_on_hold(struct ath5k_hw *ah)
356{
357 struct pci_dev *pdev = ah->ah_sc->pdev;
358 u32 bus_flags;
359 int ret;
360
361 /* Make sure device is awake */
362 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
363 if (ret) {
364 ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
365 return ret;
366 }
367
368 /*
369 * Put chipset on warm reset...
370 *
Bob Copeland8801df82010-08-21 16:39:02 -0400371 * Note: putting PCI core on warm reset on PCI-E cards
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300372 * results card to hang and always return 0xffff... so
373 * we ingore that flag for PCI-E cards. On PCI cards
374 * this flag gets cleared after 64 PCI clocks.
375 */
376 bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
377
378 if (ah->ah_version == AR5K_AR5210) {
379 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
380 AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
381 AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
382 mdelay(2);
383 } else {
384 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
385 AR5K_RESET_CTL_BASEBAND | bus_flags);
386 }
387
388 if (ret) {
389 ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n");
390 return -EIO;
391 }
392
393 /* ...wakeup again!*/
394 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
395 if (ret) {
396 ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n");
397 return ret;
398 }
399
400 return ret;
401}
402
403/*
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200404 * Bring up MAC + PHY Chips and program PLL
405 * TODO: Half/Quarter rate support
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300406 */
407int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
408{
409 struct pci_dev *pdev = ah->ah_sc->pdev;
410 u32 turbo, mode, clock, bus_flags;
411 int ret;
412
413 turbo = 0;
414 mode = 0;
415 clock = 0;
416
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300417 /* Wakeup the device */
418 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
419 if (ret) {
420 ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
421 return ret;
422 }
423
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300424 /*
425 * Put chipset on warm reset...
426 *
Bob Copeland8801df82010-08-21 16:39:02 -0400427 * Note: putting PCI core on warm reset on PCI-E cards
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300428 * results card to hang and always return 0xffff... so
429 * we ingore that flag for PCI-E cards. On PCI cards
430 * this flag gets cleared after 64 PCI clocks.
431 */
432 bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
433
434 if (ah->ah_version == AR5K_AR5210) {
435 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
436 AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
437 AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
438 mdelay(2);
439 } else {
440 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
441 AR5K_RESET_CTL_BASEBAND | bus_flags);
442 }
443
444 if (ret) {
445 ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
446 return -EIO;
447 }
448
449 /* ...wakeup again!...*/
450 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
451 if (ret) {
452 ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
453 return ret;
454 }
455
456 /* ...clear reset control register and pull device out of
457 * warm reset */
458 if (ath5k_hw_nic_reset(ah, 0)) {
459 ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
460 return -EIO;
461 }
462
463 /* On initialization skip PLL programming since we don't have
464 * a channel / mode set yet */
465 if (initial)
466 return 0;
467
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300468 if (ah->ah_version != AR5K_AR5210) {
469 /*
470 * Get channel mode flags
471 */
472
473 if (ah->ah_radio >= AR5K_RF5112) {
474 mode = AR5K_PHY_MODE_RAD_RF5112;
475 clock = AR5K_PHY_PLL_RF5112;
476 } else {
477 mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/
478 clock = AR5K_PHY_PLL_RF5111; /*Zero*/
479 }
480
481 if (flags & CHANNEL_2GHZ) {
482 mode |= AR5K_PHY_MODE_FREQ_2GHZ;
483 clock |= AR5K_PHY_PLL_44MHZ;
484
485 if (flags & CHANNEL_CCK) {
486 mode |= AR5K_PHY_MODE_MOD_CCK;
487 } else if (flags & CHANNEL_OFDM) {
488 /* XXX Dynamic OFDM/CCK is not supported by the
489 * AR5211 so we set MOD_OFDM for plain g (no
490 * CCK headers) operation. We need to test
491 * this, 5211 might support ofdm-only g after
492 * all, there are also initial register values
493 * in the code for g mode (see initvals.c). */
494 if (ah->ah_version == AR5K_AR5211)
495 mode |= AR5K_PHY_MODE_MOD_OFDM;
496 else
497 mode |= AR5K_PHY_MODE_MOD_DYN;
498 } else {
499 ATH5K_ERR(ah->ah_sc,
500 "invalid radio modulation mode\n");
501 return -EINVAL;
502 }
503 } else if (flags & CHANNEL_5GHZ) {
504 mode |= AR5K_PHY_MODE_FREQ_5GHZ;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200505
506 if (ah->ah_radio == AR5K_RF5413)
Pavel Roskin807e3732009-03-27 17:47:27 -0400507 clock = AR5K_PHY_PLL_40MHZ_5413;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200508 else
509 clock |= AR5K_PHY_PLL_40MHZ;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300510
511 if (flags & CHANNEL_OFDM)
512 mode |= AR5K_PHY_MODE_MOD_OFDM;
513 else {
514 ATH5K_ERR(ah->ah_sc,
515 "invalid radio modulation mode\n");
516 return -EINVAL;
517 }
518 } else {
519 ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n");
520 return -EINVAL;
521 }
522
523 if (flags & CHANNEL_TURBO)
524 turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
525 } else { /* Reset the device */
526
527 /* ...enable Atheros turbo mode if requested */
528 if (flags & CHANNEL_TURBO)
529 ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
530 AR5K_PHY_TURBO);
531 }
532
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300533 if (ah->ah_version != AR5K_AR5210) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300534
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200535 /* ...update PLL if needed */
536 if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) {
537 ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
538 udelay(300);
539 }
540
541 /* ...set the PHY operating mode */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300542 ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
543 ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
544 }
545
546 return 0;
547}
548
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200549
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200550/**************************************\
551* Post-initvals register modifications *
552\**************************************/
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200553
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200554/* TODO: Half/Quarter rate */
555static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
556 struct ieee80211_channel *channel)
557{
558 if (ah->ah_version == AR5K_AR5212 &&
559 ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
560
561 /* Setup ADC control */
562 ath5k_hw_reg_write(ah,
563 (AR5K_REG_SM(2,
564 AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) |
565 AR5K_REG_SM(2,
566 AR5K_PHY_ADC_CTL_INBUFGAIN_ON) |
567 AR5K_PHY_ADC_CTL_PWD_DAC_OFF |
568 AR5K_PHY_ADC_CTL_PWD_ADC_OFF),
569 AR5K_PHY_ADC_CTL);
570
571
572
573 /* Disable barker RSSI threshold */
574 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
575 AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR);
576
577 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
578 AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2);
579
580 /* Set the mute mask */
581 ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
582 }
583
584 /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */
585 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B)
586 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH);
587
588 /* Enable DCU double buffering */
589 if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B)
590 AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
591 AR5K_TXCFG_DCU_DBL_BUF_DIS);
592
593 /* Set DAC/ADC delays */
594 if (ah->ah_version == AR5K_AR5212) {
595 u32 scal;
Nick Kossifidis1889ba02009-04-30 15:55:46 -0400596 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200597 if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
598 scal = AR5K_PHY_SCAL_32MHZ_2417;
Nick Kossifidis1889ba02009-04-30 15:55:46 -0400599 else if (ee->ee_is_hb63)
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200600 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
606 /* Set fast ADC */
607 if ((ah->ah_radio == AR5K_RF5413) ||
608 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
609 u32 fast_adc = true;
610
611 if (channel->center_freq == 2462 ||
612 channel->center_freq == 2467)
613 fast_adc = 0;
614
615 /* Only update if needed */
616 if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc)
617 ath5k_hw_reg_write(ah, fast_adc,
618 AR5K_PHY_FAST_ADC);
619 }
620
621 /* Fix for first revision of the RF5112 RF chipset */
622 if (ah->ah_radio == AR5K_RF5112 &&
623 ah->ah_radio_5ghz_revision <
624 AR5K_SREV_RAD_5112A) {
625 u32 data;
626 ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
627 AR5K_PHY_CCKTXCTL);
628 if (channel->hw_value & CHANNEL_5GHZ)
629 data = 0xffb81020;
630 else
631 data = 0xffb80d20;
632 ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
633 }
634
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200635 if ((ah->ah_radio == AR5K_RF5112) &&
636 (ah->ah_mac_srev < AR5K_SREV_AR5211)) {
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200637 u32 usec_reg;
638 /* 5311 has different tx/rx latency masks
639 * from 5211, since we deal 5311 the same
640 * as 5211 when setting initvals, shift
641 * values here to their proper locations */
642 usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
643 ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 |
644 AR5K_USEC_32 |
645 AR5K_USEC_TX_LATENCY_5211 |
646 AR5K_REG_SM(29,
647 AR5K_USEC_RX_LATENCY_5210)),
648 AR5K_USEC_5211);
649 /* Clear QCU/DCU clock gating register */
650 ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
651 /* Set DAC/ADC delays */
652 ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL);
653 /* Enable PCU FIFO corruption ECO */
654 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
655 AR5K_DIAG_SW_ECO_ENABLE);
656 }
657}
658
659static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
Bruno Randolf0ca74022010-06-07 13:11:30 +0900660 struct ieee80211_channel *channel, u8 ee_mode)
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200661{
662 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200663 s16 cck_ofdm_pwr_delta;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200664
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200665 /* TODO: Add support for AR5210 EEPROM */
666 if (ah->ah_version == AR5K_AR5210)
667 return;
668
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200669 /* Adjust power delta for channel 14 */
670 if (channel->center_freq == 2484)
671 cck_ofdm_pwr_delta =
672 ((ee->ee_cck_ofdm_power_delta -
673 ee->ee_scaled_cck_delta) * 2) / 10;
674 else
675 cck_ofdm_pwr_delta =
676 (ee->ee_cck_ofdm_power_delta * 2) / 10;
677
678 /* Set CCK to OFDM power delta on tx power
679 * adjustment register */
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200680 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200681 if (channel->hw_value == CHANNEL_G)
682 ath5k_hw_reg_write(ah,
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200683 AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200684 AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
685 AR5K_REG_SM((cck_ofdm_pwr_delta * -1),
686 AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
687 AR5K_PHY_TX_PWR_ADJ);
688 else
689 ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ);
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200690 } else {
691 /* For older revs we scale power on sw during tx power
692 * setup */
693 ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta;
694 ah->ah_txpower.txp_cck_ofdm_gainf_delta =
695 ee->ee_cck_ofdm_gain_delta;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200696 }
697
Bruno Randolf0ca74022010-06-07 13:11:30 +0900698 /* XXX: necessary here? is called from ath5k_hw_set_antenna_mode()
699 * too */
700 ath5k_hw_set_antenna_switch(ah, ee_mode);
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200701
702 /* Noise floor threshold */
703 ath5k_hw_reg_write(ah,
704 AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
705 AR5K_PHY_NFTHRES);
706
707 if ((channel->hw_value & CHANNEL_TURBO) &&
708 (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
709 /* Switch settling time (Turbo) */
710 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
711 AR5K_PHY_SETTLING_SWITCH,
712 ee->ee_switch_settling_turbo[ee_mode]);
713
714 /* Tx/Rx attenuation (Turbo) */
715 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
716 AR5K_PHY_GAIN_TXRX_ATTEN,
717 ee->ee_atn_tx_rx_turbo[ee_mode]);
718
719 /* ADC/PGA desired size (Turbo) */
720 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
721 AR5K_PHY_DESIRED_SIZE_ADC,
722 ee->ee_adc_desired_size_turbo[ee_mode]);
723
724 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
725 AR5K_PHY_DESIRED_SIZE_PGA,
726 ee->ee_pga_desired_size_turbo[ee_mode]);
727
728 /* Tx/Rx margin (Turbo) */
729 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
730 AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
731 ee->ee_margin_tx_rx_turbo[ee_mode]);
732
733 } else {
734 /* Switch settling time */
735 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
736 AR5K_PHY_SETTLING_SWITCH,
737 ee->ee_switch_settling[ee_mode]);
738
739 /* Tx/Rx attenuation */
740 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
741 AR5K_PHY_GAIN_TXRX_ATTEN,
742 ee->ee_atn_tx_rx[ee_mode]);
743
744 /* ADC/PGA desired size */
745 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
746 AR5K_PHY_DESIRED_SIZE_ADC,
747 ee->ee_adc_desired_size[ee_mode]);
748
749 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
750 AR5K_PHY_DESIRED_SIZE_PGA,
751 ee->ee_pga_desired_size[ee_mode]);
752
753 /* Tx/Rx margin */
754 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
755 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
756 AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
757 ee->ee_margin_tx_rx[ee_mode]);
758 }
759
760 /* XPA delays */
761 ath5k_hw_reg_write(ah,
762 (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
763 (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
764 (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
765 (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
766
767 /* XLNA delay */
768 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3,
769 AR5K_PHY_RF_CTL3_TXE2XLNA_ON,
770 ee->ee_tx_end2xlna_enable[ee_mode]);
771
772 /* Thresh64 (ANI) */
773 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF,
774 AR5K_PHY_NF_THRESH62,
775 ee->ee_thr_62[ee_mode]);
776
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200777 /* False detect backoff for channels
778 * that have spur noise. Write the new
779 * cyclic power RSSI threshold. */
780 if (ath5k_hw_chan_has_spur_noise(ah, channel))
781 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
782 AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
783 AR5K_INIT_CYCRSSI_THR1 +
784 ee->ee_false_detect[ee_mode]);
785 else
786 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
787 AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
788 AR5K_INIT_CYCRSSI_THR1);
789
Bruno Randolf5f13bfa2010-03-09 16:56:10 +0900790 /* I/Q correction (set enable bit last to match HAL sources) */
791 /* TODO: Per channel i/q infos ? */
792 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
793 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF,
794 ee->ee_i_cal[ee_mode]);
795 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF,
796 ee->ee_q_cal[ee_mode]);
797 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE);
798 }
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200799
800 /* Heavy clipping -disable for now */
801 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1)
802 ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200803}
804
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200805
806/*********************\
807* Main reset function *
808\*********************/
809
Johannes Berg05c914f2008-09-11 00:01:58 +0200810int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300811 struct ieee80211_channel *channel, bool change_channel)
812{
Luis R. Rodriguez954fece2009-09-10 10:51:33 -0700813 struct ath_common *common = ath5k_hw_common(ah);
Bruno Randolf20fbed22010-06-07 13:11:35 +0900814 u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo;
Bruno Randolf0ca74022010-06-07 13:11:30 +0900815 u8 mode, freq, ee_mode;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200816 int i, ret;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300817
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300818 ee_mode = 0;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200819 staid1_flags = 0;
820 tsf_up = 0;
821 tsf_lo = 0;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300822 freq = 0;
823 mode = 0;
824
825 /*
Nick Kossifidise088f232010-11-23 20:43:18 +0200826 * Stop PCU
827 */
828 ath5k_hw_stop_rx_pcu(ah);
829
830 /*
Nick Kossifidisd41174f2010-11-23 20:41:15 +0200831 * Stop DMA
832 *
833 * Note: If DMA didn't stop continue
834 * since only a reset will fix it.
835 */
836 ath5k_hw_dma_stop(ah);
837
838 /*
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300839 * Save some registers before a reset
840 */
841 /*DCU/Antenna selection not available on 5210*/
842 if (ah->ah_version != AR5K_AR5210) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300843
844 switch (channel->hw_value & CHANNEL_MODES) {
845 case CHANNEL_A:
846 mode = AR5K_MODE_11A;
847 freq = AR5K_INI_RFGAIN_5GHZ;
848 ee_mode = AR5K_EEPROM_MODE_11A;
849 break;
850 case CHANNEL_G:
851 mode = AR5K_MODE_11G;
852 freq = AR5K_INI_RFGAIN_2GHZ;
853 ee_mode = AR5K_EEPROM_MODE_11G;
854 break;
855 case CHANNEL_B:
856 mode = AR5K_MODE_11B;
857 freq = AR5K_INI_RFGAIN_2GHZ;
858 ee_mode = AR5K_EEPROM_MODE_11B;
859 break;
860 case CHANNEL_T:
861 mode = AR5K_MODE_11A_TURBO;
862 freq = AR5K_INI_RFGAIN_5GHZ;
863 ee_mode = AR5K_EEPROM_MODE_11A;
864 break;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300865 case CHANNEL_TG:
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200866 if (ah->ah_version == AR5K_AR5211) {
867 ATH5K_ERR(ah->ah_sc,
868 "TurboG mode not available on 5211");
869 return -EINVAL;
870 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300871 mode = AR5K_MODE_11G_TURBO;
872 freq = AR5K_INI_RFGAIN_2GHZ;
873 ee_mode = AR5K_EEPROM_MODE_11G;
874 break;
875 case CHANNEL_XR:
876 if (ah->ah_version == AR5K_AR5211) {
877 ATH5K_ERR(ah->ah_sc,
878 "XR mode not available on 5211");
879 return -EINVAL;
880 }
881 mode = AR5K_MODE_XR;
882 freq = AR5K_INI_RFGAIN_5GHZ;
883 ee_mode = AR5K_EEPROM_MODE_11A;
884 break;
885 default:
886 ATH5K_ERR(ah->ah_sc,
887 "invalid channel: %d\n", channel->center_freq);
888 return -EINVAL;
889 }
890
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200891 if (change_channel) {
892 /*
893 * Save frame sequence count
894 * For revs. after Oahu, only save
895 * seq num for DCU 0 (Global seq num)
896 */
897 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
898
899 for (i = 0; i < 10; i++)
900 s_seq[i] = ath5k_hw_reg_read(ah,
901 AR5K_QUEUE_DCU_SEQNUM(i));
902
903 } else {
904 s_seq[0] = ath5k_hw_reg_read(ah,
905 AR5K_QUEUE_DCU_SEQNUM(0));
906 }
907
Bob Copelanda180a132010-08-15 13:03:12 -0400908 /* TSF accelerates on AR5211 during reset
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200909 * As a workaround save it here and restore
910 * it later so that it's back in time after
911 * reset. This way it'll get re-synced on the
912 * next beacon without breaking ad-hoc.
913 *
914 * On AR5212 TSF is almost preserved across a
915 * reset so it stays back in time anyway and
916 * we don't have to save/restore it.
917 *
918 * XXX: Since this breaks power saving we have
919 * to disable power saving until we receive the
920 * next beacon, so we can resync beacon timers */
921 if (ah->ah_version == AR5K_AR5211) {
922 tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
923 tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
924 }
925 }
926
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200927 if (ah->ah_version == AR5K_AR5212) {
928 /* Restore normal 32/40MHz clock operation
929 * to avoid register access delay on certain
930 * PHY registers */
931 ath5k_hw_set_sleep_clock(ah, false);
932
933 /* Since we are going to write rf buffer
934 * check if we have any pending gain_F
935 * optimization settings */
936 if (change_channel && ah->ah_rf_banks != NULL)
937 ath5k_hw_gainf_calibrate(ah);
938 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300939 }
940
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200941 /*GPIOs*/
942 s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
943 AR5K_PCICFG_LEDSTATE;
944 s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
945 s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
Nick Kossifidisa406c132009-02-09 06:08:51 +0200946
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200947 /* AR5K_STA_ID1 flags, only preserve antenna
948 * settings and ack/cts rate mode */
949 staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) &
950 (AR5K_STA_ID1_DEFAULT_ANTENNA |
951 AR5K_STA_ID1_DESC_ANTENNA |
952 AR5K_STA_ID1_RTS_DEF_ANTENNA |
953 AR5K_STA_ID1_ACKCTS_6MB |
954 AR5K_STA_ID1_BASE_RATE_11B |
955 AR5K_STA_ID1_SELFGEN_DEF_ANT);
956
957 /* Wakeup the device */
958 ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
959 if (ret)
960 return ret;
961
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200962 /* PHY access enable */
963 if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
964 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
965 else
966 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40,
967 AR5K_PHY(0));
968
969 /* Write initial settings */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300970 ret = ath5k_hw_write_initvals(ah, mode, change_channel);
971 if (ret)
972 return ret;
973
974 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200975 * Tweak initval settings for revised
976 * chipsets and add some more config
977 * bits
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300978 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200979 ath5k_hw_tweak_initval_settings(ah, channel);
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200980
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200981 /* Commit values from EEPROM */
982 ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300983
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300984
985 /*
986 * Restore saved values
987 */
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200988
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300989 /*DCU/Antenna selection not available on 5210*/
990 if (ah->ah_version != AR5K_AR5210) {
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200991
992 if (change_channel) {
993 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
994 for (i = 0; i < 10; i++)
995 ath5k_hw_reg_write(ah, s_seq[i],
996 AR5K_QUEUE_DCU_SEQNUM(i));
997 } else {
998 ath5k_hw_reg_write(ah, s_seq[0],
999 AR5K_QUEUE_DCU_SEQNUM(0));
1000 }
1001
1002
1003 if (ah->ah_version == AR5K_AR5211) {
1004 ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
1005 ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
1006 }
1007 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001008 }
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001009
1010 /* Ledstate */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001011 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001012
1013 /* Gpio settings */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001014 ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
1015 ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
1016
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001017 /* Restore sta_id flags and preserve our mac address*/
Luis R. Rodriguez954fece2009-09-10 10:51:33 -07001018 ath5k_hw_reg_write(ah,
1019 get_unaligned_le32(common->macaddr),
1020 AR5K_STA_ID0);
1021 ath5k_hw_reg_write(ah,
Luis R. Rodriguez91b9eb82009-10-06 20:44:30 -04001022 staid1_flags | get_unaligned_le16(common->macaddr + 4),
Luis R. Rodriguez954fece2009-09-10 10:51:33 -07001023 AR5K_STA_ID1);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001024
1025
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001026 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001027 * Initialize PCU
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001028 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001029 ath5k_hw_pcu_init(ah, op_mode, mode);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001030
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001031 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001032 * Initialize PHY
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001033 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001034 ret = ath5k_hw_phy_init(ah, channel, mode, ee_mode, freq);
1035 if (ret) {
1036 ATH5K_ERR(ah->ah_sc,
1037 "failed to initialize PHY (%i) !\n", ret);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001038 return ret;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001039 }
1040
1041 /*
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001042 * Configure QCUs/DCUs
1043 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001044 ret = ath5k_hw_init_queues(ah);
1045 if (ret)
1046 return ret;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001047
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001048
1049 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001050 * Initialize DMA/Interrupts
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001051 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001052 ath5k_hw_dma_init(ah);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001053
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001054
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001055 /* Enable 32KHz clock function for AR5212+ chips
1056 * Set clocks to 32KHz operation and use an
1057 * external 32KHz crystal when sleeping if one
1058 * exists */
Bob Copeland5d6ce622010-01-20 23:51:03 -05001059 if (ah->ah_version == AR5K_AR5212 &&
Bruno Randolfccfe5552010-03-09 16:55:38 +09001060 op_mode != NL80211_IFTYPE_AP)
Bob Copeland5d6ce622010-01-20 23:51:03 -05001061 ath5k_hw_set_sleep_clock(ah, true);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001062
1063 /*
Bruno Randolfa3b980f2010-03-09 16:55:33 +09001064 * Disable beacons and reset the TSF
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001065 */
Bruno Randolfa3b980f2010-03-09 16:55:33 +09001066 AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
1067 ath5k_hw_reset_tsf(ah);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001068 return 0;
1069}