diff options
author | Roshni Shah <shah.roshni@yahoo.com> | 2011-03-14 06:49:42 -0400 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2012-03-02 16:59:46 -0500 |
commit | 2731b2eadeaa141e6f305fa8086106608112bbaa (patch) | |
tree | 2702d45bac84073cd580ccb1bd3eafb9a000d3b6 /drivers/net/wireless/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c | |
parent | 6d23f5084c975be637f7d748db82116bf84d3872 (diff) |
Add support for the i.MX53 QSB2.6.35.3-mx53-early-201103141049
This patch seems to have originated from the 11.01.00 release
from Freescale, which is no longer available except through the
gitweb interface from Freescale.
http://opensource.freescale.com/git?p=imx/linux-2.6-imx.git;a=commit;h=27fdf7bae11978d21e8aba09bb635f49b07edd4a
Diffstat (limited to 'drivers/net/wireless/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c')
-rw-r--r-- | drivers/net/wireless/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c | 506 |
1 files changed, 506 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c b/drivers/net/wireless/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c new file mode 100644 index 000000000000..d4048c8efd0c --- /dev/null +++ b/drivers/net/wireless/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2004-2008 Atheros Communications Inc. + * All rights reserved. + * + * This file implements the Atheros PS and patch downloaded for HCI UART Transport driver. + * This file can be used for HCI SDIO transport implementation for AR6002 with HCI_TRANSPORT_SDIO + * defined. + * + * + * ar3kcpsconfig.c + * + * + * + * The software source and binaries included in this development package are + * licensed, not sold. You, or your company, received the package under one + * or more license agreements. The rights granted to you are specifically + * listed in these license agreement(s). All other rights remain with Atheros + * Communications, Inc., its subsidiaries, or the respective owner including + * those listed on the included copyright notices.. Distribution of any + * portion of this package must be in strict compliance with the license + * agreement(s) terms. + * + * + * + */ + + + +#include "ar3kpsconfig.h" +#ifndef HCI_TRANSPORT_SDIO +#include "hci_ath.h" +#include "hci_uart.h" +#endif /* #ifndef HCI_TRANSPORT_SDIO */ + +/* + * Structure used to send HCI packet, hci packet length and device info + * together as parameter to PSThread. + */ +typedef struct { + + PSCmdPacket *HciCmdList; + A_UINT32 num_packets; + AR3K_CONFIG_INFO *dev; +}HciCommandListParam; + +A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig, + A_UINT8 *pHCICommand, + int CmdLength, + A_UINT8 **ppEventBuffer, + A_UINT8 **ppBufferToFree); + +A_UINT32 Rom_Version; +A_UINT32 Build_Version; + +A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code); +A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig); +#ifndef HCI_TRANSPORT_SDIO + +DECLARE_WAIT_QUEUE_HEAD(PsCompleteEvent); +DECLARE_WAIT_QUEUE_HEAD(HciEvent); +A_UCHAR *HciEventpacket; +rwlock_t syncLock; +wait_queue_t Eventwait; + +int PSHciWritepacket(struct hci_dev*,A_UCHAR* Data, A_UINT32 len); +extern char *bdaddr; +#endif /* HCI_TRANSPORT_SDIO */ + +A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr); + +int PSSendOps(void *arg); + +#ifdef BT_PS_DEBUG +void Hci_log(A_UCHAR * log_string,A_UCHAR *data,A_UINT32 len) +{ + int i; + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s : ",log_string)); + for (i = 0; i < len; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("0x%02x ", data[i])); + } + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n...................................\n")); +} +#else +#define Hci_log(string,data,len) +#endif /* BT_PS_DEBUG */ + + + + +A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev) +{ + A_STATUS status = A_OK; + if(hdev == NULL) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Device handle received\n")); + return A_ERROR; + } + +#ifndef HCI_TRANSPORT_SDIO + DECLARE_WAITQUEUE(wait, current); +#endif /* HCI_TRANSPORT_SDIO */ + + +#ifdef HCI_TRANSPORT_SDIO + status = PSSendOps((void*)hdev); +#else + if(InitPSState(hdev) == -1) { + return A_ERROR; + } + allow_signal(SIGKILL); + add_wait_queue(&PsCompleteEvent,&wait); + set_current_state(TASK_INTERRUPTIBLE); + if(!kernel_thread(PSSendOps,(void*)hdev,CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Kthread Failed\n")); + remove_wait_queue(&PsCompleteEvent,&wait); + return A_ERROR; + } + wait_event_interruptible(PsCompleteEvent,(PSTagMode == FALSE)); + set_current_state(TASK_RUNNING); + remove_wait_queue(&PsCompleteEvent,&wait); + +#endif /* HCI_TRANSPORT_SDIO */ + + + return status; + +} + +int PSSendOps(void *arg) +{ + int i; + int status = 0; + PSCmdPacket *HciCmdList; /* List storing the commands */ + const struct firmware* firmware; + A_UINT32 numCmds; + A_UINT8 *event; + A_UINT8 *bufferToFree; + struct hci_dev *device; + A_UCHAR *buffer; + A_UINT32 len; + A_UINT32 DevType; + A_UCHAR *PsFileName; + A_UCHAR *patchFileName; + AR3K_CONFIG_INFO *hdev = (AR3K_CONFIG_INFO*)arg; + struct device *firmwareDev = NULL; + status = 0; + HciCmdList = NULL; +#ifdef HCI_TRANSPORT_SDIO + device = hdev->pBtStackHCIDev; + firmwareDev = device->parent; +#else + device = hdev; + firmwareDev = &device->dev; + AthEnableSyncCommandOp(TRUE); +#endif /* HCI_TRANSPORT_SDIO */ + /* 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. + */ + if(A_ERROR == getDeviceType(hdev,&DevType)) { + status = 1; + goto complete; + } + if(A_ERROR == ReadVersionInfo(hdev)) { + status = 1; + goto complete; + } + patchFileName = PATCH_FILE; + if(DevType){ + if(DevType == 0xdeadc0de){ + PsFileName = PS_ASIC_FILE; + } else{ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" FPGA Test Image : %x %x \n",Rom_Version,Build_Version)); + if((Rom_Version == 0x99999999) && (Build_Version == 1)){ + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("FPGA Test Image : Skipping Patch File load\n")); + patchFileName = NULL; + } + PsFileName = PS_FPGA_FILE; + } + } + else{ + PsFileName = PS_ASIC_FILE; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%x: FPGA/ASIC PS File Name %s\n", DevType,PsFileName)); + /* Read the PS file to a dynamically allocated buffer */ + if(request_firmware(&firmware,PsFileName,firmwareDev) < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); + status = 1; + goto complete; + + } + if(NULL == firmware || firmware->size == 0) { + status = 1; + goto complete; + } + buffer = (A_UCHAR *)A_MALLOC(firmware->size); + if(buffer != NULL) { + /* Copy the read file to a local Dynamic buffer */ + memcpy(buffer,firmware->data,firmware->size); + len = firmware->size; + release_firmware(firmware); + /* Parse the PS buffer to a global variable */ + status = AthDoParsePS(buffer,len); + A_FREE(buffer); + } else { + release_firmware(firmware); + } + + + /* Read the patch file to a dynamically allocated buffer */ + if((patchFileName == NULL) || (request_firmware(&firmware,patchFileName,firmwareDev) < 0)) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); + /* + * It is not necessary that Patch file be available, continue with PS Operations if. + * failed. + */ + status = 0; + + } else { + if(NULL == firmware || firmware->size == 0) { + status = 0; + } else { + buffer = (A_UCHAR *)A_MALLOC(firmware->size); + if(buffer != NULL) { + /* Copy the read file to a local Dynamic buffer */ + memcpy(buffer,firmware->data,firmware->size); + len = firmware->size; + release_firmware(firmware); + /* parse and store the Patch file contents to a global variables */ + status = AthDoParsePatch(buffer,len); + A_FREE(buffer); + } else { + release_firmware(firmware); + } + } + } + + /* Create an HCI command list from the parsed PS and patch information */ + AthCreateCommandList(&HciCmdList,&numCmds); + + /* Form the parameter for PSSendOps() API */ + + + /* + * First Send the CRC packet, + * We have to continue with the PS operations only if the CRC packet has been replied with + * a Command complete event with status Error. + */ + + if(SendHCICommandWaitCommandComplete + (hdev, + HciCmdList[0].Hcipacket, + HciCmdList[0].packetLen, + &event, + &bufferToFree) == A_OK) { + if(ReadPSEvent(event) == A_OK) { /* Exit if the status is success */ + if(bufferToFree != NULL) { + A_FREE(bufferToFree); + } +#ifndef HCI_TRANSPORT_SDIO + if(bdaddr[0] !='\0') { + write_bdaddr(hdev,bdaddr); + } +#endif + status = 1; + goto complete; + } + if(bufferToFree != NULL) { + A_FREE(bufferToFree); + } + } else { + status = 0; + goto complete; + } + + for(i = 1; i <numCmds; i++) { + + if(SendHCICommandWaitCommandComplete + (hdev, + HciCmdList[i].Hcipacket, + HciCmdList[i].packetLen, + &event, + &bufferToFree) == A_OK) { + if(ReadPSEvent(event) != A_OK) { /* Exit if the status is success */ + if(bufferToFree != NULL) { + A_FREE(bufferToFree); + } + status = 1; + goto complete; + } + if(bufferToFree != NULL) { + A_FREE(bufferToFree); + } + } else { + status = 0; + goto complete; + } + } +#ifndef HCI_TRANSPORT_SDIO + if(bdaddr[0] != '\0') { + write_bdaddr(hdev,bdaddr); + } else +#endif /* HCI_TRANSPORT_SDIO */ + { + /* Read Contents of BDADDR file if user has not provided any option */ + if(request_firmware(&firmware,BDADDR_FILE,firmwareDev) < 0) { + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: firmware file open error\n", __FUNCTION__ )); + status = 1; + goto complete; + } + if(NULL == firmware || firmware->size == 0) { + status = 1; + goto complete; + } + write_bdaddr(hdev,(A_UCHAR *)firmware->data); + release_firmware(firmware); + } +complete: +#ifndef HCI_TRANSPORT_SDIO + AthEnableSyncCommandOp(FALSE); + PSTagMode = FALSE; + wake_up_interruptible(&PsCompleteEvent); +#endif /* HCI_TRANSPORT_SDIO */ + if(NULL != HciCmdList) { + AthFreeCommandList(&HciCmdList,numCmds); + } + return status; +} +#ifndef HCI_TRANSPORT_SDIO +/* + * This API is used to send the HCI command to controller and return + * with a HCI Command Complete event. + * For HCI SDIO transport, this will be internally defined. + */ +A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig, + A_UINT8 *pHCICommand, + int CmdLength, + A_UINT8 **ppEventBuffer, + A_UINT8 **ppBufferToFree) +{ + if(CmdLength == 0) { + return A_ERROR; + } + Hci_log("COM Write -->",pHCICommand,CmdLength); + PSAcked = FALSE; + if(PSHciWritepacket(pConfig,pHCICommand,CmdLength) == 0) { + /* If the controller is not available, return Error */ + return A_ERROR; + } + //add_timer(&psCmdTimer); + wait_event_interruptible(HciEvent,(PSAcked == TRUE)); + if(NULL != HciEventpacket) { + *ppEventBuffer = HciEventpacket; + *ppBufferToFree = HciEventpacket; + } else { + /* Did not get an event from controller. return error */ + *ppBufferToFree = NULL; + return A_ERROR; + } + + return A_OK; +} +#endif /* HCI_TRANSPORT_SDIO */ + +A_STATUS ReadPSEvent(A_UCHAR* Data){ + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" PS Event %x %x %x\n",Data[4],Data[5],Data[3])); + + if(Data[4] == 0xFC && Data[5] == 0x00) + { + switch(Data[3]){ + case 0x0B: + return A_OK; + break; + case 0x0C: + /* Change Baudrate */ + return A_OK; + break; + case 0x04: + return A_OK; + break; + case 0x1E: + Rom_Version = Data[9]; + Rom_Version = ((Rom_Version << 8) |Data[8]); + Rom_Version = ((Rom_Version << 8) |Data[7]); + Rom_Version = ((Rom_Version << 8) |Data[6]); + + Build_Version = Data[13]; + Build_Version = ((Build_Version << 8) |Data[12]); + Build_Version = ((Build_Version << 8) |Data[11]); + Build_Version = ((Build_Version << 8) |Data[10]); + return A_OK; + break; + + + } + } + + return A_ERROR; +} +int str2ba(unsigned char *str_bdaddr,unsigned char *bdaddr) +{ + unsigned char bdbyte[3]; + unsigned char *str_byte = str_bdaddr; + int i,j; + unsigned char colon_present = 0; + + if(NULL != strstr(str_bdaddr,":")) { + colon_present = 1; + } + + + bdbyte[2] = '\0'; + + for( i = 0,j = 5; i < 6; i++, j--) { + bdbyte[0] = str_byte[0]; + bdbyte[1] = str_byte[1]; + bdaddr[j] = A_STRTOL(bdbyte,NULL,16); + if(colon_present == 1) { + str_byte+=3; + } else { + str_byte+=2; + } + } + return 0; +} + +A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr) +{ + A_UCHAR bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + A_UINT8 *event; + A_UINT8 *bufferToFree = NULL; + A_STATUS result = A_ERROR; + + str2ba(bdaddr,&bdaddr_cmd[7]); + + if(A_OK == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd, + sizeof(bdaddr_cmd), + &event,&bufferToFree)) { + + if(event[4] == 0xFC && event[5] == 0x00){ + if(event[3] == 0x0B){ + result = A_OK; + } + } + + } + if(bufferToFree != NULL) { + A_FREE(bufferToFree); + } + return result; + +} +A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig) +{ + A_UINT8 hciCommand[] = {0x1E,0xfc,0x00}; + A_UINT8 *event; + A_UINT8 *bufferToFree = NULL; + A_STATUS result = A_ERROR; + if(A_OK == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) { + result = ReadPSEvent(event); + + } + if(bufferToFree != NULL) { + A_FREE(bufferToFree); + } + return result; +} +A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code) +{ + A_UINT8 hciCommand[] = {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04}; + A_UINT8 *event; + A_UINT8 *bufferToFree = NULL; + A_UINT32 reg; + A_STATUS result = A_ERROR; + *code = 0; + hciCommand[3] = (A_UINT8)(FPGA_REGISTER & 0xFF); + hciCommand[4] = (A_UINT8)((FPGA_REGISTER >> 8) & 0xFF); + hciCommand[5] = (A_UINT8)((FPGA_REGISTER >> 16) & 0xFF); + hciCommand[6] = (A_UINT8)((FPGA_REGISTER >> 24) & 0xFF); + if(A_OK == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) { + + if(event[4] == 0xFC && event[5] == 0x00){ + switch(event[3]){ + case 0x05: + reg = event[9]; + reg = ((reg << 8) |event[8]); + reg = ((reg << 8) |event[7]); + reg = ((reg << 8) |event[6]); + *code = reg; + result = A_OK; + + break; + case 0x06: + //Sleep(500); + break; + } + } + + } + if(bufferToFree != NULL) { + A_FREE(bufferToFree); + } + return result; +} + + |