aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k/attach.c
diff options
context:
space:
mode:
authorNick Kossifidis <mick@madwifi.org>2008-08-29 15:45:39 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-05 16:15:24 -0400
commitc6e387a214f4b2c4bd48020409e366c133385d98 (patch)
tree11fd58fd71e113a62d05f6f191771ca3d7d544f0 /drivers/net/wireless/ath5k/attach.c
parentfa9abe050d0a018b888fce61a4353afab17b0860 (diff)
ath5k: HW code cleanup
* No code changes... * Split hw.c to multiple files for better maintenance and add some documentation on each file code is going to grow soon (eeprom.c for example is going to get much stuff currently developed on ath_info) so it's better this way. * Rename following functions to maintain naming scheme: ah_setup_xtx_desc -> ah_setup_mrr_tx_desc (Because xtx doesn't say much, it's actually a multi-rate-retry tx descriptor) ath5k_hw_put_tx/rx_buf - > ath5k_hw_set_tx/rxdp ath5k_hw_get_tx/rx_buf -> ath5k_hw_get_tx/rxdp (We don't put any "buf" we set descriptor pointers on hw) ath5k_hw_tx_start -> ath5k_hw_start_tx_dma ath5k_hw_start_rx -> ath5k_hw_start_rx_dma ath5k_hw_stop_pcu_recv -> ath5k_hw_stop_rx_pcu (It's easier this way to identify them, we also have ath5k_hw_start_rx_pcu which completes the set) ath5k_hw_set_intr -> ath5k_hw_set_imr (As in get_isr we set imr here, not "intr") * Move ath5k_hw_setup_rx_desc on ah->ah_setup_rx_desc so we can include support for different rx descriptors in the future * Further cleanups so that checkpatch doesn't complain (only some > 80 col warnings for eeprom.h and reg.h as usual due to comments) Tested on 5211 and 5213 cards and works ok. Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis <mickflemm@gmail.com> Acked-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath5k/attach.c')
-rw-r--r--drivers/net/wireless/ath5k/attach.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c
new file mode 100644
index 000000000000..0eb2511fe147
--- /dev/null
+++ b/drivers/net/wireless/ath5k/attach.c
@@ -0,0 +1,315 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 */
18
19/*************************************\
20* Attach/Detach Functions and helpers *
21\*************************************/
22
23#include <linux/pci.h>
24#include "ath5k.h"
25#include "reg.h"
26#include "debug.h"
27#include "base.h"
28
29/**
30 * ath5k_hw_post - Power On Self Test helper function
31 *
32 * @ah: The &struct ath5k_hw
33 */
34static int ath5k_hw_post(struct ath5k_hw *ah)
35{
36
37 int i, c;
38 u16 cur_reg;
39 u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)};
40 u32 var_pattern;
41 u32 static_pattern[4] = {
42 0x55555555, 0xaaaaaaaa,
43 0x66666666, 0x99999999
44 };
45 u32 init_val;
46 u32 cur_val;
47
48 for (c = 0; c < 2; c++) {
49
50 cur_reg = regs[c];
51
52 /* Save previous value */
53 init_val = ath5k_hw_reg_read(ah, cur_reg);
54
55 for (i = 0; i < 256; i++) {
56 var_pattern = i << 16 | i;
57 ath5k_hw_reg_write(ah, var_pattern, cur_reg);
58 cur_val = ath5k_hw_reg_read(ah, cur_reg);
59
60 if (cur_val != var_pattern) {
61 ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
62 return -EAGAIN;
63 }
64
65 /* Found on ndiswrapper dumps */
66 var_pattern = 0x0039080f;
67 ath5k_hw_reg_write(ah, var_pattern, cur_reg);
68 }
69
70 for (i = 0; i < 4; i++) {
71 var_pattern = static_pattern[i];
72 ath5k_hw_reg_write(ah, var_pattern, cur_reg);
73 cur_val = ath5k_hw_reg_read(ah, cur_reg);
74
75 if (cur_val != var_pattern) {
76 ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
77 return -EAGAIN;
78 }
79
80 /* Found on ndiswrapper dumps */
81 var_pattern = 0x003b080f;
82 ath5k_hw_reg_write(ah, var_pattern, cur_reg);
83 }
84
85 /* Restore previous value */
86 ath5k_hw_reg_write(ah, init_val, cur_reg);
87
88 }
89
90 return 0;
91
92}
93
94/**
95 * ath5k_hw_attach - Check if hw is supported and init the needed structs
96 *
97 * @sc: The &struct ath5k_softc we got from the driver's attach function
98 * @mac_version: The mac version id (check out ath5k.h) based on pci id
99 *
100 * Check if the device is supported, perform a POST and initialize the needed
101 * structs. Returns -ENOMEM if we don't have memory for the needed structs,
102 * -ENODEV if the device is not supported or prints an error msg if something
103 * else went wrong.
104 */
105struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
106{
107 struct ath5k_hw *ah;
108 struct pci_dev *pdev = sc->pdev;
109 u8 mac[ETH_ALEN];
110 int ret;
111 u32 srev;
112
113 /*If we passed the test malloc a ath5k_hw struct*/
114 ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
115 if (ah == NULL) {
116 ret = -ENOMEM;
117 ATH5K_ERR(sc, "out of memory\n");
118 goto err;
119 }
120
121 ah->ah_sc = sc;
122 ah->ah_iobase = sc->iobase;
123
124 /*
125 * HW information
126 */
127 ah->ah_op_mode = IEEE80211_IF_TYPE_STA;
128 ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
129 ah->ah_turbo = false;
130 ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
131 ah->ah_imr = 0;
132 ah->ah_atim_window = 0;
133 ah->ah_aifs = AR5K_TUNE_AIFS;
134 ah->ah_cw_min = AR5K_TUNE_CWMIN;
135 ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
136 ah->ah_software_retry = false;
137 ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
138
139 /*
140 * Set the mac revision based on the pci id
141 */
142 ah->ah_version = mac_version;
143
144 /*Fill the ath5k_hw struct with the needed functions*/
145 ret = ath5k_hw_init_desc_functions(ah);
146 if (ret)
147 goto err_free;
148
149 /* Bring device out of sleep and reset it's units */
150 ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true);
151 if (ret)
152 goto err_free;
153
154 /* Get MAC, PHY and RADIO revisions */
155 srev = ath5k_hw_reg_read(ah, AR5K_SREV);
156 ah->ah_mac_srev = srev;
157 ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
158 ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
159 ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
160 0xffffffff;
161 ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
162 CHANNEL_5GHZ);
163
164 if (ah->ah_version == AR5K_AR5210)
165 ah->ah_radio_2ghz_revision = 0;
166 else
167 ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
168 CHANNEL_2GHZ);
169
170 /* Return on unsuported chips (unsupported eeprom etc) */
171 if ((srev >= AR5K_SREV_VER_AR5416) &&
172 (srev < AR5K_SREV_VER_AR2425)) {
173 ATH5K_ERR(sc, "Device not yet supported.\n");
174 ret = -ENODEV;
175 goto err_free;
176 } else if (srev == AR5K_SREV_VER_AR2425) {
177 ATH5K_WARN(sc, "Support for RF2425 is under development.\n");
178 }
179
180 /* Identify single chip solutions */
181 if (((srev <= AR5K_SREV_VER_AR5414) &&
182 (srev >= AR5K_SREV_VER_AR2413)) ||
183 (srev == AR5K_SREV_VER_AR2425)) {
184 ah->ah_single_chip = true;
185 } else {
186 ah->ah_single_chip = false;
187 }
188
189 /* Single chip radio */
190 if (ah->ah_radio_2ghz_revision == ah->ah_radio_5ghz_revision)
191 ah->ah_radio_2ghz_revision = 0;
192
193 /* Identify the radio chip*/
194 if (ah->ah_version == AR5K_AR5210) {
195 ah->ah_radio = AR5K_RF5110;
196 /*
197 * Register returns 0x0/0x04 for radio revision
198 * so ath5k_hw_radio_revision doesn't parse the value
199 * correctly. For now we are based on mac's srev to
200 * identify RF2425 radio.
201 */
202 } else if (srev == AR5K_SREV_VER_AR2425) {
203 ah->ah_radio = AR5K_RF2425;
204 ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425;
205 } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
206 ah->ah_radio = AR5K_RF5111;
207 ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
208 } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) {
209 ah->ah_radio = AR5K_RF5112;
210 ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
211 } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
212 ah->ah_radio = AR5K_RF2413;
213 ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
214 } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) {
215 ah->ah_radio = AR5K_RF5413;
216 ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
217 } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) {
218 /* AR5424 */
219 if (srev >= AR5K_SREV_VER_AR5424) {
220 ah->ah_radio = AR5K_RF5413;
221 ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
222 /* AR2424 */
223 } else {
224 ah->ah_radio = AR5K_RF2413; /* For testing */
225 ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
226 }
227 }
228 ah->ah_phy = AR5K_PHY(0);
229
230 /*
231 * Write PCI-E power save settings
232 */
233 if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
234 ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080);
235 ath5k_hw_reg_write(ah, 0x24924924, 0x4080);
236 ath5k_hw_reg_write(ah, 0x28000039, 0x4080);
237 ath5k_hw_reg_write(ah, 0x53160824, 0x4080);
238 ath5k_hw_reg_write(ah, 0xe5980579, 0x4080);
239 ath5k_hw_reg_write(ah, 0x001defff, 0x4080);
240 ath5k_hw_reg_write(ah, 0x1aaabe40, 0x4080);
241 ath5k_hw_reg_write(ah, 0xbe105554, 0x4080);
242 ath5k_hw_reg_write(ah, 0x000e3007, 0x4080);
243 ath5k_hw_reg_write(ah, 0x00000000, 0x4084);
244 }
245
246 /*
247 * POST
248 */
249 ret = ath5k_hw_post(ah);
250 if (ret)
251 goto err_free;
252
253 /* Write AR5K_PCICFG_UNK on 2112B and later chips */
254 if (ah->ah_radio_5ghz_revision > AR5K_SREV_RAD_2112B ||
255 srev > AR5K_SREV_VER_AR2413) {
256 ath5k_hw_reg_write(ah, AR5K_PCICFG_UNK, AR5K_PCICFG);
257 }
258
259 /*
260 * Get card capabilities, values, ...
261 */
262 ret = ath5k_eeprom_init(ah);
263 if (ret) {
264 ATH5K_ERR(sc, "unable to init EEPROM\n");
265 goto err_free;
266 }
267
268 /* Get misc capabilities */
269 ret = ath5k_hw_set_capabilities(ah);
270 if (ret) {
271 ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n",
272 sc->pdev->device);
273 goto err_free;
274 }
275
276 /* Get MAC address */
277 ret = ath5k_eeprom_read_mac(ah, mac);
278 if (ret) {
279 ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
280 sc->pdev->device);
281 goto err_free;
282 }
283
284 ath5k_hw_set_lladdr(ah, mac);
285 /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
286 memset(ah->ah_bssid, 0xff, ETH_ALEN);
287 ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
288 ath5k_hw_set_opmode(ah);
289
290 ath5k_hw_set_rfgain_opt(ah);
291
292 return ah;
293err_free:
294 kfree(ah);
295err:
296 return ERR_PTR(ret);
297}
298
299/**
300 * ath5k_hw_detach - Free the ath5k_hw struct
301 *
302 * @ah: The &struct ath5k_hw
303 */
304void ath5k_hw_detach(struct ath5k_hw *ah)
305{
306 ATH5K_TRACE(ah->ah_sc);
307
308 __set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
309
310 if (ah->ah_rf_banks != NULL)
311 kfree(ah->ah_rf_banks);
312
313 /* assume interrupts are down */
314 kfree(ah);
315}