2 * Copyright (c) 2004-2010 Atheros Communications Inc.
5 * This file implements the Atheros PS and patch downloaded for HCI UART Transport driver.
6 * This file can be used for HCI SDIO transport implementation for AR6002 with HCI_TRANSPORT_SDIO
14 * The software source and binaries included in this development package are
15 * licensed, not sold. You, or your company, received the package under one
16 * or more license agreements. The rights granted to you are specifically
17 * listed in these license agreement(s). All other rights remain with Atheros
18 * Communications, Inc., its subsidiaries, or the respective owner including
19 * those listed on the included copyright notices.. Distribution of any
20 * portion of this package must be in strict compliance with the license
29 #include "ar3kpsconfig.h"
30 #ifndef HCI_TRANSPORT_SDIO
33 #endif /* #ifndef HCI_TRANSPORT_SDIO */
35 #define MAX_FW_PATH_LEN 50
36 #define MAX_BDADDR_FORMAT_LENGTH 30
39 * Structure used to send HCI packet, hci packet length and device info
40 * together as parameter to PSThread.
44 PSCmdPacket
*HciCmdList
;
46 AR3K_CONFIG_INFO
*dev
;
49 int SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO
*pConfig
,
59 int getDeviceType(AR3K_CONFIG_INFO
*pConfig
, u32
*code
);
60 int ReadVersionInfo(AR3K_CONFIG_INFO
*pConfig
);
61 #ifndef HCI_TRANSPORT_SDIO
63 DECLARE_WAIT_QUEUE_HEAD(PsCompleteEvent
);
64 DECLARE_WAIT_QUEUE_HEAD(HciEvent
);
65 A_UCHAR
*HciEventpacket
;
67 wait_queue_t Eventwait
;
69 int PSHciWritepacket(struct hci_dev
*,A_UCHAR
* Data
, u32 len
);
71 #endif /* HCI_TRANSPORT_SDIO */
73 int write_bdaddr(AR3K_CONFIG_INFO
*pConfig
,A_UCHAR
*bdaddr
,int type
);
75 int PSSendOps(void *arg
);
78 void Hci_log(A_UCHAR
* log_string
,A_UCHAR
*data
,u32 len
)
81 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("%s : ",log_string
));
82 for (i
= 0; i
< len
; i
++) {
83 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("0x%02x ", data
[i
]));
85 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("\n...................................\n"));
88 #define Hci_log(string,data,len)
89 #endif /* BT_PS_DEBUG */
94 int AthPSInitialize(AR3K_CONFIG_INFO
*hdev
)
98 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Invalid Device handle received\n"));
102 #ifndef HCI_TRANSPORT_SDIO
103 DECLARE_WAITQUEUE(wait
, current
);
104 #endif /* HCI_TRANSPORT_SDIO */
107 #ifdef HCI_TRANSPORT_SDIO
108 status
= PSSendOps((void*)hdev
);
110 if(InitPSState(hdev
) == -1) {
113 allow_signal(SIGKILL
);
114 add_wait_queue(&PsCompleteEvent
,&wait
);
115 set_current_state(TASK_INTERRUPTIBLE
);
116 if(!kernel_thread(PSSendOps
,(void*)hdev
,CLONE_FS
|CLONE_FILES
|CLONE_SIGHAND
|SIGCHLD
)) {
117 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Kthread Failed\n"));
118 remove_wait_queue(&PsCompleteEvent
,&wait
);
121 wait_event_interruptible(PsCompleteEvent
,(PSTagMode
== false));
122 set_current_state(TASK_RUNNING
);
123 remove_wait_queue(&PsCompleteEvent
,&wait
);
125 #endif /* HCI_TRANSPORT_SDIO */
132 int PSSendOps(void *arg
)
136 PSCmdPacket
*HciCmdList
; /* List storing the commands */
137 const struct firmware
* firmware
;
141 struct hci_dev
*device
;
146 A_UCHAR
*patchFileName
;
147 A_UCHAR
*path
= NULL
;
148 A_UCHAR
*config_path
= NULL
;
149 A_UCHAR config_bdaddr
[MAX_BDADDR_FORMAT_LENGTH
];
150 AR3K_CONFIG_INFO
*hdev
= (AR3K_CONFIG_INFO
*)arg
;
151 struct device
*firmwareDev
= NULL
;
154 #ifdef HCI_TRANSPORT_SDIO
155 device
= hdev
->pBtStackHCIDev
;
156 firmwareDev
= device
->parent
;
159 firmwareDev
= &device
->dev
;
160 AthEnableSyncCommandOp(true);
161 #endif /* HCI_TRANSPORT_SDIO */
162 /* First verify if the controller is an FPGA or ASIC, so depending on the device type the PS file to be written will be different.
165 path
=(A_UCHAR
*)A_MALLOC(MAX_FW_PATH_LEN
);
167 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Malloc failed to allocate %d bytes for path\n", MAX_FW_PATH_LEN
));
170 config_path
= (A_UCHAR
*) A_MALLOC(MAX_FW_PATH_LEN
);
171 if(config_path
== NULL
) {
172 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Malloc failed to allocate %d bytes for config_path\n", MAX_FW_PATH_LEN
));
176 if(A_ERROR
== getDeviceType(hdev
,&DevType
)) {
180 if(A_ERROR
== ReadVersionInfo(hdev
)) {
185 patchFileName
= PATCH_FILE
;
186 snprintf(path
, MAX_FW_PATH_LEN
, "%s/%xcoex/",CONFIG_PATH
,Rom_Version
);
188 if(DevType
== 0xdeadc0de){
189 PsFileName
= PS_ASIC_FILE
;
191 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,(" FPGA Test Image : %x %x \n",Rom_Version
,Build_Version
));
192 if((Rom_Version
== 0x99999999) && (Build_Version
== 1)){
194 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("FPGA Test Image : Skipping Patch File load\n"));
195 patchFileName
= NULL
;
197 PsFileName
= PS_FPGA_FILE
;
201 PsFileName
= PS_ASIC_FILE
;
204 snprintf(config_path
, MAX_FW_PATH_LEN
, "%s%s",path
,PsFileName
);
205 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("%x: FPGA/ASIC PS File Name %s\n", DevType
,config_path
));
206 /* Read the PS file to a dynamically allocated buffer */
207 if(A_REQUEST_FIRMWARE(&firmware
,config_path
,firmwareDev
) < 0) {
208 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("%s: firmware file open error\n", __FUNCTION__
));
213 if(NULL
== firmware
|| firmware
->size
== 0) {
217 buffer
= (A_UCHAR
*)A_MALLOC(firmware
->size
);
219 /* Copy the read file to a local Dynamic buffer */
220 memcpy(buffer
,firmware
->data
,firmware
->size
);
221 len
= firmware
->size
;
222 A_RELEASE_FIRMWARE(firmware
);
223 /* Parse the PS buffer to a global variable */
224 status
= AthDoParsePS(buffer
,len
);
227 A_RELEASE_FIRMWARE(firmware
);
231 /* Read the patch file to a dynamically allocated buffer */
232 if(patchFileName
!= NULL
)
233 snprintf(config_path
,
234 MAX_FW_PATH_LEN
, "%s%s",path
,patchFileName
);
238 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Patch File Name %s\n", config_path
));
239 if((patchFileName
== NULL
) || (A_REQUEST_FIRMWARE(&firmware
,config_path
,firmwareDev
) < 0)) {
240 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("%s: firmware file open error\n", __FUNCTION__
));
242 * It is not necessary that Patch file be available, continue with PS Operations if.
248 if(NULL
== firmware
|| firmware
->size
== 0) {
251 buffer
= (A_UCHAR
*)A_MALLOC(firmware
->size
);
253 /* Copy the read file to a local Dynamic buffer */
254 memcpy(buffer
,firmware
->data
,firmware
->size
);
255 len
= firmware
->size
;
256 A_RELEASE_FIRMWARE(firmware
);
257 /* parse and store the Patch file contents to a global variables */
258 status
= AthDoParsePatch(buffer
,len
);
261 A_RELEASE_FIRMWARE(firmware
);
266 /* Create an HCI command list from the parsed PS and patch information */
267 AthCreateCommandList(&HciCmdList
,&numCmds
);
269 /* Form the parameter for PSSendOps() API */
273 * First Send the CRC packet,
274 * We have to continue with the PS operations only if the CRC packet has been replied with
275 * a Command complete event with status Error.
278 if(SendHCICommandWaitCommandComplete
280 HciCmdList
[0].Hcipacket
,
281 HciCmdList
[0].packetLen
,
283 &bufferToFree
) == A_OK
) {
284 if(ReadPSEvent(event
) == A_OK
) { /* Exit if the status is success */
285 if(bufferToFree
!= NULL
) {
286 A_FREE(bufferToFree
);
289 #ifndef HCI_TRANSPORT_SDIO
290 if(bdaddr
&& bdaddr
[0] !='\0') {
291 write_bdaddr(hdev
,bdaddr
,BDADDR_TYPE_STRING
);
297 if(bufferToFree
!= NULL
) {
298 A_FREE(bufferToFree
);
305 for(i
= 1; i
<numCmds
; i
++) {
307 if(SendHCICommandWaitCommandComplete
309 HciCmdList
[i
].Hcipacket
,
310 HciCmdList
[i
].packetLen
,
312 &bufferToFree
) == A_OK
) {
313 if(ReadPSEvent(event
) != A_OK
) { /* Exit if the status is success */
314 if(bufferToFree
!= NULL
) {
315 A_FREE(bufferToFree
);
320 if(bufferToFree
!= NULL
) {
321 A_FREE(bufferToFree
);
328 #ifdef HCI_TRANSPORT_SDIO
330 if(hdev
->bdaddr
[0] !=0x00 ||
331 hdev
->bdaddr
[1] !=0x00 ||
332 hdev
->bdaddr
[2] !=0x00 ||
333 hdev
->bdaddr
[3] !=0x00 ||
334 hdev
->bdaddr
[4] !=0x00 ||
335 hdev
->bdaddr
[5] !=0x00)
336 write_bdaddr(hdev
,hdev
->bdaddr
,BDADDR_TYPE_HEX
);
338 #ifndef HCI_TRANSPORT_SDIO
340 if(bdaddr
&& bdaddr
[0] != '\0') {
341 write_bdaddr(hdev
,bdaddr
,BDADDR_TYPE_STRING
);
343 #endif /* HCI_TRANSPORT_SDIO */
344 /* Write BDADDR Read from OTP here */
351 /* Read Contents of BDADDR file if user has not provided any option */
352 snprintf(config_path
,MAX_FW_PATH_LEN
, "%s%s",path
,BDADDR_FILE
);
353 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Patch File Name %s\n", config_path
));
354 if(A_REQUEST_FIRMWARE(&firmware
,config_path
,firmwareDev
) < 0) {
355 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("%s: firmware file open error\n", __FUNCTION__
));
359 if(NULL
== firmware
|| firmware
->size
== 0) {
363 len
= min(firmware
->size
, MAX_BDADDR_FORMAT_LENGTH
- 1);
364 memcpy(config_bdaddr
, firmware
->data
, len
);
365 config_bdaddr
[len
] = '\0';
366 write_bdaddr(hdev
,config_bdaddr
,BDADDR_TYPE_STRING
);
367 A_RELEASE_FIRMWARE(firmware
);
370 #ifndef HCI_TRANSPORT_SDIO
371 AthEnableSyncCommandOp(false);
373 wake_up_interruptible(&PsCompleteEvent
);
374 #endif /* HCI_TRANSPORT_SDIO */
375 if(NULL
!= HciCmdList
) {
376 AthFreeCommandList(&HciCmdList
,numCmds
);
386 #ifndef HCI_TRANSPORT_SDIO
388 * This API is used to send the HCI command to controller and return
389 * with a HCI Command Complete event.
390 * For HCI SDIO transport, this will be internally defined.
392 int SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO
*pConfig
,
401 Hci_log("COM Write -->",pHCICommand
,CmdLength
);
403 if(PSHciWritepacket(pConfig
,pHCICommand
,CmdLength
) == 0) {
404 /* If the controller is not available, return Error */
407 //add_timer(&psCmdTimer);
408 wait_event_interruptible(HciEvent
,(PSAcked
== true));
409 if(NULL
!= HciEventpacket
) {
410 *ppEventBuffer
= HciEventpacket
;
411 *ppBufferToFree
= HciEventpacket
;
413 /* Did not get an event from controller. return error */
414 *ppBufferToFree
= NULL
;
420 #endif /* HCI_TRANSPORT_SDIO */
422 int ReadPSEvent(A_UCHAR
* Data
){
423 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,(" PS Event %x %x %x\n",Data
[4],Data
[5],Data
[3]));
425 if(Data
[4] == 0xFC && Data
[5] == 0x00)
432 /* Change Baudrate */
439 Rom_Version
= Data
[9];
440 Rom_Version
= ((Rom_Version
<< 8) |Data
[8]);
441 Rom_Version
= ((Rom_Version
<< 8) |Data
[7]);
442 Rom_Version
= ((Rom_Version
<< 8) |Data
[6]);
444 Build_Version
= Data
[13];
445 Build_Version
= ((Build_Version
<< 8) |Data
[12]);
446 Build_Version
= ((Build_Version
<< 8) |Data
[11]);
447 Build_Version
= ((Build_Version
<< 8) |Data
[10]);
457 int str2ba(unsigned char *str_bdaddr
,unsigned char *bdaddr
)
459 unsigned char bdbyte
[3];
460 unsigned char *str_byte
= str_bdaddr
;
462 unsigned char colon_present
= 0;
464 if(NULL
!= strstr(str_bdaddr
,":")) {
471 for( i
= 0,j
= 5; i
< 6; i
++, j
--) {
472 bdbyte
[0] = str_byte
[0];
473 bdbyte
[1] = str_byte
[1];
474 bdaddr
[j
] = A_STRTOL(bdbyte
,NULL
,16);
475 if(colon_present
== 1) {
484 int write_bdaddr(AR3K_CONFIG_INFO
*pConfig
,A_UCHAR
*bdaddr
,int type
)
486 A_UCHAR bdaddr_cmd
[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01,
487 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
490 u8
*bufferToFree
= NULL
;
491 int result
= A_ERROR
;
494 if (type
== BDADDR_TYPE_STRING
)
495 str2ba(bdaddr
,&bdaddr_cmd
[7]);
497 /* Bdaddr has to be sent as LAP first */
498 for(inc
= 5 ,outc
= 7; inc
>=0; inc
--, outc
++)
499 bdaddr_cmd
[outc
] = bdaddr
[inc
];
502 if(A_OK
== SendHCICommandWaitCommandComplete(pConfig
,bdaddr_cmd
,
504 &event
,&bufferToFree
)) {
506 if(event
[4] == 0xFC && event
[5] == 0x00){
507 if(event
[3] == 0x0B){
513 if(bufferToFree
!= NULL
) {
514 A_FREE(bufferToFree
);
519 int ReadVersionInfo(AR3K_CONFIG_INFO
*pConfig
)
521 u8 hciCommand
[] = {0x1E,0xfc,0x00};
523 u8
*bufferToFree
= NULL
;
524 int result
= A_ERROR
;
525 if(A_OK
== SendHCICommandWaitCommandComplete(pConfig
,hciCommand
,sizeof(hciCommand
),&event
,&bufferToFree
)) {
526 result
= ReadPSEvent(event
);
529 if(bufferToFree
!= NULL
) {
530 A_FREE(bufferToFree
);
534 int getDeviceType(AR3K_CONFIG_INFO
*pConfig
, u32
*code
)
536 u8 hciCommand
[] = {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04};
538 u8
*bufferToFree
= NULL
;
540 int result
= A_ERROR
;
542 hciCommand
[3] = (u8
)(FPGA_REGISTER
& 0xFF);
543 hciCommand
[4] = (u8
)((FPGA_REGISTER
>> 8) & 0xFF);
544 hciCommand
[5] = (u8
)((FPGA_REGISTER
>> 16) & 0xFF);
545 hciCommand
[6] = (u8
)((FPGA_REGISTER
>> 24) & 0xFF);
546 if(A_OK
== SendHCICommandWaitCommandComplete(pConfig
,hciCommand
,sizeof(hciCommand
),&event
,&bufferToFree
)) {
548 if(event
[4] == 0xFC && event
[5] == 0x00){
552 reg
= ((reg
<< 8) |event
[8]);
553 reg
= ((reg
<< 8) |event
[7]);
554 reg
= ((reg
<< 8) |event
[6]);
566 if(bufferToFree
!= NULL
) {
567 A_FREE(bufferToFree
);