blob: de28be4296a6deeae585f9cacce1ef88c20d0335 [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
Pavel Roskin0a5d3812011-07-07 18:13:24 -040028#include <linux/pci.h> /* To determine if a card is pci-e */
Forrest Zhanga54be5d2009-05-13 11:14:39 -040029#include <linux/log2.h>
Felix Fietkau4cebb342010-12-02 10:27:21 +010030#include <linux/platform_device.h>
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030031#include "ath5k.h"
32#include "reg.h"
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030033#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/**
Nick Kossifidisc2975602010-11-23 21:00:37 +020089 * ath5k_hw_init_core_clock - Initialize core clock
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020090 *
Nick Kossifidisc2975602010-11-23 21:00:37 +020091 * @ah The &struct ath5k_hw
92 *
93 * Initialize core clock parameters (usec, usec32, latencies etc).
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020094 */
Nick Kossifidisc2975602010-11-23 21:00:37 +020095static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020096{
97 struct ieee80211_channel *channel = ah->ah_current_channel;
98 struct ath_common *common = ath5k_hw_common(ah);
Nick Kossifidisc2975602010-11-23 21:00:37 +020099 u32 usec_reg, txlat, rxlat, usec, clock, sclock, txf2txs;
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200100
Nick Kossifidisc2975602010-11-23 21:00:37 +0200101 /*
102 * Set core clock frequency
103 */
Pavel Roskin32c25462011-07-23 09:29:09 -0400104 switch (channel->hw_value) {
105 case AR5K_MODE_11A:
106 clock = 40;
107 break;
108 case AR5K_MODE_11B:
109 clock = 22;
110 break;
111 case AR5K_MODE_11G:
112 default:
113 clock = 44;
114 break;
115 }
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200116
Nick Kossifidisc2975602010-11-23 21:00:37 +0200117 /* Use clock multiplier for non-default
118 * bwmode */
119 switch (ah->ah_bwmode) {
120 case AR5K_BWMODE_40MHZ:
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200121 clock *= 2;
Nick Kossifidisc2975602010-11-23 21:00:37 +0200122 break;
123 case AR5K_BWMODE_10MHZ:
124 clock /= 2;
125 break;
126 case AR5K_BWMODE_5MHZ:
127 clock /= 4;
128 break;
129 default:
130 break;
131 }
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200132
133 common->clockrate = clock;
Nick Kossifidisc2975602010-11-23 21:00:37 +0200134
135 /*
136 * Set USEC parameters
137 */
138 /* Set USEC counter on PCU*/
139 usec = clock - 1;
140 usec = AR5K_REG_SM(usec, AR5K_USEC_1);
141
142 /* Set usec duration on DCU */
143 if (ah->ah_version != AR5K_AR5210)
144 AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
145 AR5K_DCU_GBL_IFS_MISC_USEC_DUR,
146 clock);
147
148 /* Set 32MHz USEC counter */
149 if ((ah->ah_radio == AR5K_RF5112) ||
Felix Fietkauf0064382011-07-12 09:02:03 +0800150 (ah->ah_radio == AR5K_RF2413) ||
Pavel Roskine4bbf2f2011-07-07 18:14:13 -0400151 (ah->ah_radio == AR5K_RF5413) ||
152 (ah->ah_radio == AR5K_RF2316) ||
153 (ah->ah_radio == AR5K_RF2317))
154 /* Remain on 40MHz clock ? */
Nick Kossifidisc2975602010-11-23 21:00:37 +0200155 sclock = 40 - 1;
156 else
157 sclock = 32 - 1;
158 sclock = AR5K_REG_SM(sclock, AR5K_USEC_32);
159
160 /*
161 * Set tx/rx latencies
162 */
163 usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
164 txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211);
165 rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211);
166
167 /*
John W. Linvillee2452922011-04-29 14:35:14 -0400168 * Set default Tx frame to Tx data start delay
169 */
170 txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT;
171
172 /*
Nick Kossifidisc2975602010-11-23 21:00:37 +0200173 * 5210 initvals don't include usec settings
174 * so we need to use magic values here for
175 * tx/rx latencies
176 */
177 if (ah->ah_version == AR5K_AR5210) {
178 /* same for turbo */
179 txlat = AR5K_INIT_TX_LATENCY_5210;
180 rxlat = AR5K_INIT_RX_LATENCY_5210;
181 }
182
183 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
184 /* 5311 has different tx/rx latency masks
185 * from 5211, since we deal 5311 the same
186 * as 5211 when setting initvals, shift
187 * values here to their proper locations
188 *
189 * Note: Initvals indicate tx/rx/ latencies
190 * are the same for turbo mode */
191 txlat = AR5K_REG_SM(txlat, AR5K_USEC_TX_LATENCY_5210);
192 rxlat = AR5K_REG_SM(rxlat, AR5K_USEC_RX_LATENCY_5210);
193 } else
194 switch (ah->ah_bwmode) {
195 case AR5K_BWMODE_10MHZ:
196 txlat = AR5K_REG_SM(txlat * 2,
197 AR5K_USEC_TX_LATENCY_5211);
198 rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX,
199 AR5K_USEC_RX_LATENCY_5211);
200 txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_10MHZ;
201 break;
202 case AR5K_BWMODE_5MHZ:
203 txlat = AR5K_REG_SM(txlat * 4,
204 AR5K_USEC_TX_LATENCY_5211);
205 rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX,
206 AR5K_USEC_RX_LATENCY_5211);
207 txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_5MHZ;
208 break;
209 case AR5K_BWMODE_40MHZ:
210 txlat = AR5K_INIT_TX_LAT_MIN;
211 rxlat = AR5K_REG_SM(rxlat / 2,
212 AR5K_USEC_RX_LATENCY_5211);
213 txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT;
214 break;
215 default:
216 break;
217 }
218
219 usec_reg = (usec | sclock | txlat | rxlat);
220 ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC);
221
Pavel Roskin6a2a0e72011-07-09 00:17:51 -0400222 /* On 5112 set tx frame to tx data start delay */
Nick Kossifidisc2975602010-11-23 21:00:37 +0200223 if (ah->ah_radio == AR5K_RF5112) {
224 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2,
225 AR5K_PHY_RF_CTL2_TXF2TXD_START,
226 txf2txs);
227 }
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200228}
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300229
230/*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200231 * If there is an external 32KHz crystal available, use it
232 * as ref. clock instead of 32/40MHz clock and baseband clocks
233 * to save power during sleep or restore normal 32/40MHz
234 * operation.
235 *
236 * XXX: When operating on 32KHz certain PHY registers (27 - 31,
237 * 123 - 127) require delay on access.
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300238 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200239static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300240{
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200241 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
Felix Fietkauf0064382011-07-12 09:02:03 +0800242 u32 scal, spending, sclock;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300243
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200244 /* Only set 32KHz settings if we have an external
245 * 32KHz crystal present */
246 if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
247 AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
248 enable) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300249
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200250 /* 1 usec/cycle */
251 AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
252 /* Set up tsf increment on each cycle */
253 AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300254
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200255 /* Set baseband sleep control registers
256 * and sleep control rate */
257 ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300258
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200259 if ((ah->ah_radio == AR5K_RF5112) ||
260 (ah->ah_radio == AR5K_RF5413) ||
Felix Fietkau4cebb342010-12-02 10:27:21 +0100261 (ah->ah_radio == AR5K_RF2316) ||
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200262 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
263 spending = 0x14;
264 else
265 spending = 0x18;
266 ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300267
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200268 if ((ah->ah_radio == AR5K_RF5112) ||
269 (ah->ah_radio == AR5K_RF5413) ||
270 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
271 ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
272 ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
273 ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
274 ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
275 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
276 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
277 } else {
278 ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
279 ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
280 ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
281 ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
282 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
283 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
284 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300285
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200286 /* Enable sleep clock operation */
287 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
288 AR5K_PCICFG_SLEEP_CLOCK_EN);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300289
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200290 } else {
291
292 /* Disable sleep clock operation and
293 * restore default parameters */
294 AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
295 AR5K_PCICFG_SLEEP_CLOCK_EN);
296
297 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
298 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
299
Nick Kossifidisc2975602010-11-23 21:00:37 +0200300 /* Set DAC/ADC delays */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200301 ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
302 ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
303
304 if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
305 scal = AR5K_PHY_SCAL_32MHZ_2417;
306 else if (ee->ee_is_hb63)
307 scal = AR5K_PHY_SCAL_32MHZ_HB63;
308 else
309 scal = AR5K_PHY_SCAL_32MHZ;
310 ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
311
312 ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
313 ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
314
315 if ((ah->ah_radio == AR5K_RF5112) ||
316 (ah->ah_radio == AR5K_RF5413) ||
Felix Fietkau4cebb342010-12-02 10:27:21 +0100317 (ah->ah_radio == AR5K_RF2316) ||
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200318 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
319 spending = 0x14;
320 else
321 spending = 0x18;
322 ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
323
Nick Kossifidisc2975602010-11-23 21:00:37 +0200324 /* Set up tsf increment on each cycle */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200325 AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
Felix Fietkauf0064382011-07-12 09:02:03 +0800326
327 if ((ah->ah_radio == AR5K_RF5112) ||
328 (ah->ah_radio == AR5K_RF5413) ||
329 (ah->ah_radio == AR5K_RF2316) ||
330 (ah->ah_radio == AR5K_RF2317))
331 sclock = 40 - 1;
332 else
333 sclock = 32 - 1;
334 AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, sclock);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300335 }
336}
337
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200338
339/*********************\
340* Reset/Sleep control *
341\*********************/
342
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300343/*
344 * Reset chipset
345 */
346static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
347{
348 int ret;
349 u32 mask = val ? val : ~0U;
350
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300351 /* Read-and-clear RX Descriptor Pointer*/
352 ath5k_hw_reg_read(ah, AR5K_RXDP);
353
354 /*
355 * Reset the device and wait until success
356 */
357 ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
358
359 /* Wait at least 128 PCI clocks */
Nick Kossifidis1846ac32011-11-25 20:40:24 +0200360 usleep_range(15, 20);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300361
362 if (ah->ah_version == AR5K_AR5210) {
Nick Kossifidis84e463f2008-09-17 03:33:19 +0300363 val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
364 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
365 mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
366 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300367 } else {
368 val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
369 mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
370 }
371
372 ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false);
373
374 /*
375 * Reset configuration register (for hw byte-swap). Note that this
376 * is only set for big endian. We do the necessary magic in
377 * AR5K_INIT_CFG.
378 */
379 if ((val & AR5K_RESET_CTL_PCU) == 0)
380 ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
381
382 return ret;
383}
384
385/*
Felix Fietkau4cebb342010-12-02 10:27:21 +0100386 * Reset AHB chipset
387 * AR5K_RESET_CTL_PCU flag resets WMAC
388 * AR5K_RESET_CTL_BASEBAND flag resets WBB
389 */
390static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
391{
392 u32 mask = flags ? flags : ~0U;
Pavel Roskin2753f872011-07-07 18:13:55 -0400393 u32 __iomem *reg;
Felix Fietkau4cebb342010-12-02 10:27:21 +0100394 u32 regval;
395 u32 val = 0;
396
397 /* ah->ah_mac_srev is not available at this point yet */
Pavel Roskine0d687b2011-07-14 20:21:55 -0400398 if (ah->devid >= AR5K_SREV_AR2315_R6) {
Pavel Roskind816ab22011-06-15 18:03:28 -0400399 reg = (u32 __iomem *) AR5K_AR2315_RESET;
Felix Fietkau4cebb342010-12-02 10:27:21 +0100400 if (mask & AR5K_RESET_CTL_PCU)
401 val |= AR5K_AR2315_RESET_WMAC;
402 if (mask & AR5K_RESET_CTL_BASEBAND)
403 val |= AR5K_AR2315_RESET_BB_WARM;
404 } else {
Pavel Roskind816ab22011-06-15 18:03:28 -0400405 reg = (u32 __iomem *) AR5K_AR5312_RESET;
Pavel Roskine0d687b2011-07-14 20:21:55 -0400406 if (to_platform_device(ah->dev)->id == 0) {
Felix Fietkau4cebb342010-12-02 10:27:21 +0100407 if (mask & AR5K_RESET_CTL_PCU)
408 val |= AR5K_AR5312_RESET_WMAC0;
409 if (mask & AR5K_RESET_CTL_BASEBAND)
410 val |= AR5K_AR5312_RESET_BB0_COLD |
411 AR5K_AR5312_RESET_BB0_WARM;
412 } else {
413 if (mask & AR5K_RESET_CTL_PCU)
414 val |= AR5K_AR5312_RESET_WMAC1;
415 if (mask & AR5K_RESET_CTL_BASEBAND)
416 val |= AR5K_AR5312_RESET_BB1_COLD |
417 AR5K_AR5312_RESET_BB1_WARM;
418 }
419 }
420
421 /* Put BB/MAC into reset */
422 regval = __raw_readl(reg);
423 __raw_writel(regval | val, reg);
424 regval = __raw_readl(reg);
Nick Kossifidis1846ac32011-11-25 20:40:24 +0200425 usleep_range(100, 150);
Felix Fietkau4cebb342010-12-02 10:27:21 +0100426
427 /* Bring BB/MAC out of reset */
428 __raw_writel(regval & ~val, reg);
429 regval = __raw_readl(reg);
430
431 /*
432 * Reset configuration register (for hw byte-swap). Note that this
433 * is only set for big endian. We do the necessary magic in
434 * AR5K_INIT_CFG.
435 */
436 if ((flags & AR5K_RESET_CTL_PCU) == 0)
437 ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
438
439 return 0;
440}
441
442
443/*
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300444 * Sleep control
445 */
Pavel Roskin626ede62010-02-18 20:28:02 -0500446static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
447 bool set_chip, u16 sleep_duration)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300448{
449 unsigned int i;
450 u32 staid, data;
451
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300452 staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
453
454 switch (mode) {
455 case AR5K_PM_AUTO:
456 staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
457 /* fallthrough */
458 case AR5K_PM_NETWORK_SLEEP:
459 if (set_chip)
460 ath5k_hw_reg_write(ah,
461 AR5K_SLEEP_CTL_SLE_ALLOW |
462 sleep_duration,
463 AR5K_SLEEP_CTL);
464
465 staid |= AR5K_STA_ID1_PWR_SV;
466 break;
467
468 case AR5K_PM_FULL_SLEEP:
469 if (set_chip)
470 ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
471 AR5K_SLEEP_CTL);
472
473 staid |= AR5K_STA_ID1_PWR_SV;
474 break;
475
476 case AR5K_PM_AWAKE:
477
478 staid &= ~AR5K_STA_ID1_PWR_SV;
479
480 if (!set_chip)
481 goto commit;
482
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300483 data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300484
485 /* If card is down we 'll get 0xffff... so we
486 * need to clean this up before we write the register
487 */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300488 if (data & 0xffc00000)
489 data = 0;
490 else
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300491 /* Preserve sleep duration etc */
492 data = data & ~AR5K_SLEEP_CTL_SLE;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300493
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300494 ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
495 AR5K_SLEEP_CTL);
Nick Kossifidis1846ac32011-11-25 20:40:24 +0200496 usleep_range(15, 20);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300497
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300498 for (i = 200; i > 0; i--) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300499 /* Check if the chip did wake up */
500 if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
501 AR5K_PCICFG_SPWR_DN) == 0)
502 break;
503
504 /* Wait a bit and retry */
Nick Kossifidis1846ac32011-11-25 20:40:24 +0200505 usleep_range(50, 75);
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300506 ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
507 AR5K_SLEEP_CTL);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300508 }
509
510 /* Fail if the chip didn't wake up */
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300511 if (i == 0)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300512 return -EIO;
513
514 break;
515
516 default:
517 return -EINVAL;
518 }
519
520commit:
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300521 ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
522
523 return 0;
524}
525
526/*
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300527 * Put device on hold
528 *
529 * Put MAC and Baseband on warm reset and
530 * keep that state (don't clean sleep control
531 * register). After this MAC and Baseband are
532 * disabled and a full reset is needed to come
533 * back. This way we save as much power as possible
Bob Copeland8801df82010-08-21 16:39:02 -0400534 * without putting the card on full sleep.
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300535 */
536int ath5k_hw_on_hold(struct ath5k_hw *ah)
537{
Pavel Roskine0d687b2011-07-14 20:21:55 -0400538 struct pci_dev *pdev = ah->pdev;
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300539 u32 bus_flags;
540 int ret;
541
Felix Fietkau4cebb342010-12-02 10:27:21 +0100542 if (ath5k_get_bus_type(ah) == ATH_AHB)
543 return 0;
544
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300545 /* Make sure device is awake */
546 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
547 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400548 ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300549 return ret;
550 }
551
552 /*
553 * Put chipset on warm reset...
554 *
Bob Copeland8801df82010-08-21 16:39:02 -0400555 * Note: putting PCI core on warm reset on PCI-E cards
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300556 * results card to hang and always return 0xffff... so
Pavel Roskin6a2a0e72011-07-09 00:17:51 -0400557 * we ignore that flag for PCI-E cards. On PCI cards
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300558 * this flag gets cleared after 64 PCI clocks.
559 */
Hauke Mehrtense98b06b2010-12-21 02:01:54 +0100560 bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300561
562 if (ah->ah_version == AR5K_AR5210) {
563 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
564 AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
565 AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
Nick Kossifidis1846ac32011-11-25 20:40:24 +0200566 usleep_range(2000, 2500);
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300567 } else {
568 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
569 AR5K_RESET_CTL_BASEBAND | bus_flags);
570 }
571
572 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400573 ATH5K_ERR(ah, "failed to put device on warm reset\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300574 return -EIO;
575 }
576
577 /* ...wakeup again!*/
578 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
579 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400580 ATH5K_ERR(ah, "failed to put device on hold\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300581 return ret;
582 }
583
584 return ret;
585}
586
587/*
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200588 * Bring up MAC + PHY Chips and program PLL
Pavel Roskin32c25462011-07-23 09:29:09 -0400589 * Channel is NULL for the initial wakeup.
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300590 */
Pavel Roskin32c25462011-07-23 09:29:09 -0400591int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300592{
Pavel Roskine0d687b2011-07-14 20:21:55 -0400593 struct pci_dev *pdev = ah->pdev;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300594 u32 turbo, mode, clock, bus_flags;
595 int ret;
596
597 turbo = 0;
598 mode = 0;
599 clock = 0;
600
Pavel Roskin32c25462011-07-23 09:29:09 -0400601 if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) {
Felix Fietkau4cebb342010-12-02 10:27:21 +0100602 /* Wakeup the device */
603 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
604 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400605 ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
Felix Fietkau4cebb342010-12-02 10:27:21 +0100606 return ret;
607 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300608 }
609
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300610 /*
611 * Put chipset on warm reset...
612 *
Bob Copeland8801df82010-08-21 16:39:02 -0400613 * Note: putting PCI core on warm reset on PCI-E cards
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300614 * results card to hang and always return 0xffff... so
Pavel Roskin6a2a0e72011-07-09 00:17:51 -0400615 * we ignore that flag for PCI-E cards. On PCI cards
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300616 * this flag gets cleared after 64 PCI clocks.
617 */
Hauke Mehrtense98b06b2010-12-21 02:01:54 +0100618 bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300619
620 if (ah->ah_version == AR5K_AR5210) {
621 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
622 AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
623 AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
Nick Kossifidis1846ac32011-11-25 20:40:24 +0200624 usleep_range(2000, 2500);
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300625 } else {
Felix Fietkau4cebb342010-12-02 10:27:21 +0100626 if (ath5k_get_bus_type(ah) == ATH_AHB)
627 ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU |
628 AR5K_RESET_CTL_BASEBAND);
629 else
630 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
631 AR5K_RESET_CTL_BASEBAND | bus_flags);
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300632 }
633
634 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400635 ATH5K_ERR(ah, "failed to reset the MAC Chip\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300636 return -EIO;
637 }
638
639 /* ...wakeup again!...*/
640 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
641 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400642 ATH5K_ERR(ah, "failed to resume the MAC Chip\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300643 return ret;
644 }
645
Pavel Roskin6a2a0e72011-07-09 00:17:51 -0400646 /* ...reset configuration register on Wisoc ...
Felix Fietkau4cebb342010-12-02 10:27:21 +0100647 * ...clear reset control register and pull device out of
648 * warm reset on others */
649 if (ath5k_get_bus_type(ah) == ATH_AHB)
650 ret = ath5k_hw_wisoc_reset(ah, 0);
651 else
652 ret = ath5k_hw_nic_reset(ah, 0);
653
654 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400655 ATH5K_ERR(ah, "failed to warm reset the MAC Chip\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300656 return -EIO;
657 }
658
659 /* On initialization skip PLL programming since we don't have
660 * a channel / mode set yet */
Pavel Roskin32c25462011-07-23 09:29:09 -0400661 if (!channel)
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300662 return 0;
663
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300664 if (ah->ah_version != AR5K_AR5210) {
665 /*
666 * Get channel mode flags
667 */
668
669 if (ah->ah_radio >= AR5K_RF5112) {
670 mode = AR5K_PHY_MODE_RAD_RF5112;
671 clock = AR5K_PHY_PLL_RF5112;
672 } else {
673 mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/
674 clock = AR5K_PHY_PLL_RF5111; /*Zero*/
675 }
676
Pavel Roskin32c25462011-07-23 09:29:09 -0400677 if (channel->band == IEEE80211_BAND_2GHZ) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300678 mode |= AR5K_PHY_MODE_FREQ_2GHZ;
679 clock |= AR5K_PHY_PLL_44MHZ;
680
Pavel Roskin32c25462011-07-23 09:29:09 -0400681 if (channel->hw_value == AR5K_MODE_11B) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300682 mode |= AR5K_PHY_MODE_MOD_CCK;
Pavel Roskin32c25462011-07-23 09:29:09 -0400683 } else {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300684 /* XXX Dynamic OFDM/CCK is not supported by the
685 * AR5211 so we set MOD_OFDM for plain g (no
686 * CCK headers) operation. We need to test
687 * this, 5211 might support ofdm-only g after
688 * all, there are also initial register values
Nick Kossifidisf08fbf62010-11-23 21:33:22 +0200689 * in the code for g mode (see initvals.c).
690 */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300691 if (ah->ah_version == AR5K_AR5211)
692 mode |= AR5K_PHY_MODE_MOD_OFDM;
693 else
694 mode |= AR5K_PHY_MODE_MOD_DYN;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300695 }
Pavel Roskin32c25462011-07-23 09:29:09 -0400696 } else if (channel->band == IEEE80211_BAND_5GHZ) {
697 mode |= (AR5K_PHY_MODE_FREQ_5GHZ |
698 AR5K_PHY_MODE_MOD_OFDM);
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200699
Nick Kossifidisf08fbf62010-11-23 21:33:22 +0200700 /* Different PLL setting for 5413 */
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200701 if (ah->ah_radio == AR5K_RF5413)
Pavel Roskin807e3732009-03-27 17:47:27 -0400702 clock = AR5K_PHY_PLL_40MHZ_5413;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200703 else
704 clock |= AR5K_PHY_PLL_40MHZ;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300705 } else {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400706 ATH5K_ERR(ah, "invalid radio frequency mode\n");
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300707 return -EINVAL;
708 }
709
Nick Kossifidisf08fbf62010-11-23 21:33:22 +0200710 /*XXX: Can bwmode be used with dynamic mode ?
711 * (I don't think it supports 44MHz) */
Pavel Roskin6a2a0e72011-07-09 00:17:51 -0400712 /* On 2425 initvals TURBO_SHORT is not present */
Nick Kossifidisf08fbf62010-11-23 21:33:22 +0200713 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
714 turbo = AR5K_PHY_TURBO_MODE |
715 (ah->ah_radio == AR5K_RF2425) ? 0 :
716 AR5K_PHY_TURBO_SHORT;
717 } else if (ah->ah_bwmode != AR5K_BWMODE_DEFAULT) {
718 if (ah->ah_radio == AR5K_RF5413) {
719 mode |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ?
720 AR5K_PHY_MODE_HALF_RATE :
721 AR5K_PHY_MODE_QUARTER_RATE;
722 } else if (ah->ah_version == AR5K_AR5212) {
723 clock |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ?
724 AR5K_PHY_PLL_HALF_RATE :
725 AR5K_PHY_PLL_QUARTER_RATE;
726 }
727 }
728
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300729 } else { /* Reset the device */
730
731 /* ...enable Atheros turbo mode if requested */
Nick Kossifidisf08fbf62010-11-23 21:33:22 +0200732 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300733 ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
734 AR5K_PHY_TURBO);
735 }
736
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300737 if (ah->ah_version != AR5K_AR5210) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300738
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200739 /* ...update PLL if needed */
740 if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) {
741 ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
Nick Kossifidis1846ac32011-11-25 20:40:24 +0200742 usleep_range(300, 350);
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200743 }
744
745 /* ...set the PHY operating mode */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300746 ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
747 ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
748 }
749
750 return 0;
751}
752
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200753
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200754/**************************************\
755* Post-initvals register modifications *
756\**************************************/
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200757
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200758/* TODO: Half/Quarter rate */
759static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
760 struct ieee80211_channel *channel)
761{
762 if (ah->ah_version == AR5K_AR5212 &&
763 ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
764
765 /* Setup ADC control */
766 ath5k_hw_reg_write(ah,
767 (AR5K_REG_SM(2,
768 AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) |
769 AR5K_REG_SM(2,
770 AR5K_PHY_ADC_CTL_INBUFGAIN_ON) |
771 AR5K_PHY_ADC_CTL_PWD_DAC_OFF |
772 AR5K_PHY_ADC_CTL_PWD_ADC_OFF),
773 AR5K_PHY_ADC_CTL);
774
775
776
777 /* Disable barker RSSI threshold */
778 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
779 AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR);
780
781 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
782 AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2);
783
784 /* Set the mute mask */
785 ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
786 }
787
788 /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */
789 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B)
790 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH);
791
792 /* Enable DCU double buffering */
793 if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B)
794 AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
795 AR5K_TXCFG_DCU_DBL_BUF_DIS);
796
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200797 /* Set fast ADC */
798 if ((ah->ah_radio == AR5K_RF5413) ||
Felix Fietkau4cebb342010-12-02 10:27:21 +0100799 (ah->ah_radio == AR5K_RF2317) ||
800 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200801 u32 fast_adc = true;
802
803 if (channel->center_freq == 2462 ||
804 channel->center_freq == 2467)
805 fast_adc = 0;
806
807 /* Only update if needed */
808 if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc)
809 ath5k_hw_reg_write(ah, fast_adc,
810 AR5K_PHY_FAST_ADC);
811 }
812
813 /* Fix for first revision of the RF5112 RF chipset */
814 if (ah->ah_radio == AR5K_RF5112 &&
815 ah->ah_radio_5ghz_revision <
816 AR5K_SREV_RAD_5112A) {
817 u32 data;
818 ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
819 AR5K_PHY_CCKTXCTL);
Pavel Roskin32c25462011-07-23 09:29:09 -0400820 if (channel->band == IEEE80211_BAND_5GHZ)
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200821 data = 0xffb81020;
822 else
823 data = 0xffb80d20;
824 ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
825 }
826
Nick Kossifidis325089a2010-11-23 21:02:20 +0200827 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200828 /* Clear QCU/DCU clock gating register */
829 ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
830 /* Set DAC/ADC delays */
Nick Kossifidis325089a2010-11-23 21:02:20 +0200831 ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ_5311,
832 AR5K_PHY_SCAL);
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200833 /* Enable PCU FIFO corruption ECO */
834 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
835 AR5K_DIAG_SW_ECO_ENABLE);
836 }
Nick Kossifidisb4050862010-11-23 21:04:43 +0200837
838 if (ah->ah_bwmode) {
839 /* Increase PHY switch and AGC settling time
840 * on turbo mode (ath5k_hw_commit_eeprom_settings
841 * will override settling time if available) */
842 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
843
844 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
845 AR5K_PHY_SETTLING_AGC,
846 AR5K_AGC_SETTLING_TURBO);
847
848 /* XXX: Initvals indicate we only increase
849 * switch time on AR5212, 5211 and 5210
850 * only change agc time (bug?) */
851 if (ah->ah_version == AR5K_AR5212)
852 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
853 AR5K_PHY_SETTLING_SWITCH,
854 AR5K_SWITCH_SETTLING_TURBO);
855
856 if (ah->ah_version == AR5K_AR5210) {
857 /* Set Frame Control Register */
858 ath5k_hw_reg_write(ah,
859 (AR5K_PHY_FRAME_CTL_INI |
860 AR5K_PHY_TURBO_MODE |
861 AR5K_PHY_TURBO_SHORT | 0x2020),
862 AR5K_PHY_FRAME_CTL_5210);
863 }
864 /* On 5413 PHY force window length for half/quarter rate*/
865 } else if ((ah->ah_mac_srev >= AR5K_SREV_AR5424) &&
866 (ah->ah_mac_srev <= AR5K_SREV_AR5414)) {
867 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL_5211,
868 AR5K_PHY_FRAME_CTL_WIN_LEN,
869 3);
870 }
871 } else if (ah->ah_version == AR5K_AR5210) {
872 /* Set Frame Control Register for normal operation */
873 ath5k_hw_reg_write(ah, (AR5K_PHY_FRAME_CTL_INI | 0x1020),
874 AR5K_PHY_FRAME_CTL_5210);
875 }
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200876}
877
878static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
Bruno Randolf0207c0c2010-12-21 17:30:43 +0900879 struct ieee80211_channel *channel)
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200880{
881 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200882 s16 cck_ofdm_pwr_delta;
Bruno Randolf0207c0c2010-12-21 17:30:43 +0900883 u8 ee_mode;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200884
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200885 /* TODO: Add support for AR5210 EEPROM */
886 if (ah->ah_version == AR5K_AR5210)
887 return;
888
Bruno Randolf0207c0c2010-12-21 17:30:43 +0900889 ee_mode = ath5k_eeprom_mode_from_channel(channel);
890
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200891 /* Adjust power delta for channel 14 */
892 if (channel->center_freq == 2484)
893 cck_ofdm_pwr_delta =
894 ((ee->ee_cck_ofdm_power_delta -
895 ee->ee_scaled_cck_delta) * 2) / 10;
896 else
897 cck_ofdm_pwr_delta =
898 (ee->ee_cck_ofdm_power_delta * 2) / 10;
899
900 /* Set CCK to OFDM power delta on tx power
901 * adjustment register */
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200902 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
Pavel Roskin32c25462011-07-23 09:29:09 -0400903 if (channel->hw_value == AR5K_MODE_11G)
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200904 ath5k_hw_reg_write(ah,
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200905 AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200906 AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
907 AR5K_REG_SM((cck_ofdm_pwr_delta * -1),
908 AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
909 AR5K_PHY_TX_PWR_ADJ);
910 else
911 ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ);
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200912 } else {
913 /* For older revs we scale power on sw during tx power
914 * setup */
915 ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta;
916 ah->ah_txpower.txp_cck_ofdm_gainf_delta =
917 ee->ee_cck_ofdm_gain_delta;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200918 }
919
Bruno Randolf0ca74022010-06-07 13:11:30 +0900920 /* XXX: necessary here? is called from ath5k_hw_set_antenna_mode()
921 * too */
922 ath5k_hw_set_antenna_switch(ah, ee_mode);
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200923
924 /* Noise floor threshold */
925 ath5k_hw_reg_write(ah,
926 AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
927 AR5K_PHY_NFTHRES);
928
Nick Kossifidisacb091d2010-11-23 21:49:53 +0200929 if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) &&
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200930 (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
931 /* Switch settling time (Turbo) */
932 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
933 AR5K_PHY_SETTLING_SWITCH,
934 ee->ee_switch_settling_turbo[ee_mode]);
935
936 /* Tx/Rx attenuation (Turbo) */
937 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
938 AR5K_PHY_GAIN_TXRX_ATTEN,
939 ee->ee_atn_tx_rx_turbo[ee_mode]);
940
941 /* ADC/PGA desired size (Turbo) */
942 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
943 AR5K_PHY_DESIRED_SIZE_ADC,
944 ee->ee_adc_desired_size_turbo[ee_mode]);
945
946 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
947 AR5K_PHY_DESIRED_SIZE_PGA,
948 ee->ee_pga_desired_size_turbo[ee_mode]);
949
950 /* Tx/Rx margin (Turbo) */
951 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
952 AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
953 ee->ee_margin_tx_rx_turbo[ee_mode]);
954
955 } else {
956 /* Switch settling time */
957 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
958 AR5K_PHY_SETTLING_SWITCH,
959 ee->ee_switch_settling[ee_mode]);
960
961 /* Tx/Rx attenuation */
962 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
963 AR5K_PHY_GAIN_TXRX_ATTEN,
964 ee->ee_atn_tx_rx[ee_mode]);
965
966 /* ADC/PGA desired size */
967 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
968 AR5K_PHY_DESIRED_SIZE_ADC,
969 ee->ee_adc_desired_size[ee_mode]);
970
971 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
972 AR5K_PHY_DESIRED_SIZE_PGA,
973 ee->ee_pga_desired_size[ee_mode]);
974
975 /* Tx/Rx margin */
976 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
977 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
978 AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
979 ee->ee_margin_tx_rx[ee_mode]);
980 }
981
982 /* XPA delays */
983 ath5k_hw_reg_write(ah,
984 (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
985 (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
986 (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
987 (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
988
989 /* XLNA delay */
990 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3,
991 AR5K_PHY_RF_CTL3_TXE2XLNA_ON,
992 ee->ee_tx_end2xlna_enable[ee_mode]);
993
994 /* Thresh64 (ANI) */
995 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF,
996 AR5K_PHY_NF_THRESH62,
997 ee->ee_thr_62[ee_mode]);
998
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200999 /* False detect backoff for channels
1000 * that have spur noise. Write the new
1001 * cyclic power RSSI threshold. */
1002 if (ath5k_hw_chan_has_spur_noise(ah, channel))
1003 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
1004 AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
1005 AR5K_INIT_CYCRSSI_THR1 +
1006 ee->ee_false_detect[ee_mode]);
1007 else
1008 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
1009 AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
1010 AR5K_INIT_CYCRSSI_THR1);
1011
Bruno Randolf5f13bfa2010-03-09 16:56:10 +09001012 /* I/Q correction (set enable bit last to match HAL sources) */
1013 /* TODO: Per channel i/q infos ? */
1014 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
1015 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF,
1016 ee->ee_i_cal[ee_mode]);
1017 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF,
1018 ee->ee_q_cal[ee_mode]);
1019 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE);
1020 }
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001021
1022 /* Heavy clipping -disable for now */
1023 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1)
1024 ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001025}
1026
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001027
1028/*********************\
1029* Main reset function *
1030\*********************/
1031
Johannes Berg05c914f2008-09-11 00:01:58 +02001032int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001033 struct ieee80211_channel *channel, bool fast, bool skip_pcu)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001034{
Nick Kossifidisc2b0ebe2010-11-23 21:42:22 +02001035 u32 s_seq[10], s_led[3], tsf_up, tsf_lo;
Bruno Randolf0207c0c2010-12-21 17:30:43 +09001036 u8 mode;
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001037 int i, ret;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001038
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001039 tsf_up = 0;
1040 tsf_lo = 0;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001041 mode = 0;
1042
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001043 /*
1044 * Sanity check for fast flag
1045 * Fast channel change only available
1046 * on AR2413/AR5413.
1047 */
1048 if (fast && (ah->ah_radio != AR5K_RF2413) &&
1049 (ah->ah_radio != AR5K_RF5413))
1050 fast = 0;
1051
1052 /* Disable sleep clock operation
1053 * to avoid register access delay on certain
1054 * PHY registers */
1055 if (ah->ah_version == AR5K_AR5212)
1056 ath5k_hw_set_sleep_clock(ah, false);
Nick Kossifidisc2975602010-11-23 21:00:37 +02001057
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001058 /*
Nick Kossifidise088f232010-11-23 20:43:18 +02001059 * Stop PCU
1060 */
1061 ath5k_hw_stop_rx_pcu(ah);
1062
1063 /*
Nick Kossifidisd41174f2010-11-23 20:41:15 +02001064 * Stop DMA
1065 *
1066 * Note: If DMA didn't stop continue
1067 * since only a reset will fix it.
1068 */
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001069 ret = ath5k_hw_dma_stop(ah);
1070
1071 /* RF Bus grant won't work if we have pending
1072 * frames */
1073 if (ret && fast) {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001074 ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001075 "DMA didn't stop, falling back to normal reset\n");
1076 fast = 0;
1077 /* Non fatal, just continue with
1078 * normal reset */
1079 ret = 0;
1080 }
1081
Pavel Roskin32c25462011-07-23 09:29:09 -04001082 mode = channel->hw_value;
1083 switch (mode) {
1084 case AR5K_MODE_11A:
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001085 break;
Pavel Roskin32c25462011-07-23 09:29:09 -04001086 case AR5K_MODE_11G:
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001087 if (ah->ah_version <= AR5K_AR5211) {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001088 ATH5K_ERR(ah,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001089 "G mode not available on 5210/5211");
1090 return -EINVAL;
1091 }
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001092 break;
Pavel Roskin32c25462011-07-23 09:29:09 -04001093 case AR5K_MODE_11B:
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001094 if (ah->ah_version < AR5K_AR5211) {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001095 ATH5K_ERR(ah,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001096 "B mode not available on 5210");
1097 return -EINVAL;
1098 }
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001099 break;
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001100 default:
Pavel Roskine0d687b2011-07-14 20:21:55 -04001101 ATH5K_ERR(ah,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001102 "invalid channel: %d\n", channel->center_freq);
1103 return -EINVAL;
1104 }
1105
1106 /*
1107 * If driver requested fast channel change and DMA has stopped
1108 * go on. If it fails continue with a normal reset.
1109 */
1110 if (fast) {
Bruno Randolf0207c0c2010-12-21 17:30:43 +09001111 ret = ath5k_hw_phy_init(ah, channel, mode, true);
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001112 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001113 ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001114 "fast chan change failed, falling back to normal reset\n");
1115 /* Non fatal, can happen eg.
1116 * on mode change */
1117 ret = 0;
Nick Kossifidisa99168e2011-06-02 03:09:48 +03001118 } else {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001119 ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
Nick Kossifidisa99168e2011-06-02 03:09:48 +03001120 "fast chan change successful\n");
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001121 return 0;
Nick Kossifidisa99168e2011-06-02 03:09:48 +03001122 }
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001123 }
Nick Kossifidisd41174f2010-11-23 20:41:15 +02001124
1125 /*
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001126 * Save some registers before a reset
1127 */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001128 if (ah->ah_version != AR5K_AR5210) {
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001129 /*
1130 * Save frame sequence count
1131 * For revs. after Oahu, only save
1132 * seq num for DCU 0 (Global seq num)
1133 */
1134 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001135
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001136 for (i = 0; i < 10; i++)
1137 s_seq[i] = ath5k_hw_reg_read(ah,
1138 AR5K_QUEUE_DCU_SEQNUM(i));
1139
1140 } else {
1141 s_seq[0] = ath5k_hw_reg_read(ah,
1142 AR5K_QUEUE_DCU_SEQNUM(0));
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001143 }
1144
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001145 /* TSF accelerates on AR5211 during reset
1146 * As a workaround save it here and restore
1147 * it later so that it's back in time after
1148 * reset. This way it'll get re-synced on the
1149 * next beacon without breaking ad-hoc.
1150 *
1151 * On AR5212 TSF is almost preserved across a
1152 * reset so it stays back in time anyway and
1153 * we don't have to save/restore it.
1154 *
1155 * XXX: Since this breaks power saving we have
1156 * to disable power saving until we receive the
1157 * next beacon, so we can resync beacon timers */
1158 if (ah->ah_version == AR5K_AR5211) {
1159 tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
1160 tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001161 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001162 }
1163
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001164
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001165 /*GPIOs*/
1166 s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
1167 AR5K_PCICFG_LEDSTATE;
1168 s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
1169 s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
Nick Kossifidisa406c132009-02-09 06:08:51 +02001170
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001171
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001172 /*
1173 * Since we are going to write rf buffer
1174 * check if we have any pending gain_F
1175 * optimization settings
1176 */
1177 if (ah->ah_version == AR5K_AR5212 &&
1178 (ah->ah_radio <= AR5K_RF5112)) {
1179 if (!fast && ah->ah_rf_banks != NULL)
1180 ath5k_hw_gainf_calibrate(ah);
1181 }
1182
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001183 /* Wakeup the device */
Pavel Roskin32c25462011-07-23 09:29:09 -04001184 ret = ath5k_hw_nic_wakeup(ah, channel);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001185 if (ret)
1186 return ret;
1187
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001188 /* PHY access enable */
1189 if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
1190 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
1191 else
1192 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40,
1193 AR5K_PHY(0));
1194
1195 /* Write initial settings */
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001196 ret = ath5k_hw_write_initvals(ah, mode, skip_pcu);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001197 if (ret)
1198 return ret;
1199
Nick Kossifidisc2975602010-11-23 21:00:37 +02001200 /* Initialize core clock settings */
1201 ath5k_hw_init_core_clock(ah);
1202
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001203 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001204 * Tweak initval settings for revised
1205 * chipsets and add some more config
1206 * bits
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001207 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001208 ath5k_hw_tweak_initval_settings(ah, channel);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001209
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001210 /* Commit values from EEPROM */
Bruno Randolf0207c0c2010-12-21 17:30:43 +09001211 ath5k_hw_commit_eeprom_settings(ah, channel);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001212
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001213
1214 /*
1215 * Restore saved values
1216 */
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001217
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001218 /* Seqnum, TSF */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001219 if (ah->ah_version != AR5K_AR5210) {
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001220 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
1221 for (i = 0; i < 10; i++)
1222 ath5k_hw_reg_write(ah, s_seq[i],
1223 AR5K_QUEUE_DCU_SEQNUM(i));
1224 } else {
1225 ath5k_hw_reg_write(ah, s_seq[0],
1226 AR5K_QUEUE_DCU_SEQNUM(0));
1227 }
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001228
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001229 if (ah->ah_version == AR5K_AR5211) {
1230 ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
1231 ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001232 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001233 }
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001234
1235 /* Ledstate */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001236 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001237
1238 /* Gpio settings */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001239 ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
1240 ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
1241
1242 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001243 * Initialize PCU
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001244 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001245 ath5k_hw_pcu_init(ah, op_mode, mode);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001246
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001247 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001248 * Initialize PHY
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001249 */
Bruno Randolf0207c0c2010-12-21 17:30:43 +09001250 ret = ath5k_hw_phy_init(ah, channel, mode, false);
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001251 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001252 ATH5K_ERR(ah,
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001253 "failed to initialize PHY (%i) !\n", ret);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001254 return ret;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001255 }
1256
1257 /*
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001258 * Configure QCUs/DCUs
1259 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001260 ret = ath5k_hw_init_queues(ah);
1261 if (ret)
1262 return ret;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001263
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001264
1265 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001266 * Initialize DMA/Interrupts
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001267 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001268 ath5k_hw_dma_init(ah);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001269
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001270
Felix Fietkau63402112011-07-12 09:02:04 +08001271 /*
1272 * Enable 32KHz clock function for AR5212+ chips
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001273 * Set clocks to 32KHz operation and use an
1274 * external 32KHz crystal when sleeping if one
Felix Fietkau63402112011-07-12 09:02:04 +08001275 * exists.
1276 * Disabled by default because it is also disabled in
1277 * other drivers and it is known to cause stability
1278 * issues on some devices
1279 */
1280 if (ah->ah_use_32khz_clock && ah->ah_version == AR5K_AR5212 &&
Bruno Randolfccfe5552010-03-09 16:55:38 +09001281 op_mode != NL80211_IFTYPE_AP)
Bob Copeland5d6ce622010-01-20 23:51:03 -05001282 ath5k_hw_set_sleep_clock(ah, true);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001283
1284 /*
Bruno Randolfa3b980f2010-03-09 16:55:33 +09001285 * Disable beacons and reset the TSF
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001286 */
Bruno Randolfa3b980f2010-03-09 16:55:33 +09001287 AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
1288 ath5k_hw_reset_tsf(ah);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001289 return 0;
1290}