linux/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2004-2010 Atheros Communications Inc.
   3 * All rights reserved.
   4 *
   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
   7 * defined.
   8 *
   9 *
  10 * ar3kcpsconfig.c
  11 *
  12 *
  13 *
  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
  21 * agreement(s) terms.
  22 *
  23 *
  24 *
  25 */
  26
  27
  28
  29#include "ar3kpsconfig.h"
  30#ifndef HCI_TRANSPORT_SDIO
  31#include "hci_ath.h"
  32#include "hci_uart.h"
  33#endif /* #ifndef HCI_TRANSPORT_SDIO */
  34
  35#define MAX_FW_PATH_LEN             50
  36#define MAX_BDADDR_FORMAT_LENGTH    30
  37
  38/*
  39 *  Structure used to send HCI packet, hci packet length and device info 
  40 *  together as parameter to PSThread.
  41 */
  42typedef struct {
  43
  44    struct ps_cmd_packet *HciCmdList;
  45    u32 num_packets;
  46    struct ar3k_config_info *dev;
  47}HciCommandListParam;
  48
  49int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
  50                                           u8 *pHCICommand,
  51                                           int              CmdLength,
  52                                           u8 **ppEventBuffer,
  53                                           u8 **ppBufferToFree);
  54
  55u32 Rom_Version;
  56u32 Build_Version;
  57extern bool BDADDR;
  58
  59int getDeviceType(struct ar3k_config_info *pConfig, u32 *code);
  60int ReadVersionInfo(struct ar3k_config_info *pConfig);
  61#ifndef HCI_TRANSPORT_SDIO
  62
  63DECLARE_WAIT_QUEUE_HEAD(PsCompleteEvent);
  64DECLARE_WAIT_QUEUE_HEAD(HciEvent);
  65u8 *HciEventpacket;
  66rwlock_t syncLock;
  67wait_queue_t Eventwait;
  68
  69int PSHciWritepacket(struct hci_dev*,u8* Data, u32 len);
  70extern char *bdaddr;
  71#endif /* HCI_TRANSPORT_SDIO */
  72
  73int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type);
  74
  75int PSSendOps(void *arg);
  76
  77#ifdef BT_PS_DEBUG
  78void Hci_log(u8 * log_string,u8 *data,u32 len)
  79{
  80    int i;
  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]));
  84    }
  85    AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("\n...................................\n"));
  86}
  87#else
  88#define Hci_log(string,data,len)
  89#endif /* BT_PS_DEBUG */
  90
  91
  92
  93
  94int AthPSInitialize(struct ar3k_config_info *hdev)
  95{
  96    int status = 0;
  97    if(hdev == NULL) {
  98        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Device handle received\n"));
  99        return A_ERROR;
 100    }
 101
 102#ifndef HCI_TRANSPORT_SDIO
 103    DECLARE_WAITQUEUE(wait, current);
 104#endif /* HCI_TRANSPORT_SDIO */
 105    
 106
 107#ifdef HCI_TRANSPORT_SDIO
 108    status = PSSendOps((void*)hdev);
 109#else
 110    if(InitPSState(hdev) == -1) {
 111        return A_ERROR;
 112    }
 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);
 119        return A_ERROR;
 120    }
 121    wait_event_interruptible(PsCompleteEvent,(PSTagMode == false));
 122    set_current_state(TASK_RUNNING);
 123    remove_wait_queue(&PsCompleteEvent,&wait);
 124
 125#endif /* HCI_TRANSPORT_SDIO */
 126
 127
 128    return status;
 129    
 130}
 131
 132int PSSendOps(void *arg) 
 133{
 134    int i;
 135    int status = 0;
 136    struct ps_cmd_packet *HciCmdList; /* List storing the commands */
 137    const struct firmware* firmware;
 138    u32 numCmds;
 139    u8 *event;
 140    u8 *bufferToFree;
 141    struct hci_dev *device;
 142    u8 *buffer;
 143    u32 len;
 144    u32 DevType;
 145    u8 *PsFileName;
 146    u8 *patchFileName;
 147    u8 *path = NULL;
 148    u8 *config_path = NULL;
 149    u8 config_bdaddr[MAX_BDADDR_FORMAT_LENGTH];
 150    struct ar3k_config_info *hdev = (struct ar3k_config_info*)arg;
 151    struct device *firmwareDev = NULL;
 152    status = 0;
 153    HciCmdList = NULL;
 154#ifdef HCI_TRANSPORT_SDIO
 155    device = hdev->pBtStackHCIDev; 
 156    firmwareDev = device->parent;
 157#else 
 158    device = hdev;
 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.
 163     */
 164
 165    path =(u8 *)A_MALLOC(MAX_FW_PATH_LEN);
 166    if(path == NULL) {
 167        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for path\n", MAX_FW_PATH_LEN));
 168        goto complete;
 169    }
 170    config_path = (u8 *) 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));
 173        goto complete;
 174    }
 175
 176    if(A_ERROR == getDeviceType(hdev,&DevType)) {
 177        status = 1;
 178        goto complete;
 179    }
 180    if(A_ERROR == ReadVersionInfo(hdev)) {
 181        status = 1;
 182        goto complete;
 183    }
 184
 185    patchFileName = PATCH_FILE;
 186    snprintf(path, MAX_FW_PATH_LEN, "%s/%xcoex/",CONFIG_PATH,Rom_Version);
 187    if(DevType){
 188        if(DevType == 0xdeadc0de){
 189                PsFileName =  PS_ASIC_FILE;
 190            } else{
 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)){
 193                        
 194                        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("FPGA Test Image : Skipping Patch File load\n"));
 195                        patchFileName = NULL;
 196                }
 197                PsFileName =  PS_FPGA_FILE;
 198            }
 199    }
 200    else{
 201            PsFileName =  PS_ASIC_FILE;
 202    }
 203
 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__ ));
 209        status = 1;
 210        goto complete;
 211
 212    }
 213    if(NULL == firmware || firmware->size == 0) {
 214        status = 1;
 215        goto complete;
 216    }
 217    buffer = (u8 *)A_MALLOC(firmware->size);
 218    if(buffer != NULL) {
 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);
 225        kfree(buffer);
 226    } else {
 227        A_RELEASE_FIRMWARE(firmware);
 228    }
 229
 230
 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);
 235        else {
 236                status = 0;
 237        }
 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__ ));
 241        /* 
 242         *  It is not necessary that Patch file be available, continue with PS Operations if.
 243         *  failed.
 244         */
 245        status = 0;
 246
 247    } else {
 248        if(NULL == firmware || firmware->size == 0) {
 249            status = 0;
 250        } else {
 251            buffer = (u8 *)A_MALLOC(firmware->size);
 252            if(buffer != NULL) {
 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);
 259                kfree(buffer);
 260            } else {
 261                A_RELEASE_FIRMWARE(firmware);
 262            }
 263        }
 264    }
 265
 266    /* Create an HCI command list from the parsed PS and patch information */
 267    AthCreateCommandList(&HciCmdList,&numCmds);
 268
 269    /* Form the parameter for PSSendOps() API */
 270 
 271
 272    /*
 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.
 276     */
 277
 278    if(SendHCICommandWaitCommandComplete
 279    (hdev,
 280    HciCmdList[0].Hcipacket,
 281    HciCmdList[0].packetLen,
 282    &event,
 283    &bufferToFree) == 0) {
 284        if(ReadPSEvent(event) == 0) { /* Exit if the status is success */
 285            if(bufferToFree != NULL) {
 286                kfree(bufferToFree);
 287                }
 288        
 289#ifndef HCI_TRANSPORT_SDIO
 290                        if(bdaddr && bdaddr[0] !='\0') {
 291                                write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING);
 292                        }
 293#endif 
 294               status = 1;
 295               goto complete;
 296        }
 297        if(bufferToFree != NULL) {
 298               kfree(bufferToFree);
 299        }
 300    } else {
 301        status = 0;
 302        goto complete;
 303    }
 304 
 305    for(i = 1; i <numCmds; i++) {
 306    
 307        if(SendHCICommandWaitCommandComplete
 308        (hdev,
 309        HciCmdList[i].Hcipacket,
 310        HciCmdList[i].packetLen,
 311        &event,
 312        &bufferToFree) == 0) {
 313            if(ReadPSEvent(event) != 0) { /* Exit if the status is success */
 314                if(bufferToFree != NULL) {
 315                    kfree(bufferToFree);
 316                    }
 317                   status = 1;
 318                    goto complete;
 319            }
 320            if(bufferToFree != NULL) {
 321                   kfree(bufferToFree);
 322            }
 323        } else {
 324            status = 0;
 325            goto complete;
 326        }
 327    }
 328#ifdef HCI_TRANSPORT_SDIO
 329        if(BDADDR == false)
 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);
 337
 338#ifndef HCI_TRANSPORT_SDIO
 339
 340        if(bdaddr && bdaddr[0] != '\0') {
 341                write_bdaddr(hdev,bdaddr,BDADDR_TYPE_STRING);
 342        } else
 343#endif /* HCI_TRANSPORT_SDIO */
 344    /* Write BDADDR Read from OTP here */
 345
 346
 347
 348#endif
 349
 350        {
 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__ ));
 356                status = 1;
 357                goto complete;
 358        }
 359        if(NULL == firmware || firmware->size == 0) {
 360                status = 1;
 361                goto complete;
 362        }
 363        len = min_t(size_t, 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);
 368        }
 369complete:
 370#ifndef HCI_TRANSPORT_SDIO
 371    AthEnableSyncCommandOp(false);
 372    PSTagMode = false;
 373    wake_up_interruptible(&PsCompleteEvent);
 374#endif /* HCI_TRANSPORT_SDIO */
 375    if(NULL != HciCmdList) {
 376        AthFreeCommandList(&HciCmdList,numCmds);
 377    }
 378    if(path) {
 379        kfree(path);
 380    }
 381    if(config_path) {
 382        kfree(config_path);
 383    }
 384    return status;
 385}
 386#ifndef HCI_TRANSPORT_SDIO
 387/*
 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. 
 391 */
 392int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
 393                                           u8 *pHCICommand,
 394                                           int              CmdLength,
 395                                           u8 **ppEventBuffer,
 396                                           u8 **ppBufferToFree)
 397{
 398    if(CmdLength == 0) {
 399        return A_ERROR;
 400    }
 401    Hci_log("COM Write -->",pHCICommand,CmdLength);
 402    PSAcked = false;
 403    if(PSHciWritepacket(pConfig,pHCICommand,CmdLength) == 0) {
 404        /* If the controller is not available, return Error */
 405        return A_ERROR;
 406    }
 407    //add_timer(&psCmdTimer);
 408    wait_event_interruptible(HciEvent,(PSAcked == true));
 409    if(NULL != HciEventpacket) {
 410        *ppEventBuffer = HciEventpacket;
 411        *ppBufferToFree = HciEventpacket;
 412    } else {
 413        /* Did not get an event from controller. return error */
 414        *ppBufferToFree = NULL;
 415        return A_ERROR;
 416    }
 417
 418    return 0;
 419}
 420#endif /* HCI_TRANSPORT_SDIO */
 421
 422int ReadPSEvent(u8* Data){
 423    AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" PS Event %x %x %x\n",Data[4],Data[5],Data[3]));
 424                                
 425    if(Data[4] == 0xFC && Data[5] == 0x00)
 426    {
 427         switch(Data[3]){
 428             case 0x0B:
 429                     return 0;
 430                 break;
 431                 case 0x0C:
 432                    /* Change Baudrate */
 433                        return 0;
 434                 break;  
 435                 case 0x04:
 436                     return 0;
 437                 break;  
 438                case 0x1E:
 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]);
 443
 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]);
 448                        return 0;
 449                break;
 450
 451        
 452                }
 453    }                       
 454        
 455    return A_ERROR;           
 456}
 457int str2ba(unsigned char *str_bdaddr,unsigned char *bdaddr)
 458{
 459        unsigned char bdbyte[3];
 460        unsigned char *str_byte = str_bdaddr;
 461        int i,j;
 462        unsigned char colon_present = 0;
 463
 464        if(NULL != strstr(str_bdaddr,":")) {
 465                colon_present = 1;
 466        }
 467
 468
 469        bdbyte[2] = '\0';
 470
 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) {
 476                        str_byte+=3;
 477                } else {
 478                        str_byte+=2;
 479                }
 480        }
 481        return 0; 
 482}
 483
 484int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type)
 485{
 486        u8 bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, 
 487                                                        0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 488
 489    u8 *event;
 490    u8 *bufferToFree = NULL;
 491    int result = A_ERROR;
 492        int inc,outc;
 493
 494        if (type == BDADDR_TYPE_STRING)
 495                str2ba(bdaddr,&bdaddr_cmd[7]);
 496        else {
 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];
 500        }
 501
 502    if(0 == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd,
 503                                                                                                sizeof(bdaddr_cmd),
 504                                                                                                &event,&bufferToFree)) {
 505
 506        if(event[4] == 0xFC && event[5] == 0x00){
 507               if(event[3] == 0x0B){
 508                result = 0;
 509            }
 510        }
 511
 512    }
 513    if(bufferToFree != NULL) {
 514        kfree(bufferToFree);
 515   }
 516    return result;
 517
 518}
 519int ReadVersionInfo(struct ar3k_config_info *pConfig)
 520{
 521    u8 hciCommand[] =  {0x1E,0xfc,0x00};
 522    u8 *event;
 523    u8 *bufferToFree = NULL;
 524    int result = A_ERROR;
 525    if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
 526        result = ReadPSEvent(event);
 527
 528    }
 529    if(bufferToFree != NULL) {
 530        kfree(bufferToFree);
 531   }
 532    return result;
 533}
 534int getDeviceType(struct ar3k_config_info *pConfig, u32 *code)
 535{
 536    u8 hciCommand[] =  {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04};
 537    u8 *event;
 538    u8 *bufferToFree = NULL;
 539    u32 reg;
 540    int result = A_ERROR;
 541    *code = 0;
 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(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
 547
 548        if(event[4] == 0xFC && event[5] == 0x00){
 549               switch(event[3]){
 550                case 0x05:
 551                reg = event[9];
 552                reg = ((reg << 8) |event[8]);
 553                reg = ((reg << 8) |event[7]);
 554                reg = ((reg << 8) |event[6]);
 555                *code = reg;
 556                result = 0;
 557
 558                break;
 559                case 0x06:
 560                    //Sleep(500);
 561                break;
 562            }
 563        }
 564
 565    }
 566    if(bufferToFree != NULL) {
 567        kfree(bufferToFree);
 568   }
 569    return result;
 570}
 571
 572
 573