Commit | Line | Data |
---|---|---|
30295c89 VM |
1 | //------------------------------------------------------------------------------ |
2 | // Copyright (c) 2009-2010 Atheros Corporation. All rights reserved. | |
3 | // | |
4 | // | |
5 | // Permission to use, copy, modify, and/or 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 | // AR3K configuration implementation | |
21 | // | |
22 | // Author(s): ="Atheros" | |
23 | //============================================================================== | |
24 | ||
25 | #include "a_config.h" | |
26 | #include "athdefs.h" | |
27 | #include "a_types.h" | |
28 | #include "a_osapi.h" | |
29 | #define ATH_MODULE_NAME misc | |
30 | #include "a_debug.h" | |
31 | #include "common_drv.h" | |
32 | #ifdef EXPORT_HCI_BRIDGE_INTERFACE | |
33 | #include "export_hci_transport.h" | |
34 | #else | |
35 | #include "hci_transport_api.h" | |
36 | #endif | |
37 | #include "ar3kconfig.h" | |
38 | #include "tlpm.h" | |
39 | ||
40 | #define BAUD_CHANGE_COMMAND_STATUS_OFFSET 5 | |
41 | #define HCI_EVENT_RESP_TIMEOUTMS 3000 | |
42 | #define HCI_CMD_OPCODE_BYTE_LOW_OFFSET 0 | |
43 | #define HCI_CMD_OPCODE_BYTE_HI_OFFSET 1 | |
44 | #define HCI_EVENT_OPCODE_BYTE_LOW 3 | |
45 | #define HCI_EVENT_OPCODE_BYTE_HI 4 | |
46 | #define HCI_CMD_COMPLETE_EVENT_CODE 0xE | |
47 | #define HCI_MAX_EVT_RECV_LENGTH 257 | |
48 | #define EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET 5 | |
49 | ||
1f4c34bd | 50 | int AthPSInitialize(AR3K_CONFIG_INFO *hdev); |
30295c89 | 51 | |
1f4c34bd | 52 | static int SendHCICommand(AR3K_CONFIG_INFO *pConfig, |
ab3655da | 53 | u8 *pBuffer, |
30295c89 VM |
54 | int Length) |
55 | { | |
56 | HTC_PACKET *pPacket = NULL; | |
1f4c34bd | 57 | int status = A_OK; |
30295c89 VM |
58 | |
59 | do { | |
60 | ||
61 | pPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET)); | |
62 | if (NULL == pPacket) { | |
63 | status = A_NO_MEMORY; | |
64 | break; | |
65 | } | |
66 | ||
67 | A_MEMZERO(pPacket,sizeof(HTC_PACKET)); | |
68 | SET_HTC_PACKET_INFO_TX(pPacket, | |
69 | NULL, | |
70 | pBuffer, | |
71 | Length, | |
72 | HCI_COMMAND_TYPE, | |
73 | AR6K_CONTROL_PKT_TAG); | |
74 | ||
75 | /* issue synchronously */ | |
1071a134 | 76 | status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,true); |
30295c89 | 77 | |
1071a134 | 78 | } while (false); |
30295c89 VM |
79 | |
80 | if (pPacket != NULL) { | |
81 | A_FREE(pPacket); | |
82 | } | |
83 | ||
84 | return status; | |
85 | } | |
86 | ||
1f4c34bd | 87 | static int RecvHCIEvent(AR3K_CONFIG_INFO *pConfig, |
ab3655da | 88 | u8 *pBuffer, |
30295c89 VM |
89 | int *pLength) |
90 | { | |
1f4c34bd | 91 | int status = A_OK; |
30295c89 VM |
92 | HTC_PACKET *pRecvPacket = NULL; |
93 | ||
94 | do { | |
95 | ||
96 | pRecvPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET)); | |
97 | if (NULL == pRecvPacket) { | |
98 | status = A_NO_MEMORY; | |
99 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); | |
100 | break; | |
101 | } | |
102 | ||
103 | A_MEMZERO(pRecvPacket,sizeof(HTC_PACKET)); | |
104 | ||
105 | SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE); | |
106 | ||
107 | status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev, | |
108 | pRecvPacket, | |
109 | HCI_EVENT_RESP_TIMEOUTMS); | |
391bb211 | 110 | if (status) { |
30295c89 VM |
111 | break; |
112 | } | |
113 | ||
114 | *pLength = pRecvPacket->ActualLength; | |
115 | ||
1071a134 | 116 | } while (false); |
30295c89 VM |
117 | |
118 | if (pRecvPacket != NULL) { | |
119 | A_FREE(pRecvPacket); | |
120 | } | |
121 | ||
122 | return status; | |
123 | } | |
124 | ||
1f4c34bd | 125 | int SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig, |
ab3655da | 126 | u8 *pHCICommand, |
30295c89 | 127 | int CmdLength, |
ab3655da JP |
128 | u8 **ppEventBuffer, |
129 | u8 **ppBufferToFree) | |
30295c89 | 130 | { |
1f4c34bd | 131 | int status = A_OK; |
ab3655da JP |
132 | u8 *pBuffer = NULL; |
133 | u8 *pTemp; | |
30295c89 | 134 | int length; |
1071a134 | 135 | bool commandComplete = false; |
ab3655da | 136 | u8 opCodeBytes[2]; |
30295c89 VM |
137 | |
138 | do { | |
139 | ||
140 | length = max(HCI_MAX_EVT_RECV_LENGTH,CmdLength); | |
141 | length += pConfig->pHCIProps->HeadRoom + pConfig->pHCIProps->TailRoom; | |
142 | length += pConfig->pHCIProps->IOBlockPad; | |
143 | ||
ab3655da | 144 | pBuffer = (u8 *)A_MALLOC(length); |
30295c89 VM |
145 | if (NULL == pBuffer) { |
146 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to allocate bt buffer \n")); | |
147 | status = A_NO_MEMORY; | |
148 | break; | |
149 | } | |
150 | ||
151 | /* get the opcodes to check the command complete event */ | |
152 | opCodeBytes[0] = pHCICommand[HCI_CMD_OPCODE_BYTE_LOW_OFFSET]; | |
153 | opCodeBytes[1] = pHCICommand[HCI_CMD_OPCODE_BYTE_HI_OFFSET]; | |
154 | ||
155 | /* copy HCI command */ | |
156 | A_MEMCPY(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength); | |
157 | /* send command */ | |
158 | status = SendHCICommand(pConfig, | |
159 | pBuffer + pConfig->pHCIProps->HeadRoom, | |
160 | CmdLength); | |
391bb211 | 161 | if (status) { |
30295c89 VM |
162 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to send HCI Command (%d) \n", status)); |
163 | AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command"); | |
164 | break; | |
165 | } | |
166 | ||
167 | /* reuse buffer to capture command complete event */ | |
168 | A_MEMZERO(pBuffer,length); | |
169 | status = RecvHCIEvent(pConfig,pBuffer,&length); | |
391bb211 | 170 | if (status) { |
30295c89 VM |
171 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI event recv failed \n")); |
172 | AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command"); | |
173 | break; | |
174 | } | |
175 | ||
176 | pTemp = pBuffer + pConfig->pHCIProps->HeadRoom; | |
177 | if (pTemp[0] == HCI_CMD_COMPLETE_EVENT_CODE) { | |
178 | if ((pTemp[HCI_EVENT_OPCODE_BYTE_LOW] == opCodeBytes[0]) && | |
179 | (pTemp[HCI_EVENT_OPCODE_BYTE_HI] == opCodeBytes[1])) { | |
1071a134 | 180 | commandComplete = true; |
30295c89 VM |
181 | } |
182 | } | |
183 | ||
184 | if (!commandComplete) { | |
185 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Unexpected HCI event : %d \n",pTemp[0])); | |
186 | AR_DEBUG_PRINTBUF(pTemp,pTemp[1],"Unexpected HCI event"); | |
187 | status = A_ECOMM; | |
188 | break; | |
189 | } | |
190 | ||
191 | if (ppEventBuffer != NULL) { | |
192 | /* caller wants to look at the event */ | |
193 | *ppEventBuffer = pTemp; | |
194 | if (ppBufferToFree == NULL) { | |
195 | status = A_EINVAL; | |
196 | break; | |
197 | } | |
198 | /* caller must free the buffer */ | |
199 | *ppBufferToFree = pBuffer; | |
200 | pBuffer = NULL; | |
201 | } | |
202 | ||
1071a134 | 203 | } while (false); |
30295c89 VM |
204 | |
205 | if (pBuffer != NULL) { | |
206 | A_FREE(pBuffer); | |
207 | } | |
208 | ||
209 | return status; | |
210 | } | |
211 | ||
1f4c34bd | 212 | static int AR3KConfigureHCIBaud(AR3K_CONFIG_INFO *pConfig) |
30295c89 | 213 | { |
1f4c34bd | 214 | int status = A_OK; |
ab3655da | 215 | u8 hciBaudChangeCommand[] = {0x0c,0xfc,0x2,0,0}; |
30295c89 | 216 | A_UINT16 baudVal; |
ab3655da JP |
217 | u8 *pEvent = NULL; |
218 | u8 *pBufferToFree = NULL; | |
30295c89 VM |
219 | |
220 | do { | |
221 | ||
222 | if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) { | |
223 | baudVal = (A_UINT16)(pConfig->AR3KBaudRate / 100); | |
ab3655da JP |
224 | hciBaudChangeCommand[3] = (u8)baudVal; |
225 | hciBaudChangeCommand[4] = (u8)(baudVal >> 8); | |
30295c89 VM |
226 | |
227 | status = SendHCICommandWaitCommandComplete(pConfig, | |
228 | hciBaudChangeCommand, | |
229 | sizeof(hciBaudChangeCommand), | |
230 | &pEvent, | |
231 | &pBufferToFree); | |
391bb211 | 232 | if (status) { |
30295c89 VM |
233 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n")); |
234 | break; | |
235 | } | |
236 | ||
237 | if (pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET] != 0) { | |
238 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | |
239 | ("AR3K Config: Baud change command event status failed: %d \n", | |
240 | pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET])); | |
241 | status = A_ECOMM; | |
242 | break; | |
243 | } | |
244 | ||
245 | AR_DEBUG_PRINTF(ATH_DEBUG_ANY, | |
246 | ("AR3K Config: Baud Changed to %d \n",pConfig->AR3KBaudRate)); | |
247 | } | |
248 | ||
249 | if (pConfig->Flags & AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY) { | |
250 | /* some versions of AR3K do not switch baud immediately, up to 300MS */ | |
251 | A_MDELAY(325); | |
252 | } | |
253 | ||
254 | if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP) { | |
255 | /* Tell target to change UART baud rate for AR6K */ | |
256 | status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate); | |
257 | ||
391bb211 | 258 | if (status) { |
30295c89 VM |
259 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, |
260 | ("AR3K Config: failed to set scale and step values: %d \n", status)); | |
261 | break; | |
262 | } | |
263 | ||
264 | AR_DEBUG_PRINTF(ATH_DEBUG_ANY, | |
265 | ("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate)); | |
266 | } | |
267 | ||
1071a134 | 268 | } while (false); |
30295c89 VM |
269 | |
270 | if (pBufferToFree != NULL) { | |
271 | A_FREE(pBufferToFree); | |
272 | } | |
273 | ||
274 | return status; | |
275 | } | |
276 | ||
1f4c34bd | 277 | static int AR3KExitMinBoot(AR3K_CONFIG_INFO *pConfig) |
30295c89 | 278 | { |
1f4c34bd | 279 | int status; |
4c42080f | 280 | char exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00, |
30295c89 | 281 | 0x00,0x00,0x00,0x00,0x00}; |
ab3655da JP |
282 | u8 *pEvent = NULL; |
283 | u8 *pBufferToFree = NULL; | |
30295c89 VM |
284 | |
285 | status = SendHCICommandWaitCommandComplete(pConfig, | |
286 | exitMinBootCmd, | |
287 | sizeof(exitMinBootCmd), | |
288 | &pEvent, | |
289 | &pBufferToFree); | |
290 | ||
509c9d97 | 291 | if (!status) { |
30295c89 VM |
292 | if (pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET] != 0) { |
293 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR, | |
294 | ("AR3K Config: MinBoot exit command event status failed: %d \n", | |
295 | pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET])); | |
296 | status = A_ECOMM; | |
297 | } else { | |
298 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO, | |
299 | ("AR3K Config: MinBoot Exit Command Complete (Success) \n")); | |
300 | A_MDELAY(1); | |
301 | } | |
302 | } else { | |
303 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: MinBoot Exit Failed! \n")); | |
304 | } | |
305 | ||
306 | if (pBufferToFree != NULL) { | |
307 | A_FREE(pBufferToFree); | |
308 | } | |
309 | ||
310 | return status; | |
311 | } | |
312 | ||
1f4c34bd | 313 | static int AR3KConfigureSendHCIReset(AR3K_CONFIG_INFO *pConfig) |
30295c89 | 314 | { |
1f4c34bd | 315 | int status = A_OK; |
ab3655da JP |
316 | u8 hciResetCommand[] = {0x03,0x0c,0x0}; |
317 | u8 *pEvent = NULL; | |
318 | u8 *pBufferToFree = NULL; | |
30295c89 VM |
319 | |
320 | status = SendHCICommandWaitCommandComplete( pConfig, | |
321 | hciResetCommand, | |
322 | sizeof(hciResetCommand), | |
323 | &pEvent, | |
324 | &pBufferToFree ); | |
325 | ||
391bb211 | 326 | if (status) { |
30295c89 VM |
327 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI reset failed! \n")); |
328 | } | |
329 | ||
330 | if (pBufferToFree != NULL) { | |
331 | A_FREE(pBufferToFree); | |
332 | } | |
333 | ||
334 | return status; | |
335 | } | |
336 | ||
1f4c34bd | 337 | static int AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig) |
30295c89 | 338 | { |
1f4c34bd | 339 | int status; |
30295c89 | 340 | /* AR3K vendor specific command for Host Wakeup Config */ |
4c42080f | 341 | char hostWakeupConfig[] = {0x31,0xFC,0x18, |
30295c89 VM |
342 | 0x02,0x00,0x00,0x00, |
343 | 0x01,0x00,0x00,0x00, | |
344 | TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms | |
345 | 0x00,0x00,0x00,0x00, | |
346 | TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms | |
347 | 0x00,0x00,0x00,0x00}; | |
348 | /* AR3K vendor specific command for Target Wakeup Config */ | |
4c42080f | 349 | char targetWakeupConfig[] = {0x31,0xFC,0x18, |
30295c89 VM |
350 | 0x04,0x00,0x00,0x00, |
351 | 0x01,0x00,0x00,0x00, | |
352 | TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms | |
353 | 0x00,0x00,0x00,0x00, | |
354 | TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms | |
355 | 0x00,0x00,0x00,0x00}; | |
356 | /* AR3K vendor specific command for Host Wakeup Enable */ | |
4c42080f | 357 | char hostWakeupEnable[] = {0x31,0xFC,0x4, |
30295c89 VM |
358 | 0x01,0x00,0x00,0x00}; |
359 | /* AR3K vendor specific command for Target Wakeup Enable */ | |
4c42080f | 360 | char targetWakeupEnable[] = {0x31,0xFC,0x4, |
30295c89 VM |
361 | 0x06,0x00,0x00,0x00}; |
362 | /* AR3K vendor specific command for Sleep Enable */ | |
4c42080f | 363 | char sleepEnable[] = {0x4,0xFC,0x1, |
30295c89 | 364 | 0x1}; |
ab3655da JP |
365 | u8 *pEvent = NULL; |
366 | u8 *pBufferToFree = NULL; | |
30295c89 VM |
367 | |
368 | if (0 != pConfig->IdleTimeout) { | |
ab3655da JP |
369 | u8 idle_lsb = pConfig->IdleTimeout & 0xFF; |
370 | u8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8; | |
30295c89 VM |
371 | hostWakeupConfig[11] = targetWakeupConfig[11] = idle_lsb; |
372 | hostWakeupConfig[12] = targetWakeupConfig[12] = idle_msb; | |
373 | } | |
374 | ||
375 | if (0 != pConfig->WakeupTimeout) { | |
376 | hostWakeupConfig[19] = targetWakeupConfig[19] = (pConfig->WakeupTimeout & 0xFF); | |
377 | } | |
378 | ||
379 | status = SendHCICommandWaitCommandComplete(pConfig, | |
380 | hostWakeupConfig, | |
381 | sizeof(hostWakeupConfig), | |
382 | &pEvent, | |
383 | &pBufferToFree); | |
384 | if (pBufferToFree != NULL) { | |
385 | A_FREE(pBufferToFree); | |
386 | } | |
391bb211 | 387 | if (status) { |
30295c89 VM |
388 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Config Failed! \n")); |
389 | return status; | |
390 | } | |
391 | ||
392 | pEvent = NULL; | |
393 | pBufferToFree = NULL; | |
394 | status = SendHCICommandWaitCommandComplete(pConfig, | |
395 | targetWakeupConfig, | |
396 | sizeof(targetWakeupConfig), | |
397 | &pEvent, | |
398 | &pBufferToFree); | |
399 | if (pBufferToFree != NULL) { | |
400 | A_FREE(pBufferToFree); | |
401 | } | |
391bb211 | 402 | if (status) { |
30295c89 VM |
403 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Config Failed! \n")); |
404 | return status; | |
405 | } | |
406 | ||
407 | pEvent = NULL; | |
408 | pBufferToFree = NULL; | |
409 | status = SendHCICommandWaitCommandComplete(pConfig, | |
410 | hostWakeupEnable, | |
411 | sizeof(hostWakeupEnable), | |
412 | &pEvent, | |
413 | &pBufferToFree); | |
414 | if (pBufferToFree != NULL) { | |
415 | A_FREE(pBufferToFree); | |
416 | } | |
391bb211 | 417 | if (status) { |
30295c89 VM |
418 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Enable Failed! \n")); |
419 | return status; | |
420 | } | |
421 | ||
422 | pEvent = NULL; | |
423 | pBufferToFree = NULL; | |
424 | status = SendHCICommandWaitCommandComplete(pConfig, | |
425 | targetWakeupEnable, | |
426 | sizeof(targetWakeupEnable), | |
427 | &pEvent, | |
428 | &pBufferToFree); | |
429 | if (pBufferToFree != NULL) { | |
430 | A_FREE(pBufferToFree); | |
431 | } | |
391bb211 | 432 | if (status) { |
30295c89 VM |
433 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Enable Failed! \n")); |
434 | return status; | |
435 | } | |
436 | ||
437 | pEvent = NULL; | |
438 | pBufferToFree = NULL; | |
439 | status = SendHCICommandWaitCommandComplete(pConfig, | |
440 | sleepEnable, | |
441 | sizeof(sleepEnable), | |
442 | &pEvent, | |
443 | &pBufferToFree); | |
444 | if (pBufferToFree != NULL) { | |
445 | A_FREE(pBufferToFree); | |
446 | } | |
391bb211 | 447 | if (status) { |
30295c89 VM |
448 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Sleep Enable Failed! \n")); |
449 | } | |
450 | ||
451 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Enable TLPM Completed (status = %d) \n",status)); | |
452 | ||
453 | return status; | |
454 | } | |
455 | ||
1f4c34bd | 456 | int AR3KConfigure(AR3K_CONFIG_INFO *pConfig) |
30295c89 | 457 | { |
1f4c34bd | 458 | int status = A_OK; |
30295c89 VM |
459 | |
460 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuring AR3K ...\n")); | |
461 | ||
462 | do { | |
463 | ||
464 | if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) { | |
465 | status = A_EINVAL; | |
466 | break; | |
467 | } | |
468 | ||
469 | /* disable asynchronous recv while we issue commands and receive events synchronously */ | |
1071a134 | 470 | status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false); |
391bb211 | 471 | if (status) { |
30295c89 VM |
472 | break; |
473 | } | |
474 | ||
475 | if (pConfig->Flags & AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT) { | |
476 | status = AR3KExitMinBoot(pConfig); | |
391bb211 | 477 | if (status) { |
30295c89 VM |
478 | break; |
479 | } | |
480 | } | |
481 | ||
482 | ||
483 | /* Load patching and PST file if available*/ | |
484 | if (A_OK != AthPSInitialize(pConfig)) { | |
485 | AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch Download Failed!\n")); | |
486 | } | |
487 | ||
488 | /* Send HCI reset to make PS tags take effect*/ | |
489 | AR3KConfigureSendHCIReset(pConfig); | |
490 | ||
491 | if (pConfig->Flags & | |
492 | (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) { | |
493 | status = AR3KConfigureHCIBaud(pConfig); | |
391bb211 | 494 | if (status) { |
30295c89 VM |
495 | break; |
496 | } | |
497 | } | |
498 | ||
499 | ||
500 | ||
501 | if (pConfig->PwrMgmtEnabled) { | |
502 | /* the delay is required after the previous HCI reset before further | |
503 | * HCI commands can be issued | |
504 | */ | |
505 | A_MDELAY(200); | |
506 | AR3KEnableTLPM(pConfig); | |
507 | } | |
508 | ||
509 | /* re-enable asynchronous recv */ | |
1071a134 | 510 | status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true); |
391bb211 | 511 | if (status) { |
30295c89 VM |
512 | break; |
513 | } | |
514 | ||
515 | ||
1071a134 | 516 | } while (false); |
30295c89 VM |
517 | |
518 | ||
519 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuration Complete (status = %d) \n",status)); | |
520 | ||
521 | return status; | |
522 | } | |
523 | ||
1f4c34bd | 524 | int AR3KConfigureExit(void *config) |
30295c89 | 525 | { |
1f4c34bd | 526 | int status = A_OK; |
30295c89 VM |
527 | AR3K_CONFIG_INFO *pConfig = (AR3K_CONFIG_INFO *)config; |
528 | ||
529 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleaning up AR3K ...\n")); | |
530 | ||
531 | do { | |
532 | ||
533 | if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) { | |
534 | status = A_EINVAL; | |
535 | break; | |
536 | } | |
537 | ||
538 | /* disable asynchronous recv while we issue commands and receive events synchronously */ | |
1071a134 | 539 | status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false); |
391bb211 | 540 | if (status) { |
30295c89 VM |
541 | break; |
542 | } | |
543 | ||
544 | if (pConfig->Flags & | |
545 | (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) { | |
546 | status = AR3KConfigureHCIBaud(pConfig); | |
391bb211 | 547 | if (status) { |
30295c89 VM |
548 | break; |
549 | } | |
550 | } | |
551 | ||
552 | /* re-enable asynchronous recv */ | |
1071a134 | 553 | status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true); |
391bb211 | 554 | if (status) { |
30295c89 VM |
555 | break; |
556 | } | |
557 | ||
558 | ||
1071a134 | 559 | } while (false); |
30295c89 VM |
560 | |
561 | ||
562 | AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleanup Complete (status = %d) \n",status)); | |
563 | ||
564 | return status; | |
565 | } | |
566 |