Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelv...
[pandora-kernel.git] / drivers / staging / ath6kl / miscdrv / ar3kps / ar3kpsconfig.c
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  */
42 typedef struct {
43
44     PSCmdPacket *HciCmdList;
45     A_UINT32  num_packets;
46     AR3K_CONFIG_INFO *dev;
47 }HciCommandListParam;
48
49 A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
50                                            A_UINT8          *pHCICommand,
51                                            int              CmdLength,
52                                            A_UINT8          **ppEventBuffer,
53                                            A_UINT8          **ppBufferToFree);
54
55 A_UINT32  Rom_Version;
56 A_UINT32  Build_Version;
57 extern A_BOOL BDADDR;
58
59 A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code);
60 A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig);
61 #ifndef HCI_TRANSPORT_SDIO
62
63 DECLARE_WAIT_QUEUE_HEAD(PsCompleteEvent);
64 DECLARE_WAIT_QUEUE_HEAD(HciEvent);
65 A_UCHAR *HciEventpacket;
66 rwlock_t syncLock;
67 wait_queue_t Eventwait;
68
69 int PSHciWritepacket(struct hci_dev*,A_UCHAR* Data, A_UINT32 len);
70 extern char *bdaddr;
71 #endif /* HCI_TRANSPORT_SDIO */
72
73 A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr,int type);
74
75 int PSSendOps(void *arg);
76
77 #ifdef BT_PS_DEBUG
78 void Hci_log(A_UCHAR * log_string,A_UCHAR *data,A_UINT32 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
94 A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev)
95 {
96     A_STATUS status = A_OK;
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
132 int PSSendOps(void *arg) 
133 {
134     int i;
135     int status = 0;
136     PSCmdPacket *HciCmdList; /* List storing the commands */
137     const struct firmware* firmware;
138     A_UINT32 numCmds;
139     A_UINT8 *event;
140     A_UINT8 *bufferToFree;
141     struct hci_dev *device;
142     A_UCHAR *buffer;
143     A_UINT32 len;
144     A_UINT32 DevType;
145     A_UCHAR *PsFileName;
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;
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 =(A_UCHAR *)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 = (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));
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 = (A_UCHAR *)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         A_FREE(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 = (A_UCHAR *)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                 A_FREE(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) == A_OK) {
284         if(ReadPSEvent(event) == A_OK) { /* Exit if the status is success */
285             if(bufferToFree != NULL) {
286                 A_FREE(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                A_FREE(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) == A_OK) {
313             if(ReadPSEvent(event) != A_OK) { /* Exit if the status is success */
314                 if(bufferToFree != NULL) {
315                     A_FREE(bufferToFree);
316                     }
317                    status = 1;
318                     goto complete;
319             }
320             if(bufferToFree != NULL) {
321                    A_FREE(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 = (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);
368         }
369 complete:
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         A_FREE(path);
380     }
381     if(config_path) {
382         A_FREE(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  */
392 A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
393                                            A_UINT8          *pHCICommand,
394                                            int              CmdLength,
395                                            A_UINT8          **ppEventBuffer,
396                                            A_UINT8          **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 A_OK;
419 }
420 #endif /* HCI_TRANSPORT_SDIO */
421
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]));
424                                 
425     if(Data[4] == 0xFC && Data[5] == 0x00)
426     {
427          switch(Data[3]){
428              case 0x0B:
429                      return A_OK;
430                  break;
431                  case 0x0C:
432                     /* Change Baudrate */
433                         return A_OK;    
434                  break;  
435                  case 0x04:
436                      return A_OK;
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 A_OK;
449                 break;
450
451         
452                 }
453     }                       
454         
455     return A_ERROR;           
456 }
457 int 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
484 A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr,int type)
485 {
486         A_UCHAR bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, 
487                                                         0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
488
489     A_UINT8 *event;
490     A_UINT8 *bufferToFree = NULL;
491     A_STATUS 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(A_OK == 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 = A_OK;
509             }
510         }
511
512     }
513     if(bufferToFree != NULL) {
514         A_FREE(bufferToFree);
515    }
516     return result;
517
518 }
519 A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig)
520 {
521     A_UINT8   hciCommand[] =  {0x1E,0xfc,0x00};
522     A_UINT8 *event;
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);
527
528     }
529     if(bufferToFree != NULL) {
530         A_FREE(bufferToFree);
531    }
532     return result;
533 }
534 A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code)
535 {
536     A_UINT8   hciCommand[] =  {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04};
537     A_UINT8 *event;
538     A_UINT8 *bufferToFree = NULL;
539     A_UINT32 reg;
540     A_STATUS result = A_ERROR;
541     *code = 0;
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)) {
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 = A_OK;
557
558                 break;
559                 case 0x06:
560                     //Sleep(500);
561                 break;
562             }
563         }
564
565     }
566     if(bufferToFree != NULL) {
567         A_FREE(bufferToFree);
568    }
569     return result;
570 }
571
572