tty/serial: atmel_serial: whitespace and braces modifications
[zen-stable.git] / drivers / staging / ath6kl / miscdrv / ar3kconfig.c
blobe0ea2183019dd9a0d03d67791f49bbcd3a50e4f8
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.
18 //------------------------------------------------------------------------------
19 //==============================================================================
20 // AR3K configuration implementation
22 // Author(s): ="Atheros"
23 //==============================================================================
25 #include "a_config.h"
26 #include "athdefs.h"
27 #include "a_osapi.h"
28 #define ATH_MODULE_NAME misc
29 #include "a_debug.h"
30 #include "common_drv.h"
31 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
32 #include "export_hci_transport.h"
33 #else
34 #include "hci_transport_api.h"
35 #endif
36 #include "ar3kconfig.h"
37 #include "tlpm.h"
39 #define BAUD_CHANGE_COMMAND_STATUS_OFFSET 5
40 #define HCI_EVENT_RESP_TIMEOUTMS 3000
41 #define HCI_CMD_OPCODE_BYTE_LOW_OFFSET 0
42 #define HCI_CMD_OPCODE_BYTE_HI_OFFSET 1
43 #define HCI_EVENT_OPCODE_BYTE_LOW 3
44 #define HCI_EVENT_OPCODE_BYTE_HI 4
45 #define HCI_CMD_COMPLETE_EVENT_CODE 0xE
46 #define HCI_MAX_EVT_RECV_LENGTH 257
47 #define EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET 5
49 int AthPSInitialize(struct ar3k_config_info *hdev);
51 static int SendHCICommand(struct ar3k_config_info *pConfig,
52 u8 *pBuffer,
53 int Length)
55 struct htc_packet *pPacket = NULL;
56 int status = 0;
58 do {
60 pPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet));
61 if (NULL == pPacket) {
62 status = A_NO_MEMORY;
63 break;
66 A_MEMZERO(pPacket,sizeof(struct htc_packet));
67 SET_HTC_PACKET_INFO_TX(pPacket,
68 NULL,
69 pBuffer,
70 Length,
71 HCI_COMMAND_TYPE,
72 AR6K_CONTROL_PKT_TAG);
74 /* issue synchronously */
75 status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,true);
77 } while (false);
79 if (pPacket != NULL) {
80 kfree(pPacket);
83 return status;
86 static int RecvHCIEvent(struct ar3k_config_info *pConfig,
87 u8 *pBuffer,
88 int *pLength)
90 int status = 0;
91 struct htc_packet *pRecvPacket = NULL;
93 do {
95 pRecvPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet));
96 if (NULL == pRecvPacket) {
97 status = A_NO_MEMORY;
98 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n"));
99 break;
102 A_MEMZERO(pRecvPacket,sizeof(struct htc_packet));
104 SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE);
106 status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev,
107 pRecvPacket,
108 HCI_EVENT_RESP_TIMEOUTMS);
109 if (status) {
110 break;
113 *pLength = pRecvPacket->ActualLength;
115 } while (false);
117 if (pRecvPacket != NULL) {
118 kfree(pRecvPacket);
121 return status;
124 int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
125 u8 *pHCICommand,
126 int CmdLength,
127 u8 **ppEventBuffer,
128 u8 **ppBufferToFree)
130 int status = 0;
131 u8 *pBuffer = NULL;
132 u8 *pTemp;
133 int length;
134 bool commandComplete = false;
135 u8 opCodeBytes[2];
137 do {
139 length = max(HCI_MAX_EVT_RECV_LENGTH,CmdLength);
140 length += pConfig->pHCIProps->HeadRoom + pConfig->pHCIProps->TailRoom;
141 length += pConfig->pHCIProps->IOBlockPad;
143 pBuffer = (u8 *)A_MALLOC(length);
144 if (NULL == pBuffer) {
145 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to allocate bt buffer \n"));
146 status = A_NO_MEMORY;
147 break;
150 /* get the opcodes to check the command complete event */
151 opCodeBytes[0] = pHCICommand[HCI_CMD_OPCODE_BYTE_LOW_OFFSET];
152 opCodeBytes[1] = pHCICommand[HCI_CMD_OPCODE_BYTE_HI_OFFSET];
154 /* copy HCI command */
155 memcpy(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength);
156 /* send command */
157 status = SendHCICommand(pConfig,
158 pBuffer + pConfig->pHCIProps->HeadRoom,
159 CmdLength);
160 if (status) {
161 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to send HCI Command (%d) \n", status));
162 AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
163 break;
166 /* reuse buffer to capture command complete event */
167 A_MEMZERO(pBuffer,length);
168 status = RecvHCIEvent(pConfig,pBuffer,&length);
169 if (status) {
170 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI event recv failed \n"));
171 AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
172 break;
175 pTemp = pBuffer + pConfig->pHCIProps->HeadRoom;
176 if (pTemp[0] == HCI_CMD_COMPLETE_EVENT_CODE) {
177 if ((pTemp[HCI_EVENT_OPCODE_BYTE_LOW] == opCodeBytes[0]) &&
178 (pTemp[HCI_EVENT_OPCODE_BYTE_HI] == opCodeBytes[1])) {
179 commandComplete = true;
183 if (!commandComplete) {
184 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Unexpected HCI event : %d \n",pTemp[0]));
185 AR_DEBUG_PRINTBUF(pTemp,pTemp[1],"Unexpected HCI event");
186 status = A_ECOMM;
187 break;
190 if (ppEventBuffer != NULL) {
191 /* caller wants to look at the event */
192 *ppEventBuffer = pTemp;
193 if (ppBufferToFree == NULL) {
194 status = A_EINVAL;
195 break;
197 /* caller must free the buffer */
198 *ppBufferToFree = pBuffer;
199 pBuffer = NULL;
202 } while (false);
204 if (pBuffer != NULL) {
205 kfree(pBuffer);
208 return status;
211 static int AR3KConfigureHCIBaud(struct ar3k_config_info *pConfig)
213 int status = 0;
214 u8 hciBaudChangeCommand[] = {0x0c,0xfc,0x2,0,0};
215 u16 baudVal;
216 u8 *pEvent = NULL;
217 u8 *pBufferToFree = NULL;
219 do {
221 if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) {
222 baudVal = (u16)(pConfig->AR3KBaudRate / 100);
223 hciBaudChangeCommand[3] = (u8)baudVal;
224 hciBaudChangeCommand[4] = (u8)(baudVal >> 8);
226 status = SendHCICommandWaitCommandComplete(pConfig,
227 hciBaudChangeCommand,
228 sizeof(hciBaudChangeCommand),
229 &pEvent,
230 &pBufferToFree);
231 if (status) {
232 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n"));
233 break;
236 if (pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET] != 0) {
237 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
238 ("AR3K Config: Baud change command event status failed: %d \n",
239 pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET]));
240 status = A_ECOMM;
241 break;
244 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
245 ("AR3K Config: Baud Changed to %d \n",pConfig->AR3KBaudRate));
248 if (pConfig->Flags & AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY) {
249 /* some versions of AR3K do not switch baud immediately, up to 300MS */
250 A_MDELAY(325);
253 if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP) {
254 /* Tell target to change UART baud rate for AR6K */
255 status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate);
257 if (status) {
258 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
259 ("AR3K Config: failed to set scale and step values: %d \n", status));
260 break;
263 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
264 ("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate));
267 } while (false);
269 if (pBufferToFree != NULL) {
270 kfree(pBufferToFree);
273 return status;
276 static int AR3KExitMinBoot(struct ar3k_config_info *pConfig)
278 int status;
279 char exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
280 0x00,0x00,0x00,0x00,0x00};
281 u8 *pEvent = NULL;
282 u8 *pBufferToFree = NULL;
284 status = SendHCICommandWaitCommandComplete(pConfig,
285 exitMinBootCmd,
286 sizeof(exitMinBootCmd),
287 &pEvent,
288 &pBufferToFree);
290 if (!status) {
291 if (pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET] != 0) {
292 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
293 ("AR3K Config: MinBoot exit command event status failed: %d \n",
294 pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET]));
295 status = A_ECOMM;
296 } else {
297 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
298 ("AR3K Config: MinBoot Exit Command Complete (Success) \n"));
299 A_MDELAY(1);
301 } else {
302 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: MinBoot Exit Failed! \n"));
305 if (pBufferToFree != NULL) {
306 kfree(pBufferToFree);
309 return status;
312 static int AR3KConfigureSendHCIReset(struct ar3k_config_info *pConfig)
314 int status = 0;
315 u8 hciResetCommand[] = {0x03,0x0c,0x0};
316 u8 *pEvent = NULL;
317 u8 *pBufferToFree = NULL;
319 status = SendHCICommandWaitCommandComplete( pConfig,
320 hciResetCommand,
321 sizeof(hciResetCommand),
322 &pEvent,
323 &pBufferToFree );
325 if (status) {
326 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI reset failed! \n"));
329 if (pBufferToFree != NULL) {
330 kfree(pBufferToFree);
333 return status;
336 static int AR3KEnableTLPM(struct ar3k_config_info *pConfig)
338 int status;
339 /* AR3K vendor specific command for Host Wakeup Config */
340 char hostWakeupConfig[] = {0x31,0xFC,0x18,
341 0x02,0x00,0x00,0x00,
342 0x01,0x00,0x00,0x00,
343 TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms
344 0x00,0x00,0x00,0x00,
345 TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms
346 0x00,0x00,0x00,0x00};
347 /* AR3K vendor specific command for Target Wakeup Config */
348 char targetWakeupConfig[] = {0x31,0xFC,0x18,
349 0x04,0x00,0x00,0x00,
350 0x01,0x00,0x00,0x00,
351 TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms
352 0x00,0x00,0x00,0x00,
353 TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00, //wakeup timeout in ms
354 0x00,0x00,0x00,0x00};
355 /* AR3K vendor specific command for Host Wakeup Enable */
356 char hostWakeupEnable[] = {0x31,0xFC,0x4,
357 0x01,0x00,0x00,0x00};
358 /* AR3K vendor specific command for Target Wakeup Enable */
359 char targetWakeupEnable[] = {0x31,0xFC,0x4,
360 0x06,0x00,0x00,0x00};
361 /* AR3K vendor specific command for Sleep Enable */
362 char sleepEnable[] = {0x4,0xFC,0x1,
363 0x1};
364 u8 *pEvent = NULL;
365 u8 *pBufferToFree = NULL;
367 if (0 != pConfig->IdleTimeout) {
368 u8 idle_lsb = pConfig->IdleTimeout & 0xFF;
369 u8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8;
370 hostWakeupConfig[11] = targetWakeupConfig[11] = idle_lsb;
371 hostWakeupConfig[12] = targetWakeupConfig[12] = idle_msb;
374 if (0 != pConfig->WakeupTimeout) {
375 hostWakeupConfig[19] = targetWakeupConfig[19] = (pConfig->WakeupTimeout & 0xFF);
378 status = SendHCICommandWaitCommandComplete(pConfig,
379 hostWakeupConfig,
380 sizeof(hostWakeupConfig),
381 &pEvent,
382 &pBufferToFree);
383 if (pBufferToFree != NULL) {
384 kfree(pBufferToFree);
386 if (status) {
387 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Config Failed! \n"));
388 return status;
391 pEvent = NULL;
392 pBufferToFree = NULL;
393 status = SendHCICommandWaitCommandComplete(pConfig,
394 targetWakeupConfig,
395 sizeof(targetWakeupConfig),
396 &pEvent,
397 &pBufferToFree);
398 if (pBufferToFree != NULL) {
399 kfree(pBufferToFree);
401 if (status) {
402 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Config Failed! \n"));
403 return status;
406 pEvent = NULL;
407 pBufferToFree = NULL;
408 status = SendHCICommandWaitCommandComplete(pConfig,
409 hostWakeupEnable,
410 sizeof(hostWakeupEnable),
411 &pEvent,
412 &pBufferToFree);
413 if (pBufferToFree != NULL) {
414 kfree(pBufferToFree);
416 if (status) {
417 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Enable Failed! \n"));
418 return status;
421 pEvent = NULL;
422 pBufferToFree = NULL;
423 status = SendHCICommandWaitCommandComplete(pConfig,
424 targetWakeupEnable,
425 sizeof(targetWakeupEnable),
426 &pEvent,
427 &pBufferToFree);
428 if (pBufferToFree != NULL) {
429 kfree(pBufferToFree);
431 if (status) {
432 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Enable Failed! \n"));
433 return status;
436 pEvent = NULL;
437 pBufferToFree = NULL;
438 status = SendHCICommandWaitCommandComplete(pConfig,
439 sleepEnable,
440 sizeof(sleepEnable),
441 &pEvent,
442 &pBufferToFree);
443 if (pBufferToFree != NULL) {
444 kfree(pBufferToFree);
446 if (status) {
447 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Sleep Enable Failed! \n"));
450 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Enable TLPM Completed (status = %d) \n",status));
452 return status;
455 int AR3KConfigure(struct ar3k_config_info *pConfig)
457 int status = 0;
459 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuring AR3K ...\n"));
461 do {
463 if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) {
464 status = A_EINVAL;
465 break;
468 /* disable asynchronous recv while we issue commands and receive events synchronously */
469 status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false);
470 if (status) {
471 break;
474 if (pConfig->Flags & AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT) {
475 status = AR3KExitMinBoot(pConfig);
476 if (status) {
477 break;
482 /* Load patching and PST file if available*/
483 if (0 != AthPSInitialize(pConfig)) {
484 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch Download Failed!\n"));
487 /* Send HCI reset to make PS tags take effect*/
488 AR3KConfigureSendHCIReset(pConfig);
490 if (pConfig->Flags &
491 (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
492 status = AR3KConfigureHCIBaud(pConfig);
493 if (status) {
494 break;
500 if (pConfig->PwrMgmtEnabled) {
501 /* the delay is required after the previous HCI reset before further
502 * HCI commands can be issued
504 A_MDELAY(200);
505 AR3KEnableTLPM(pConfig);
508 /* re-enable asynchronous recv */
509 status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true);
510 if (status) {
511 break;
515 } while (false);
518 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuration Complete (status = %d) \n",status));
520 return status;
523 int AR3KConfigureExit(void *config)
525 int status = 0;
526 struct ar3k_config_info *pConfig = (struct ar3k_config_info *)config;
528 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleaning up AR3K ...\n"));
530 do {
532 if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) {
533 status = A_EINVAL;
534 break;
537 /* disable asynchronous recv while we issue commands and receive events synchronously */
538 status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false);
539 if (status) {
540 break;
543 if (pConfig->Flags &
544 (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
545 status = AR3KConfigureHCIBaud(pConfig);
546 if (status) {
547 break;
551 /* re-enable asynchronous recv */
552 status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true);
553 if (status) {
554 break;
558 } while (false);
561 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleanup Complete (status = %d) \n",status));
563 return status;