blob: 8bc57e4576155b377ecf7ec2e4c1f26701b1964e [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"
33#include "base.h"
34#include "debug.h"
35
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020036
37/******************\
38* Helper functions *
39\******************/
40
Pavel Roskinec182d92010-02-18 20:28:41 -050041/*
42 * Check if a register write has been completed
43 */
44int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
45 bool is_set)
46{
47 int i;
48 u32 data;
49
50 for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
51 data = ath5k_hw_reg_read(ah, reg);
52 if (is_set && (data & flag))
53 break;
54 else if ((data & flag) == val)
55 break;
56 udelay(15);
57 }
58
59 return (i <= 0) ? -EAGAIN : 0;
60}
61
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020062
63/*************************\
64* Clock related functions *
65\*************************/
66
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030067/**
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020068 * ath5k_hw_htoclock - Translate usec to hw clock units
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030069 *
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020070 * @ah: The &struct ath5k_hw
71 * @usec: value in microseconds
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030072 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020073unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030074{
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020075 struct ath_common *common = ath5k_hw_common(ah);
76 return usec * common->clockrate;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030077}
78
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020079/**
80 * ath5k_hw_clocktoh - Translate hw clock units to usec
81 * @clock: value in hw clock units
82 */
83unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
84{
85 struct ath_common *common = ath5k_hw_common(ah);
86 return clock / common->clockrate;
87}
88
89/**
Nick Kossifidisc2975602010-11-23 21:00:37 +020090 * ath5k_hw_init_core_clock - Initialize core clock
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020091 *
Nick Kossifidisc2975602010-11-23 21:00:37 +020092 * @ah The &struct ath5k_hw
93 *
94 * Initialize core clock parameters (usec, usec32, latencies etc).
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020095 */
Nick Kossifidisc2975602010-11-23 21:00:37 +020096static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020097{
98 struct ieee80211_channel *channel = ah->ah_current_channel;
99 struct ath_common *common = ath5k_hw_common(ah);
Nick Kossifidisc2975602010-11-23 21:00:37 +0200100 u32 usec_reg, txlat, rxlat, usec, clock, sclock, txf2txs;
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200101
Nick Kossifidisc2975602010-11-23 21:00:37 +0200102 /*
103 * Set core clock frequency
104 */
Pavel Roskin32c25462011-07-23 09:29:09 -0400105 switch (channel->hw_value) {
106 case AR5K_MODE_11A:
107 clock = 40;
108 break;
109 case AR5K_MODE_11B:
110 clock = 22;
111 break;
112 case AR5K_MODE_11G:
113 default:
114 clock = 44;
115 break;
116 }
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200117
Nick Kossifidisc2975602010-11-23 21:00:37 +0200118 /* Use clock multiplier for non-default
119 * bwmode */
120 switch (ah->ah_bwmode) {
121 case AR5K_BWMODE_40MHZ:
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200122 clock *= 2;
Nick Kossifidisc2975602010-11-23 21:00:37 +0200123 break;
124 case AR5K_BWMODE_10MHZ:
125 clock /= 2;
126 break;
127 case AR5K_BWMODE_5MHZ:
128 clock /= 4;
129 break;
130 default:
131 break;
132 }
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200133
134 common->clockrate = clock;
Nick Kossifidisc2975602010-11-23 21:00:37 +0200135
136 /*
137 * Set USEC parameters
138 */
139 /* Set USEC counter on PCU*/
140 usec = clock - 1;
141 usec = AR5K_REG_SM(usec, AR5K_USEC_1);
142
143 /* Set usec duration on DCU */
144 if (ah->ah_version != AR5K_AR5210)
145 AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
146 AR5K_DCU_GBL_IFS_MISC_USEC_DUR,
147 clock);
148
149 /* Set 32MHz USEC counter */
150 if ((ah->ah_radio == AR5K_RF5112) ||
Felix Fietkauf0064382011-07-12 09:02:03 +0800151 (ah->ah_radio == AR5K_RF2413) ||
Pavel Roskine4bbf2f2011-07-07 18:14:13 -0400152 (ah->ah_radio == AR5K_RF5413) ||
153 (ah->ah_radio == AR5K_RF2316) ||
154 (ah->ah_radio == AR5K_RF2317))
155 /* Remain on 40MHz clock ? */
Nick Kossifidisc2975602010-11-23 21:00:37 +0200156 sclock = 40 - 1;
157 else
158 sclock = 32 - 1;
159 sclock = AR5K_REG_SM(sclock, AR5K_USEC_32);
160
161 /*
162 * Set tx/rx latencies
163 */
164 usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
165 txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211);
166 rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211);
167
168 /*
John W. Linvillee2452922011-04-29 14:35:14 -0400169 * Set default Tx frame to Tx data start delay
170 */
171 txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT;
172
173 /*
Nick Kossifidisc2975602010-11-23 21:00:37 +0200174 * 5210 initvals don't include usec settings
175 * so we need to use magic values here for
176 * tx/rx latencies
177 */
178 if (ah->ah_version == AR5K_AR5210) {
179 /* same for turbo */
180 txlat = AR5K_INIT_TX_LATENCY_5210;
181 rxlat = AR5K_INIT_RX_LATENCY_5210;
182 }
183
184 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
185 /* 5311 has different tx/rx latency masks
186 * from 5211, since we deal 5311 the same
187 * as 5211 when setting initvals, shift
188 * values here to their proper locations
189 *
190 * Note: Initvals indicate tx/rx/ latencies
191 * are the same for turbo mode */
192 txlat = AR5K_REG_SM(txlat, AR5K_USEC_TX_LATENCY_5210);
193 rxlat = AR5K_REG_SM(rxlat, AR5K_USEC_RX_LATENCY_5210);
194 } else
195 switch (ah->ah_bwmode) {
196 case AR5K_BWMODE_10MHZ:
197 txlat = AR5K_REG_SM(txlat * 2,
198 AR5K_USEC_TX_LATENCY_5211);
199 rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX,
200 AR5K_USEC_RX_LATENCY_5211);
201 txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_10MHZ;
202 break;
203 case AR5K_BWMODE_5MHZ:
204 txlat = AR5K_REG_SM(txlat * 4,
205 AR5K_USEC_TX_LATENCY_5211);
206 rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX,
207 AR5K_USEC_RX_LATENCY_5211);
208 txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_5MHZ;
209 break;
210 case AR5K_BWMODE_40MHZ:
211 txlat = AR5K_INIT_TX_LAT_MIN;
212 rxlat = AR5K_REG_SM(rxlat / 2,
213 AR5K_USEC_RX_LATENCY_5211);
214 txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT;
215 break;
216 default:
217 break;
218 }
219
220 usec_reg = (usec | sclock | txlat | rxlat);
221 ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC);
222
Pavel Roskin6a2a0e72011-07-09 00:17:51 -0400223 /* On 5112 set tx frame to tx data start delay */
Nick Kossifidisc2975602010-11-23 21:00:37 +0200224 if (ah->ah_radio == AR5K_RF5112) {
225 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2,
226 AR5K_PHY_RF_CTL2_TXF2TXD_START,
227 txf2txs);
228 }
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200229}
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300230
231/*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200232 * If there is an external 32KHz crystal available, use it
233 * as ref. clock instead of 32/40MHz clock and baseband clocks
234 * to save power during sleep or restore normal 32/40MHz
235 * operation.
236 *
237 * XXX: When operating on 32KHz certain PHY registers (27 - 31,
238 * 123 - 127) require delay on access.
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300239 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200240static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300241{
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200242 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
Felix Fietkauf0064382011-07-12 09:02:03 +0800243 u32 scal, spending, sclock;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300244
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200245 /* Only set 32KHz settings if we have an external
246 * 32KHz crystal present */
247 if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
248 AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
249 enable) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300250
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200251 /* 1 usec/cycle */
252 AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
253 /* Set up tsf increment on each cycle */
254 AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300255
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200256 /* Set baseband sleep control registers
257 * and sleep control rate */
258 ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300259
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200260 if ((ah->ah_radio == AR5K_RF5112) ||
261 (ah->ah_radio == AR5K_RF5413) ||
Felix Fietkau4cebb342010-12-02 10:27:21 +0100262 (ah->ah_radio == AR5K_RF2316) ||
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200263 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
264 spending = 0x14;
265 else
266 spending = 0x18;
267 ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300268
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200269 if ((ah->ah_radio == AR5K_RF5112) ||
270 (ah->ah_radio == AR5K_RF5413) ||
271 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
272 ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
273 ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
274 ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
275 ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
276 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
277 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
278 } else {
279 ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
280 ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
281 ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
282 ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
283 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
284 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
285 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300286
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200287 /* Enable sleep clock operation */
288 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
289 AR5K_PCICFG_SLEEP_CLOCK_EN);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300290
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200291 } else {
292
293 /* Disable sleep clock operation and
294 * restore default parameters */
295 AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
296 AR5K_PCICFG_SLEEP_CLOCK_EN);
297
298 AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
299 AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
300
Nick Kossifidisc2975602010-11-23 21:00:37 +0200301 /* Set DAC/ADC delays */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200302 ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
303 ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
304
305 if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
306 scal = AR5K_PHY_SCAL_32MHZ_2417;
307 else if (ee->ee_is_hb63)
308 scal = AR5K_PHY_SCAL_32MHZ_HB63;
309 else
310 scal = AR5K_PHY_SCAL_32MHZ;
311 ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
312
313 ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
314 ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
315
316 if ((ah->ah_radio == AR5K_RF5112) ||
317 (ah->ah_radio == AR5K_RF5413) ||
Felix Fietkau4cebb342010-12-02 10:27:21 +0100318 (ah->ah_radio == AR5K_RF2316) ||
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200319 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
320 spending = 0x14;
321 else
322 spending = 0x18;
323 ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
324
Nick Kossifidisc2975602010-11-23 21:00:37 +0200325 /* Set up tsf increment on each cycle */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200326 AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
Felix Fietkauf0064382011-07-12 09:02:03 +0800327
328 if ((ah->ah_radio == AR5K_RF5112) ||
329 (ah->ah_radio == AR5K_RF5413) ||
330 (ah->ah_radio == AR5K_RF2316) ||
331 (ah->ah_radio == AR5K_RF2317))
332 sclock = 40 - 1;
333 else
334 sclock = 32 - 1;
335 AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, sclock);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300336 }
337}
338
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200339
340/*********************\
341* Reset/Sleep control *
342\*********************/
343
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300344/*
345 * Reset chipset
346 */
347static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
348{
349 int ret;
350 u32 mask = val ? val : ~0U;
351
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300352 /* Read-and-clear RX Descriptor Pointer*/
353 ath5k_hw_reg_read(ah, AR5K_RXDP);
354
355 /*
356 * Reset the device and wait until success
357 */
358 ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
359
360 /* Wait at least 128 PCI clocks */
361 udelay(15);
362
363 if (ah->ah_version == AR5K_AR5210) {
Nick Kossifidis84e463f2008-09-17 03:33:19 +0300364 val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
365 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
366 mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA
367 | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300368 } else {
369 val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
370 mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
371 }
372
373 ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false);
374
375 /*
376 * Reset configuration register (for hw byte-swap). Note that this
377 * is only set for big endian. We do the necessary magic in
378 * AR5K_INIT_CFG.
379 */
380 if ((val & AR5K_RESET_CTL_PCU) == 0)
381 ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
382
383 return ret;
384}
385
386/*
Felix Fietkau4cebb342010-12-02 10:27:21 +0100387 * Reset AHB chipset
388 * AR5K_RESET_CTL_PCU flag resets WMAC
389 * AR5K_RESET_CTL_BASEBAND flag resets WBB
390 */
391static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
392{
393 u32 mask = flags ? flags : ~0U;
Pavel Roskin2753f872011-07-07 18:13:55 -0400394 u32 __iomem *reg;
Felix Fietkau4cebb342010-12-02 10:27:21 +0100395 u32 regval;
396 u32 val = 0;
397
398 /* ah->ah_mac_srev is not available at this point yet */
Pavel Roskine0d687b2011-07-14 20:21:55 -0400399 if (ah->devid >= AR5K_SREV_AR2315_R6) {
Pavel Roskind816ab22011-06-15 18:03:28 -0400400 reg = (u32 __iomem *) AR5K_AR2315_RESET;
Felix Fietkau4cebb342010-12-02 10:27:21 +0100401 if (mask & AR5K_RESET_CTL_PCU)
402 val |= AR5K_AR2315_RESET_WMAC;
403 if (mask & AR5K_RESET_CTL_BASEBAND)
404 val |= AR5K_AR2315_RESET_BB_WARM;
405 } else {
Pavel Roskind816ab22011-06-15 18:03:28 -0400406 reg = (u32 __iomem *) AR5K_AR5312_RESET;
Pavel Roskine0d687b2011-07-14 20:21:55 -0400407 if (to_platform_device(ah->dev)->id == 0) {
Felix Fietkau4cebb342010-12-02 10:27:21 +0100408 if (mask & AR5K_RESET_CTL_PCU)
409 val |= AR5K_AR5312_RESET_WMAC0;
410 if (mask & AR5K_RESET_CTL_BASEBAND)
411 val |= AR5K_AR5312_RESET_BB0_COLD |
412 AR5K_AR5312_RESET_BB0_WARM;
413 } else {
414 if (mask & AR5K_RESET_CTL_PCU)
415 val |= AR5K_AR5312_RESET_WMAC1;
416 if (mask & AR5K_RESET_CTL_BASEBAND)
417 val |= AR5K_AR5312_RESET_BB1_COLD |
418 AR5K_AR5312_RESET_BB1_WARM;
419 }
420 }
421
422 /* Put BB/MAC into reset */
423 regval = __raw_readl(reg);
424 __raw_writel(regval | val, reg);
425 regval = __raw_readl(reg);
426 udelay(100);
427
428 /* Bring BB/MAC out of reset */
429 __raw_writel(regval & ~val, reg);
430 regval = __raw_readl(reg);
431
432 /*
433 * Reset configuration register (for hw byte-swap). Note that this
434 * is only set for big endian. We do the necessary magic in
435 * AR5K_INIT_CFG.
436 */
437 if ((flags & AR5K_RESET_CTL_PCU) == 0)
438 ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
439
440 return 0;
441}
442
443
444/*
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300445 * Sleep control
446 */
Pavel Roskin626ede62010-02-18 20:28:02 -0500447static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
448 bool set_chip, u16 sleep_duration)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300449{
450 unsigned int i;
451 u32 staid, data;
452
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300453 staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
454
455 switch (mode) {
456 case AR5K_PM_AUTO:
457 staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
458 /* fallthrough */
459 case AR5K_PM_NETWORK_SLEEP:
460 if (set_chip)
461 ath5k_hw_reg_write(ah,
462 AR5K_SLEEP_CTL_SLE_ALLOW |
463 sleep_duration,
464 AR5K_SLEEP_CTL);
465
466 staid |= AR5K_STA_ID1_PWR_SV;
467 break;
468
469 case AR5K_PM_FULL_SLEEP:
470 if (set_chip)
471 ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
472 AR5K_SLEEP_CTL);
473
474 staid |= AR5K_STA_ID1_PWR_SV;
475 break;
476
477 case AR5K_PM_AWAKE:
478
479 staid &= ~AR5K_STA_ID1_PWR_SV;
480
481 if (!set_chip)
482 goto commit;
483
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300484 data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300485
486 /* If card is down we 'll get 0xffff... so we
487 * need to clean this up before we write the register
488 */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300489 if (data & 0xffc00000)
490 data = 0;
491 else
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300492 /* Preserve sleep duration etc */
493 data = data & ~AR5K_SLEEP_CTL_SLE;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300494
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300495 ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
496 AR5K_SLEEP_CTL);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300497 udelay(15);
498
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300499 for (i = 200; i > 0; i--) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300500 /* Check if the chip did wake up */
501 if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
502 AR5K_PCICFG_SPWR_DN) == 0)
503 break;
504
505 /* Wait a bit and retry */
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300506 udelay(50);
507 ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
508 AR5K_SLEEP_CTL);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300509 }
510
511 /* Fail if the chip didn't wake up */
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300512 if (i == 0)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300513 return -EIO;
514
515 break;
516
517 default:
518 return -EINVAL;
519 }
520
521commit:
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300522 ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
523
524 return 0;
525}
526
527/*
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300528 * Put device on hold
529 *
530 * Put MAC and Baseband on warm reset and
531 * keep that state (don't clean sleep control
532 * register). After this MAC and Baseband are
533 * disabled and a full reset is needed to come
534 * back. This way we save as much power as possible
Bob Copeland8801df82010-08-21 16:39:02 -0400535 * without putting the card on full sleep.
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300536 */
537int ath5k_hw_on_hold(struct ath5k_hw *ah)
538{
Pavel Roskine0d687b2011-07-14 20:21:55 -0400539 struct pci_dev *pdev = ah->pdev;
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300540 u32 bus_flags;
541 int ret;
542
Felix Fietkau4cebb342010-12-02 10:27:21 +0100543 if (ath5k_get_bus_type(ah) == ATH_AHB)
544 return 0;
545
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300546 /* Make sure device is awake */
547 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
548 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400549 ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300550 return ret;
551 }
552
553 /*
554 * Put chipset on warm reset...
555 *
Bob Copeland8801df82010-08-21 16:39:02 -0400556 * Note: putting PCI core on warm reset on PCI-E cards
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300557 * results card to hang and always return 0xffff... so
Pavel Roskin6a2a0e72011-07-09 00:17:51 -0400558 * we ignore that flag for PCI-E cards. On PCI cards
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300559 * this flag gets cleared after 64 PCI clocks.
560 */
Hauke Mehrtense98b06b2010-12-21 02:01:54 +0100561 bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300562
563 if (ah->ah_version == AR5K_AR5210) {
564 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
565 AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
566 AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
567 mdelay(2);
568 } else {
569 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
570 AR5K_RESET_CTL_BASEBAND | bus_flags);
571 }
572
573 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400574 ATH5K_ERR(ah, "failed to put device on warm reset\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300575 return -EIO;
576 }
577
578 /* ...wakeup again!*/
579 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
580 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400581 ATH5K_ERR(ah, "failed to put device on hold\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300582 return ret;
583 }
584
585 return ret;
586}
587
588/*
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200589 * Bring up MAC + PHY Chips and program PLL
Pavel Roskin32c25462011-07-23 09:29:09 -0400590 * Channel is NULL for the initial wakeup.
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300591 */
Pavel Roskin32c25462011-07-23 09:29:09 -0400592int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300593{
Pavel Roskine0d687b2011-07-14 20:21:55 -0400594 struct pci_dev *pdev = ah->pdev;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300595 u32 turbo, mode, clock, bus_flags;
596 int ret;
597
598 turbo = 0;
599 mode = 0;
600 clock = 0;
601
Pavel Roskin32c25462011-07-23 09:29:09 -0400602 if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) {
Felix Fietkau4cebb342010-12-02 10:27:21 +0100603 /* Wakeup the device */
604 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
605 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400606 ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
Felix Fietkau4cebb342010-12-02 10:27:21 +0100607 return ret;
608 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300609 }
610
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300611 /*
612 * Put chipset on warm reset...
613 *
Bob Copeland8801df82010-08-21 16:39:02 -0400614 * Note: putting PCI core on warm reset on PCI-E cards
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300615 * results card to hang and always return 0xffff... so
Pavel Roskin6a2a0e72011-07-09 00:17:51 -0400616 * we ignore that flag for PCI-E cards. On PCI cards
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300617 * this flag gets cleared after 64 PCI clocks.
618 */
Hauke Mehrtense98b06b2010-12-21 02:01:54 +0100619 bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI;
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300620
621 if (ah->ah_version == AR5K_AR5210) {
622 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
623 AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
624 AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
625 mdelay(2);
626 } else {
Felix Fietkau4cebb342010-12-02 10:27:21 +0100627 if (ath5k_get_bus_type(ah) == ATH_AHB)
628 ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU |
629 AR5K_RESET_CTL_BASEBAND);
630 else
631 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
632 AR5K_RESET_CTL_BASEBAND | bus_flags);
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300633 }
634
635 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400636 ATH5K_ERR(ah, "failed to reset the MAC Chip\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300637 return -EIO;
638 }
639
640 /* ...wakeup again!...*/
641 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
642 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400643 ATH5K_ERR(ah, "failed to resume the MAC Chip\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300644 return ret;
645 }
646
Pavel Roskin6a2a0e72011-07-09 00:17:51 -0400647 /* ...reset configuration register on Wisoc ...
Felix Fietkau4cebb342010-12-02 10:27:21 +0100648 * ...clear reset control register and pull device out of
649 * warm reset on others */
650 if (ath5k_get_bus_type(ah) == ATH_AHB)
651 ret = ath5k_hw_wisoc_reset(ah, 0);
652 else
653 ret = ath5k_hw_nic_reset(ah, 0);
654
655 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400656 ATH5K_ERR(ah, "failed to warm reset the MAC Chip\n");
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300657 return -EIO;
658 }
659
660 /* On initialization skip PLL programming since we don't have
661 * a channel / mode set yet */
Pavel Roskin32c25462011-07-23 09:29:09 -0400662 if (!channel)
Nick Kossifidisedd7fc72009-08-10 03:29:02 +0300663 return 0;
664
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300665 if (ah->ah_version != AR5K_AR5210) {
666 /*
667 * Get channel mode flags
668 */
669
670 if (ah->ah_radio >= AR5K_RF5112) {
671 mode = AR5K_PHY_MODE_RAD_RF5112;
672 clock = AR5K_PHY_PLL_RF5112;
673 } else {
674 mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/
675 clock = AR5K_PHY_PLL_RF5111; /*Zero*/
676 }
677
Pavel Roskin32c25462011-07-23 09:29:09 -0400678 if (channel->band == IEEE80211_BAND_2GHZ) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300679 mode |= AR5K_PHY_MODE_FREQ_2GHZ;
680 clock |= AR5K_PHY_PLL_44MHZ;
681
Pavel Roskin32c25462011-07-23 09:29:09 -0400682 if (channel->hw_value == AR5K_MODE_11B) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300683 mode |= AR5K_PHY_MODE_MOD_CCK;
Pavel Roskin32c25462011-07-23 09:29:09 -0400684 } else {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300685 /* XXX Dynamic OFDM/CCK is not supported by the
686 * AR5211 so we set MOD_OFDM for plain g (no
687 * CCK headers) operation. We need to test
688 * this, 5211 might support ofdm-only g after
689 * all, there are also initial register values
Nick Kossifidisf08fbf62010-11-23 21:33:22 +0200690 * in the code for g mode (see initvals.c).
691 */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300692 if (ah->ah_version == AR5K_AR5211)
693 mode |= AR5K_PHY_MODE_MOD_OFDM;
694 else
695 mode |= AR5K_PHY_MODE_MOD_DYN;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300696 }
Pavel Roskin32c25462011-07-23 09:29:09 -0400697 } else if (channel->band == IEEE80211_BAND_5GHZ) {
698 mode |= (AR5K_PHY_MODE_FREQ_5GHZ |
699 AR5K_PHY_MODE_MOD_OFDM);
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200700
Nick Kossifidisf08fbf62010-11-23 21:33:22 +0200701 /* Different PLL setting for 5413 */
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200702 if (ah->ah_radio == AR5K_RF5413)
Pavel Roskin807e3732009-03-27 17:47:27 -0400703 clock = AR5K_PHY_PLL_40MHZ_5413;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200704 else
705 clock |= AR5K_PHY_PLL_40MHZ;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300706 } else {
Pavel Roskine0d687b2011-07-14 20:21:55 -0400707 ATH5K_ERR(ah, "invalid radio frequency mode\n");
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300708 return -EINVAL;
709 }
710
Nick Kossifidisf08fbf62010-11-23 21:33:22 +0200711 /*XXX: Can bwmode be used with dynamic mode ?
712 * (I don't think it supports 44MHz) */
Pavel Roskin6a2a0e72011-07-09 00:17:51 -0400713 /* On 2425 initvals TURBO_SHORT is not present */
Nick Kossifidisf08fbf62010-11-23 21:33:22 +0200714 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
715 turbo = AR5K_PHY_TURBO_MODE |
716 (ah->ah_radio == AR5K_RF2425) ? 0 :
717 AR5K_PHY_TURBO_SHORT;
718 } else if (ah->ah_bwmode != AR5K_BWMODE_DEFAULT) {
719 if (ah->ah_radio == AR5K_RF5413) {
720 mode |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ?
721 AR5K_PHY_MODE_HALF_RATE :
722 AR5K_PHY_MODE_QUARTER_RATE;
723 } else if (ah->ah_version == AR5K_AR5212) {
724 clock |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ?
725 AR5K_PHY_PLL_HALF_RATE :
726 AR5K_PHY_PLL_QUARTER_RATE;
727 }
728 }
729
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300730 } else { /* Reset the device */
731
732 /* ...enable Atheros turbo mode if requested */
Nick Kossifidisf08fbf62010-11-23 21:33:22 +0200733 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300734 ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
735 AR5K_PHY_TURBO);
736 }
737
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300738 if (ah->ah_version != AR5K_AR5210) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300739
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200740 /* ...update PLL if needed */
741 if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) {
742 ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
743 udelay(300);
744 }
745
746 /* ...set the PHY operating mode */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300747 ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
748 ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
749 }
750
751 return 0;
752}
753
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200754
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200755/**************************************\
756* Post-initvals register modifications *
757\**************************************/
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200758
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200759/* TODO: Half/Quarter rate */
760static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
761 struct ieee80211_channel *channel)
762{
763 if (ah->ah_version == AR5K_AR5212 &&
764 ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
765
766 /* Setup ADC control */
767 ath5k_hw_reg_write(ah,
768 (AR5K_REG_SM(2,
769 AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) |
770 AR5K_REG_SM(2,
771 AR5K_PHY_ADC_CTL_INBUFGAIN_ON) |
772 AR5K_PHY_ADC_CTL_PWD_DAC_OFF |
773 AR5K_PHY_ADC_CTL_PWD_ADC_OFF),
774 AR5K_PHY_ADC_CTL);
775
776
777
778 /* Disable barker RSSI threshold */
779 AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
780 AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR);
781
782 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL,
783 AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2);
784
785 /* Set the mute mask */
786 ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
787 }
788
789 /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */
790 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B)
791 ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH);
792
793 /* Enable DCU double buffering */
794 if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B)
795 AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
796 AR5K_TXCFG_DCU_DBL_BUF_DIS);
797
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200798 /* Set fast ADC */
799 if ((ah->ah_radio == AR5K_RF5413) ||
Felix Fietkau4cebb342010-12-02 10:27:21 +0100800 (ah->ah_radio == AR5K_RF2317) ||
801 (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200802 u32 fast_adc = true;
803
804 if (channel->center_freq == 2462 ||
805 channel->center_freq == 2467)
806 fast_adc = 0;
807
808 /* Only update if needed */
809 if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc)
810 ath5k_hw_reg_write(ah, fast_adc,
811 AR5K_PHY_FAST_ADC);
812 }
813
814 /* Fix for first revision of the RF5112 RF chipset */
815 if (ah->ah_radio == AR5K_RF5112 &&
816 ah->ah_radio_5ghz_revision <
817 AR5K_SREV_RAD_5112A) {
818 u32 data;
819 ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
820 AR5K_PHY_CCKTXCTL);
Pavel Roskin32c25462011-07-23 09:29:09 -0400821 if (channel->band == IEEE80211_BAND_5GHZ)
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200822 data = 0xffb81020;
823 else
824 data = 0xffb80d20;
825 ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
826 }
827
Nick Kossifidis325089a2010-11-23 21:02:20 +0200828 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200829 /* Clear QCU/DCU clock gating register */
830 ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
831 /* Set DAC/ADC delays */
Nick Kossifidis325089a2010-11-23 21:02:20 +0200832 ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ_5311,
833 AR5K_PHY_SCAL);
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200834 /* Enable PCU FIFO corruption ECO */
835 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
836 AR5K_DIAG_SW_ECO_ENABLE);
837 }
Nick Kossifidisb4050862010-11-23 21:04:43 +0200838
839 if (ah->ah_bwmode) {
840 /* Increase PHY switch and AGC settling time
841 * on turbo mode (ath5k_hw_commit_eeprom_settings
842 * will override settling time if available) */
843 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
844
845 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
846 AR5K_PHY_SETTLING_AGC,
847 AR5K_AGC_SETTLING_TURBO);
848
849 /* XXX: Initvals indicate we only increase
850 * switch time on AR5212, 5211 and 5210
851 * only change agc time (bug?) */
852 if (ah->ah_version == AR5K_AR5212)
853 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
854 AR5K_PHY_SETTLING_SWITCH,
855 AR5K_SWITCH_SETTLING_TURBO);
856
857 if (ah->ah_version == AR5K_AR5210) {
858 /* Set Frame Control Register */
859 ath5k_hw_reg_write(ah,
860 (AR5K_PHY_FRAME_CTL_INI |
861 AR5K_PHY_TURBO_MODE |
862 AR5K_PHY_TURBO_SHORT | 0x2020),
863 AR5K_PHY_FRAME_CTL_5210);
864 }
865 /* On 5413 PHY force window length for half/quarter rate*/
866 } else if ((ah->ah_mac_srev >= AR5K_SREV_AR5424) &&
867 (ah->ah_mac_srev <= AR5K_SREV_AR5414)) {
868 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL_5211,
869 AR5K_PHY_FRAME_CTL_WIN_LEN,
870 3);
871 }
872 } else if (ah->ah_version == AR5K_AR5210) {
873 /* Set Frame Control Register for normal operation */
874 ath5k_hw_reg_write(ah, (AR5K_PHY_FRAME_CTL_INI | 0x1020),
875 AR5K_PHY_FRAME_CTL_5210);
876 }
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200877}
878
879static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
Bruno Randolf0207c0c2010-12-21 17:30:43 +0900880 struct ieee80211_channel *channel)
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200881{
882 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200883 s16 cck_ofdm_pwr_delta;
Bruno Randolf0207c0c2010-12-21 17:30:43 +0900884 u8 ee_mode;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200885
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200886 /* TODO: Add support for AR5210 EEPROM */
887 if (ah->ah_version == AR5K_AR5210)
888 return;
889
Bruno Randolf0207c0c2010-12-21 17:30:43 +0900890 ee_mode = ath5k_eeprom_mode_from_channel(channel);
891
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200892 /* Adjust power delta for channel 14 */
893 if (channel->center_freq == 2484)
894 cck_ofdm_pwr_delta =
895 ((ee->ee_cck_ofdm_power_delta -
896 ee->ee_scaled_cck_delta) * 2) / 10;
897 else
898 cck_ofdm_pwr_delta =
899 (ee->ee_cck_ofdm_power_delta * 2) / 10;
900
901 /* Set CCK to OFDM power delta on tx power
902 * adjustment register */
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200903 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
Pavel Roskin32c25462011-07-23 09:29:09 -0400904 if (channel->hw_value == AR5K_MODE_11G)
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200905 ath5k_hw_reg_write(ah,
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200906 AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200907 AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
908 AR5K_REG_SM((cck_ofdm_pwr_delta * -1),
909 AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX),
910 AR5K_PHY_TX_PWR_ADJ);
911 else
912 ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ);
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200913 } else {
914 /* For older revs we scale power on sw during tx power
915 * setup */
916 ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta;
917 ah->ah_txpower.txp_cck_ofdm_gainf_delta =
918 ee->ee_cck_ofdm_gain_delta;
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200919 }
920
Bruno Randolf0ca74022010-06-07 13:11:30 +0900921 /* XXX: necessary here? is called from ath5k_hw_set_antenna_mode()
922 * too */
923 ath5k_hw_set_antenna_switch(ah, ee_mode);
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200924
925 /* Noise floor threshold */
926 ath5k_hw_reg_write(ah,
927 AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
928 AR5K_PHY_NFTHRES);
929
Nick Kossifidisacb091d2010-11-23 21:49:53 +0200930 if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) &&
Nick Kossifidise8f055f2009-02-09 06:12:58 +0200931 (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
932 /* Switch settling time (Turbo) */
933 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
934 AR5K_PHY_SETTLING_SWITCH,
935 ee->ee_switch_settling_turbo[ee_mode]);
936
937 /* Tx/Rx attenuation (Turbo) */
938 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
939 AR5K_PHY_GAIN_TXRX_ATTEN,
940 ee->ee_atn_tx_rx_turbo[ee_mode]);
941
942 /* ADC/PGA desired size (Turbo) */
943 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
944 AR5K_PHY_DESIRED_SIZE_ADC,
945 ee->ee_adc_desired_size_turbo[ee_mode]);
946
947 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
948 AR5K_PHY_DESIRED_SIZE_PGA,
949 ee->ee_pga_desired_size_turbo[ee_mode]);
950
951 /* Tx/Rx margin (Turbo) */
952 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
953 AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
954 ee->ee_margin_tx_rx_turbo[ee_mode]);
955
956 } else {
957 /* Switch settling time */
958 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
959 AR5K_PHY_SETTLING_SWITCH,
960 ee->ee_switch_settling[ee_mode]);
961
962 /* Tx/Rx attenuation */
963 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN,
964 AR5K_PHY_GAIN_TXRX_ATTEN,
965 ee->ee_atn_tx_rx[ee_mode]);
966
967 /* ADC/PGA desired size */
968 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
969 AR5K_PHY_DESIRED_SIZE_ADC,
970 ee->ee_adc_desired_size[ee_mode]);
971
972 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE,
973 AR5K_PHY_DESIRED_SIZE_PGA,
974 ee->ee_pga_desired_size[ee_mode]);
975
976 /* Tx/Rx margin */
977 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
978 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
979 AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
980 ee->ee_margin_tx_rx[ee_mode]);
981 }
982
983 /* XPA delays */
984 ath5k_hw_reg_write(ah,
985 (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
986 (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
987 (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
988 (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
989
990 /* XLNA delay */
991 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3,
992 AR5K_PHY_RF_CTL3_TXE2XLNA_ON,
993 ee->ee_tx_end2xlna_enable[ee_mode]);
994
995 /* Thresh64 (ANI) */
996 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF,
997 AR5K_PHY_NF_THRESH62,
998 ee->ee_thr_62[ee_mode]);
999
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001000 /* False detect backoff for channels
1001 * that have spur noise. Write the new
1002 * cyclic power RSSI threshold. */
1003 if (ath5k_hw_chan_has_spur_noise(ah, channel))
1004 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
1005 AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
1006 AR5K_INIT_CYCRSSI_THR1 +
1007 ee->ee_false_detect[ee_mode]);
1008 else
1009 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR,
1010 AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1,
1011 AR5K_INIT_CYCRSSI_THR1);
1012
Bruno Randolf5f13bfa2010-03-09 16:56:10 +09001013 /* I/Q correction (set enable bit last to match HAL sources) */
1014 /* TODO: Per channel i/q infos ? */
1015 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
1016 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF,
1017 ee->ee_i_cal[ee_mode]);
1018 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF,
1019 ee->ee_q_cal[ee_mode]);
1020 AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE);
1021 }
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001022
1023 /* Heavy clipping -disable for now */
1024 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1)
1025 ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001026}
1027
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001028
1029/*********************\
1030* Main reset function *
1031\*********************/
1032
Johannes Berg05c914f2008-09-11 00:01:58 +02001033int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001034 struct ieee80211_channel *channel, bool fast, bool skip_pcu)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001035{
Nick Kossifidisc2b0ebe2010-11-23 21:42:22 +02001036 u32 s_seq[10], s_led[3], tsf_up, tsf_lo;
Bruno Randolf0207c0c2010-12-21 17:30:43 +09001037 u8 mode;
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001038 int i, ret;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001039
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001040 tsf_up = 0;
1041 tsf_lo = 0;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001042 mode = 0;
1043
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001044 /*
1045 * Sanity check for fast flag
1046 * Fast channel change only available
1047 * on AR2413/AR5413.
1048 */
1049 if (fast && (ah->ah_radio != AR5K_RF2413) &&
1050 (ah->ah_radio != AR5K_RF5413))
1051 fast = 0;
1052
1053 /* Disable sleep clock operation
1054 * to avoid register access delay on certain
1055 * PHY registers */
1056 if (ah->ah_version == AR5K_AR5212)
1057 ath5k_hw_set_sleep_clock(ah, false);
Nick Kossifidisc2975602010-11-23 21:00:37 +02001058
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001059 /*
Nick Kossifidise088f232010-11-23 20:43:18 +02001060 * Stop PCU
1061 */
1062 ath5k_hw_stop_rx_pcu(ah);
1063
1064 /*
Nick Kossifidisd41174f2010-11-23 20:41:15 +02001065 * Stop DMA
1066 *
1067 * Note: If DMA didn't stop continue
1068 * since only a reset will fix it.
1069 */
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001070 ret = ath5k_hw_dma_stop(ah);
1071
1072 /* RF Bus grant won't work if we have pending
1073 * frames */
1074 if (ret && fast) {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001075 ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001076 "DMA didn't stop, falling back to normal reset\n");
1077 fast = 0;
1078 /* Non fatal, just continue with
1079 * normal reset */
1080 ret = 0;
1081 }
1082
Pavel Roskin32c25462011-07-23 09:29:09 -04001083 mode = channel->hw_value;
1084 switch (mode) {
1085 case AR5K_MODE_11A:
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001086 break;
Pavel Roskin32c25462011-07-23 09:29:09 -04001087 case AR5K_MODE_11G:
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001088 if (ah->ah_version <= AR5K_AR5211) {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001089 ATH5K_ERR(ah,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001090 "G mode not available on 5210/5211");
1091 return -EINVAL;
1092 }
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001093 break;
Pavel Roskin32c25462011-07-23 09:29:09 -04001094 case AR5K_MODE_11B:
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001095 if (ah->ah_version < AR5K_AR5211) {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001096 ATH5K_ERR(ah,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001097 "B mode not available on 5210");
1098 return -EINVAL;
1099 }
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001100 break;
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001101 default:
Pavel Roskine0d687b2011-07-14 20:21:55 -04001102 ATH5K_ERR(ah,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001103 "invalid channel: %d\n", channel->center_freq);
1104 return -EINVAL;
1105 }
1106
1107 /*
1108 * If driver requested fast channel change and DMA has stopped
1109 * go on. If it fails continue with a normal reset.
1110 */
1111 if (fast) {
Bruno Randolf0207c0c2010-12-21 17:30:43 +09001112 ret = ath5k_hw_phy_init(ah, channel, mode, true);
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001113 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001114 ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001115 "fast chan change failed, falling back to normal reset\n");
1116 /* Non fatal, can happen eg.
1117 * on mode change */
1118 ret = 0;
Nick Kossifidisa99168e2011-06-02 03:09:48 +03001119 } else {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001120 ATH5K_DBG(ah, ATH5K_DEBUG_RESET,
Nick Kossifidisa99168e2011-06-02 03:09:48 +03001121 "fast chan change successful\n");
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001122 return 0;
Nick Kossifidisa99168e2011-06-02 03:09:48 +03001123 }
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001124 }
Nick Kossifidisd41174f2010-11-23 20:41:15 +02001125
1126 /*
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001127 * Save some registers before a reset
1128 */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001129 if (ah->ah_version != AR5K_AR5210) {
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001130 /*
1131 * Save frame sequence count
1132 * For revs. after Oahu, only save
1133 * seq num for DCU 0 (Global seq num)
1134 */
1135 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001136
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001137 for (i = 0; i < 10; i++)
1138 s_seq[i] = ath5k_hw_reg_read(ah,
1139 AR5K_QUEUE_DCU_SEQNUM(i));
1140
1141 } else {
1142 s_seq[0] = ath5k_hw_reg_read(ah,
1143 AR5K_QUEUE_DCU_SEQNUM(0));
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001144 }
1145
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001146 /* TSF accelerates on AR5211 during reset
1147 * As a workaround save it here and restore
1148 * it later so that it's back in time after
1149 * reset. This way it'll get re-synced on the
1150 * next beacon without breaking ad-hoc.
1151 *
1152 * On AR5212 TSF is almost preserved across a
1153 * reset so it stays back in time anyway and
1154 * we don't have to save/restore it.
1155 *
1156 * XXX: Since this breaks power saving we have
1157 * to disable power saving until we receive the
1158 * next beacon, so we can resync beacon timers */
1159 if (ah->ah_version == AR5K_AR5211) {
1160 tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
1161 tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001162 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001163 }
1164
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001165
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001166 /*GPIOs*/
1167 s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
1168 AR5K_PCICFG_LEDSTATE;
1169 s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
1170 s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
Nick Kossifidisa406c132009-02-09 06:08:51 +02001171
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001172
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001173 /*
1174 * Since we are going to write rf buffer
1175 * check if we have any pending gain_F
1176 * optimization settings
1177 */
1178 if (ah->ah_version == AR5K_AR5212 &&
1179 (ah->ah_radio <= AR5K_RF5112)) {
1180 if (!fast && ah->ah_rf_banks != NULL)
1181 ath5k_hw_gainf_calibrate(ah);
1182 }
1183
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001184 /* Wakeup the device */
Pavel Roskin32c25462011-07-23 09:29:09 -04001185 ret = ath5k_hw_nic_wakeup(ah, channel);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001186 if (ret)
1187 return ret;
1188
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001189 /* PHY access enable */
1190 if (ah->ah_mac_srev >= AR5K_SREV_AR5211)
1191 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
1192 else
1193 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40,
1194 AR5K_PHY(0));
1195
1196 /* Write initial settings */
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001197 ret = ath5k_hw_write_initvals(ah, mode, skip_pcu);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001198 if (ret)
1199 return ret;
1200
Nick Kossifidisc2975602010-11-23 21:00:37 +02001201 /* Initialize core clock settings */
1202 ath5k_hw_init_core_clock(ah);
1203
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001204 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001205 * Tweak initval settings for revised
1206 * chipsets and add some more config
1207 * bits
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001208 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001209 ath5k_hw_tweak_initval_settings(ah, channel);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001210
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001211 /* Commit values from EEPROM */
Bruno Randolf0207c0c2010-12-21 17:30:43 +09001212 ath5k_hw_commit_eeprom_settings(ah, channel);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001213
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001214
1215 /*
1216 * Restore saved values
1217 */
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001218
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001219 /* Seqnum, TSF */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001220 if (ah->ah_version != AR5K_AR5210) {
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001221 if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
1222 for (i = 0; i < 10; i++)
1223 ath5k_hw_reg_write(ah, s_seq[i],
1224 AR5K_QUEUE_DCU_SEQNUM(i));
1225 } else {
1226 ath5k_hw_reg_write(ah, s_seq[0],
1227 AR5K_QUEUE_DCU_SEQNUM(0));
1228 }
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001229
Nick Kossifidis8aec7af2010-11-23 21:39:28 +02001230 if (ah->ah_version == AR5K_AR5211) {
1231 ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
1232 ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001233 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001234 }
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001235
1236 /* Ledstate */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001237 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001238
1239 /* Gpio settings */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001240 ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
1241 ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
1242
1243 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001244 * Initialize PCU
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001245 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001246 ath5k_hw_pcu_init(ah, op_mode, mode);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001247
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001248 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001249 * Initialize PHY
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001250 */
Bruno Randolf0207c0c2010-12-21 17:30:43 +09001251 ret = ath5k_hw_phy_init(ah, channel, mode, false);
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001252 if (ret) {
Pavel Roskine0d687b2011-07-14 20:21:55 -04001253 ATH5K_ERR(ah,
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001254 "failed to initialize PHY (%i) !\n", ret);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001255 return ret;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001256 }
1257
1258 /*
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001259 * Configure QCUs/DCUs
1260 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001261 ret = ath5k_hw_init_queues(ah);
1262 if (ret)
1263 return ret;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001264
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001265
1266 /*
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001267 * Initialize DMA/Interrupts
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001268 */
Nick Kossifidis9320b5c42010-11-23 20:36:45 +02001269 ath5k_hw_dma_init(ah);
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001270
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001271
Felix Fietkau63402112011-07-12 09:02:04 +08001272 /*
1273 * Enable 32KHz clock function for AR5212+ chips
Nick Kossifidise8f055f2009-02-09 06:12:58 +02001274 * Set clocks to 32KHz operation and use an
1275 * external 32KHz crystal when sleeping if one
Felix Fietkau63402112011-07-12 09:02:04 +08001276 * exists.
1277 * Disabled by default because it is also disabled in
1278 * other drivers and it is known to cause stability
1279 * issues on some devices
1280 */
1281 if (ah->ah_use_32khz_clock && ah->ah_version == AR5K_AR5212 &&
Bruno Randolfccfe5552010-03-09 16:55:38 +09001282 op_mode != NL80211_IFTYPE_AP)
Bob Copeland5d6ce622010-01-20 23:51:03 -05001283 ath5k_hw_set_sleep_clock(ah, true);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001284
1285 /*
Bruno Randolfa3b980f2010-03-09 16:55:33 +09001286 * Disable beacons and reset the TSF
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001287 */
Bruno Randolfa3b980f2010-03-09 16:55:33 +09001288 AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
1289 ath5k_hw_reset_tsf(ah);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001290 return 0;
1291}