staging: ath6kl: Convert A_UINT8 to u8
[linux-2.6-block.git] / drivers / staging / ath6kl / miscdrv / ar3kconfig.c
CommitLineData
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 50int AthPSInitialize(AR3K_CONFIG_INFO *hdev);
30295c89 51
1f4c34bd 52static 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 87static 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 125int 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 212static 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 277static 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 313static 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 337static 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 456int 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 524int 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