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 A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
52 A_UINT8 **ppEventBuffer,
53 A_UINT8 **ppBufferToFree);
56 A_UINT32 Build_Version;
59 A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code);
60 A_STATUS 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, A_UINT32 len);
71 #endif /* HCI_TRANSPORT_SDIO */
73 A_STATUS 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,A_UINT32 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 A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev)
96 A_STATUS status = A_OK;
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;
140 A_UINT8 *bufferToFree;
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 = (firmware->size > MAX_BDADDR_FORMAT_LENGTH)? MAX_BDADDR_FORMAT_LENGTH: firmware->size;
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 A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
393 A_UINT8 *pHCICommand,
395 A_UINT8 **ppEventBuffer,
396 A_UINT8 **ppBufferToFree)
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 A_STATUS 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 A_STATUS 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 A_UINT8 *bufferToFree = NULL;
491 A_STATUS 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 A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig)
521 A_UINT8 hciCommand[] = {0x1E,0xfc,0x00};
523 A_UINT8 *bufferToFree = NULL;
524 A_STATUS 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 A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code)
536 A_UINT8 hciCommand[] = {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04};
538 A_UINT8 *bufferToFree = NULL;
540 A_STATUS result = A_ERROR;
542 hciCommand[3] = (A_UINT8)(FPGA_REGISTER & 0xFF);
543 hciCommand[4] = (A_UINT8)((FPGA_REGISTER >> 8) & 0xFF);
544 hciCommand[5] = (A_UINT8)((FPGA_REGISTER >> 16) & 0xFF);
545 hciCommand[6] = (A_UINT8)((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);