1
//------------------------------------------------------------------------------
2
// Copyright (c) 2009-2010 Atheros Corporation. All rights reserved.
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.
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
//==============================================================================
29
#define ATH_MODULE_NAME misc
31
#include "common_drv.h"
32
#ifdef EXPORT_HCI_BRIDGE_INTERFACE
33
#include "export_hci_transport.h"
35
#include "hci_transport_api.h"
37
#include "ar3kconfig.h"
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
50
int AthPSInitialize(struct ar3k_config_info *hdev);
52
static int SendHCICommand(struct ar3k_config_info *pConfig,
56
struct htc_packet *pPacket = NULL;
61
pPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet));
62
if (NULL == pPacket) {
67
A_MEMZERO(pPacket,sizeof(struct htc_packet));
68
SET_HTC_PACKET_INFO_TX(pPacket,
73
AR6K_CONTROL_PKT_TAG);
75
/* issue synchronously */
76
status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,true);
80
if (pPacket != NULL) {
87
static int RecvHCIEvent(struct ar3k_config_info *pConfig,
92
struct htc_packet *pRecvPacket = NULL;
96
pRecvPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet));
97
if (NULL == pRecvPacket) {
99
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n"));
103
A_MEMZERO(pRecvPacket,sizeof(struct htc_packet));
105
SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE);
107
status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev,
109
HCI_EVENT_RESP_TIMEOUTMS);
114
*pLength = pRecvPacket->ActualLength;
118
if (pRecvPacket != NULL) {
125
int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
135
bool commandComplete = false;
140
length = max(HCI_MAX_EVT_RECV_LENGTH,CmdLength);
141
length += pConfig->pHCIProps->HeadRoom + pConfig->pHCIProps->TailRoom;
142
length += pConfig->pHCIProps->IOBlockPad;
144
pBuffer = (u8 *)A_MALLOC(length);
145
if (NULL == pBuffer) {
146
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to allocate bt buffer \n"));
147
status = A_NO_MEMORY;
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];
155
/* copy HCI command */
156
memcpy(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength);
158
status = SendHCICommand(pConfig,
159
pBuffer + pConfig->pHCIProps->HeadRoom,
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");
167
/* reuse buffer to capture command complete event */
168
A_MEMZERO(pBuffer,length);
169
status = RecvHCIEvent(pConfig,pBuffer,&length);
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");
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])) {
180
commandComplete = true;
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");
191
if (ppEventBuffer != NULL) {
192
/* caller wants to look at the event */
193
*ppEventBuffer = pTemp;
194
if (ppBufferToFree == NULL) {
198
/* caller must free the buffer */
199
*ppBufferToFree = pBuffer;
205
if (pBuffer != NULL) {
212
static int AR3KConfigureHCIBaud(struct ar3k_config_info *pConfig)
215
u8 hciBaudChangeCommand[] = {0x0c,0xfc,0x2,0,0};
218
u8 *pBufferToFree = NULL;
222
if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) {
223
baudVal = (u16)(pConfig->AR3KBaudRate / 100);
224
hciBaudChangeCommand[3] = (u8)baudVal;
225
hciBaudChangeCommand[4] = (u8)(baudVal >> 8);
227
status = SendHCICommandWaitCommandComplete(pConfig,
228
hciBaudChangeCommand,
229
sizeof(hciBaudChangeCommand),
233
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n"));
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]));
245
AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
246
("AR3K Config: Baud Changed to %d \n",pConfig->AR3KBaudRate));
249
if (pConfig->Flags & AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY) {
250
/* some versions of AR3K do not switch baud immediately, up to 300MS */
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);
259
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
260
("AR3K Config: failed to set scale and step values: %d \n", status));
264
AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
265
("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate));
270
if (pBufferToFree != NULL) {
271
A_FREE(pBufferToFree);
277
static int AR3KExitMinBoot(struct ar3k_config_info *pConfig)
280
char exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
281
0x00,0x00,0x00,0x00,0x00};
283
u8 *pBufferToFree = NULL;
285
status = SendHCICommandWaitCommandComplete(pConfig,
287
sizeof(exitMinBootCmd),
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]));
298
AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
299
("AR3K Config: MinBoot Exit Command Complete (Success) \n"));
303
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: MinBoot Exit Failed! \n"));
306
if (pBufferToFree != NULL) {
307
A_FREE(pBufferToFree);
313
static int AR3KConfigureSendHCIReset(struct ar3k_config_info *pConfig)
316
u8 hciResetCommand[] = {0x03,0x0c,0x0};
318
u8 *pBufferToFree = NULL;
320
status = SendHCICommandWaitCommandComplete( pConfig,
322
sizeof(hciResetCommand),
327
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI reset failed! \n"));
330
if (pBufferToFree != NULL) {
331
A_FREE(pBufferToFree);
337
static int AR3KEnableTLPM(struct ar3k_config_info *pConfig)
340
/* AR3K vendor specific command for Host Wakeup Config */
341
char hostWakeupConfig[] = {0x31,0xFC,0x18,
344
TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms
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 */
349
char targetWakeupConfig[] = {0x31,0xFC,0x18,
352
TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00, //idle timeout in ms
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 */
357
char hostWakeupEnable[] = {0x31,0xFC,0x4,
358
0x01,0x00,0x00,0x00};
359
/* AR3K vendor specific command for Target Wakeup Enable */
360
char targetWakeupEnable[] = {0x31,0xFC,0x4,
361
0x06,0x00,0x00,0x00};
362
/* AR3K vendor specific command for Sleep Enable */
363
char sleepEnable[] = {0x4,0xFC,0x1,
366
u8 *pBufferToFree = NULL;
368
if (0 != pConfig->IdleTimeout) {
369
u8 idle_lsb = pConfig->IdleTimeout & 0xFF;
370
u8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8;
371
hostWakeupConfig[11] = targetWakeupConfig[11] = idle_lsb;
372
hostWakeupConfig[12] = targetWakeupConfig[12] = idle_msb;
375
if (0 != pConfig->WakeupTimeout) {
376
hostWakeupConfig[19] = targetWakeupConfig[19] = (pConfig->WakeupTimeout & 0xFF);
379
status = SendHCICommandWaitCommandComplete(pConfig,
381
sizeof(hostWakeupConfig),
384
if (pBufferToFree != NULL) {
385
A_FREE(pBufferToFree);
388
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Config Failed! \n"));
393
pBufferToFree = NULL;
394
status = SendHCICommandWaitCommandComplete(pConfig,
396
sizeof(targetWakeupConfig),
399
if (pBufferToFree != NULL) {
400
A_FREE(pBufferToFree);
403
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Config Failed! \n"));
408
pBufferToFree = NULL;
409
status = SendHCICommandWaitCommandComplete(pConfig,
411
sizeof(hostWakeupEnable),
414
if (pBufferToFree != NULL) {
415
A_FREE(pBufferToFree);
418
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Enable Failed! \n"));
423
pBufferToFree = NULL;
424
status = SendHCICommandWaitCommandComplete(pConfig,
426
sizeof(targetWakeupEnable),
429
if (pBufferToFree != NULL) {
430
A_FREE(pBufferToFree);
433
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Enable Failed! \n"));
438
pBufferToFree = NULL;
439
status = SendHCICommandWaitCommandComplete(pConfig,
444
if (pBufferToFree != NULL) {
445
A_FREE(pBufferToFree);
448
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Sleep Enable Failed! \n"));
451
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Enable TLPM Completed (status = %d) \n",status));
456
int AR3KConfigure(struct ar3k_config_info *pConfig)
460
AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuring AR3K ...\n"));
464
if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) {
469
/* disable asynchronous recv while we issue commands and receive events synchronously */
470
status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false);
475
if (pConfig->Flags & AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT) {
476
status = AR3KExitMinBoot(pConfig);
483
/* Load patching and PST file if available*/
484
if (0 != AthPSInitialize(pConfig)) {
485
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch Download Failed!\n"));
488
/* Send HCI reset to make PS tags take effect*/
489
AR3KConfigureSendHCIReset(pConfig);
492
(AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
493
status = AR3KConfigureHCIBaud(pConfig);
501
if (pConfig->PwrMgmtEnabled) {
502
/* the delay is required after the previous HCI reset before further
503
* HCI commands can be issued
506
AR3KEnableTLPM(pConfig);
509
/* re-enable asynchronous recv */
510
status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true);
519
AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuration Complete (status = %d) \n",status));
524
int AR3KConfigureExit(void *config)
527
struct ar3k_config_info *pConfig = (struct ar3k_config_info *)config;
529
AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleaning up AR3K ...\n"));
533
if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) {
538
/* disable asynchronous recv while we issue commands and receive events synchronously */
539
status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false);
545
(AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
546
status = AR3KConfigureHCIBaud(pConfig);
552
/* re-enable asynchronous recv */
553
status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true);
562
AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleanup Complete (status = %d) \n",status));