Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / drivers / staging / ath6kl / miscdrv / ar3kconfig.c
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2009-2010 Atheros Corporation.  All rights reserved.
3 // 
4 //
5 // Permission to use, copy, modify, and/or distribute this software for any
6 // purpose with or without fee is hereby granted, provided that the above
7 // copyright notice and this permission notice appear in all copies.
8 //
9 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 //
17 //
18 //------------------------------------------------------------------------------
19 //==============================================================================
20 // AR3K configuration implementation
21 //
22 // Author(s): ="Atheros"
23 //==============================================================================
24
25 #include "a_config.h"
26 #include "athdefs.h"
27 #include "a_types.h"
28 #include "a_osapi.h"
29 #define ATH_MODULE_NAME misc
30 #include "a_debug.h"
31 #include "common_drv.h"
32 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
33 #include "export_hci_transport.h"
34 #else
35 #include "hci_transport_api.h"
36 #endif
37 #include "ar3kconfig.h"
38 #include "tlpm.h"
39
40 #define BAUD_CHANGE_COMMAND_STATUS_OFFSET   5
41 #define HCI_EVENT_RESP_TIMEOUTMS            3000
42 #define HCI_CMD_OPCODE_BYTE_LOW_OFFSET      0
43 #define HCI_CMD_OPCODE_BYTE_HI_OFFSET       1
44 #define HCI_EVENT_OPCODE_BYTE_LOW           3
45 #define HCI_EVENT_OPCODE_BYTE_HI            4
46 #define HCI_CMD_COMPLETE_EVENT_CODE         0xE
47 #define HCI_MAX_EVT_RECV_LENGTH             257
48 #define EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET  5
49
50 A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev);
51
52 static A_STATUS SendHCICommand(AR3K_CONFIG_INFO *pConfig,
53                                A_UINT8          *pBuffer,
54                                int              Length)
55 {
56     HTC_PACKET  *pPacket = NULL;
57     A_STATUS    status = A_OK;
58        
59     do {   
60         
61         pPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET));     
62         if (NULL == pPacket) {
63             status = A_NO_MEMORY;
64             break;    
65         }       
66         
67         A_MEMZERO(pPacket,sizeof(HTC_PACKET));      
68         SET_HTC_PACKET_INFO_TX(pPacket,
69                                NULL,
70                                pBuffer, 
71                                Length,
72                                HCI_COMMAND_TYPE, 
73                                AR6K_CONTROL_PKT_TAG);
74         
75             /* issue synchronously */                                      
76         status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,TRUE);   
77         
78     } while (FALSE);
79    
80     if (pPacket != NULL) {
81         A_FREE(pPacket);
82     }
83         
84     return status;
85 }
86
87 static A_STATUS RecvHCIEvent(AR3K_CONFIG_INFO *pConfig,
88                              A_UINT8          *pBuffer,
89                              int              *pLength)
90 {
91     A_STATUS    status = A_OK; 
92     HTC_PACKET  *pRecvPacket = NULL;
93     
94     do {
95                  
96         pRecvPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET));
97         if (NULL == pRecvPacket) {
98             status = A_NO_MEMORY;
99             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n"));
100             break;    
101         }     
102         
103         A_MEMZERO(pRecvPacket,sizeof(HTC_PACKET)); 
104          
105         SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE);
106         
107         status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev,
108                                                pRecvPacket,
109                                                HCI_EVENT_RESP_TIMEOUTMS);
110         if (A_FAILED(status)) {
111             break;    
112         }
113
114         *pLength = pRecvPacket->ActualLength;
115         
116     } while (FALSE);
117        
118     if (pRecvPacket != NULL) {
119         A_FREE(pRecvPacket);    
120     }
121     
122     return status;
123
124     
125 A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
126                                            A_UINT8          *pHCICommand,
127                                            int              CmdLength,
128                                            A_UINT8          **ppEventBuffer,
129                                            A_UINT8          **ppBufferToFree)
130 {
131     A_STATUS    status = A_OK;   
132     A_UINT8     *pBuffer = NULL;
133     A_UINT8     *pTemp;
134     int         length;
135     A_BOOL      commandComplete = FALSE;
136     A_UINT8     opCodeBytes[2];
137                                
138     do {
139         
140         length = max(HCI_MAX_EVT_RECV_LENGTH,CmdLength);
141         length += pConfig->pHCIProps->HeadRoom + pConfig->pHCIProps->TailRoom;
142         length += pConfig->pHCIProps->IOBlockPad;
143                                      
144         pBuffer = (A_UINT8 *)A_MALLOC(length);        
145         if (NULL == pBuffer) {
146             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to allocate bt buffer \n"));
147             status = A_NO_MEMORY;
148             break;    
149         }
150         
151             /* get the opcodes to check the command complete event */
152         opCodeBytes[0] = pHCICommand[HCI_CMD_OPCODE_BYTE_LOW_OFFSET];
153         opCodeBytes[1] = pHCICommand[HCI_CMD_OPCODE_BYTE_HI_OFFSET];
154         
155             /* copy HCI command */
156         A_MEMCPY(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength);         
157             /* send command */
158         status = SendHCICommand(pConfig,
159                                 pBuffer + pConfig->pHCIProps->HeadRoom,
160                                 CmdLength);
161         if (A_FAILED(status)) {
162             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to send HCI Command (%d) \n", status));
163             AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
164             break;    
165         }   
166         
167             /* reuse buffer to capture command complete event */
168         A_MEMZERO(pBuffer,length);
169         status = RecvHCIEvent(pConfig,pBuffer,&length);        
170         if (A_FAILED(status)) {
171             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI event recv failed \n"));
172             AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
173             break;    
174         }
175         
176         pTemp = pBuffer + pConfig->pHCIProps->HeadRoom;        
177         if (pTemp[0] == HCI_CMD_COMPLETE_EVENT_CODE) {
178             if ((pTemp[HCI_EVENT_OPCODE_BYTE_LOW] == opCodeBytes[0]) &&
179                 (pTemp[HCI_EVENT_OPCODE_BYTE_HI] == opCodeBytes[1])) {
180                 commandComplete = TRUE;    
181             }
182         }
183         
184         if (!commandComplete) {
185             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Unexpected HCI event : %d \n",pTemp[0]));
186             AR_DEBUG_PRINTBUF(pTemp,pTemp[1],"Unexpected HCI event");
187             status = A_ECOMM;
188             break;    
189         }       
190         
191         if (ppEventBuffer != NULL) {
192                 /* caller wants to look at the event */
193             *ppEventBuffer = pTemp;
194             if (ppBufferToFree == NULL) {
195                 status = A_EINVAL;
196                 break;        
197             }
198                 /* caller must free the buffer */
199             *ppBufferToFree = pBuffer;
200             pBuffer = NULL;            
201         }
202         
203     } while (FALSE);
204
205     if (pBuffer != NULL) {
206         A_FREE(pBuffer);    
207     }
208     
209     return status;    
210 }
211
212 static A_STATUS AR3KConfigureHCIBaud(AR3K_CONFIG_INFO *pConfig)
213 {
214     A_STATUS    status = A_OK;
215     A_UINT8     hciBaudChangeCommand[] =  {0x0c,0xfc,0x2,0,0};
216     A_UINT16    baudVal; 
217     A_UINT8     *pEvent = NULL;
218     A_UINT8     *pBufferToFree = NULL;
219     
220     do {
221         
222         if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) {
223             baudVal = (A_UINT16)(pConfig->AR3KBaudRate / 100);
224             hciBaudChangeCommand[3] = (A_UINT8)baudVal;
225             hciBaudChangeCommand[4] = (A_UINT8)(baudVal >> 8);
226             
227             status = SendHCICommandWaitCommandComplete(pConfig,
228                                                        hciBaudChangeCommand,
229                                                        sizeof(hciBaudChangeCommand),
230                                                        &pEvent,
231                                                        &pBufferToFree);          
232             if (A_FAILED(status)) {
233                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n"));  
234                 break;    
235             }
236             
237             if (pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET] != 0) {
238                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
239                     ("AR3K Config: Baud change command event status failed: %d \n", 
240                                 pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET]));
241                 status = A_ECOMM; 
242                 break;           
243             } 
244             
245             AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
246                     ("AR3K Config: Baud Changed to %d \n",pConfig->AR3KBaudRate));  
247         }
248         
249         if (pConfig->Flags & AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY) {
250                 /* some versions of AR3K do not switch baud immediately, up to 300MS */
251             A_MDELAY(325);
252         }
253         
254         if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP) {
255             /* Tell target to change UART baud rate for AR6K */
256             status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate);
257
258             if (A_FAILED(status)) {
259                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
260                     ("AR3K Config: failed to set scale and step values: %d \n", status));
261                 break;    
262             }
263     
264             AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
265                     ("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate));            
266         }
267                 
268     } while (FALSE);
269                         
270     if (pBufferToFree != NULL) {
271         A_FREE(pBufferToFree);    
272     }
273         
274     return status;
275 }
276
277 static A_STATUS AR3KExitMinBoot(AR3K_CONFIG_INFO *pConfig)
278 {
279     A_STATUS  status;
280     A_CHAR    exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
281                                   0x00,0x00,0x00,0x00,0x00};
282     A_UINT8   *pEvent = NULL;
283     A_UINT8   *pBufferToFree = NULL;
284     
285     status = SendHCICommandWaitCommandComplete(pConfig,
286                                                exitMinBootCmd,
287                                                sizeof(exitMinBootCmd),
288                                                &pEvent,
289                                                &pBufferToFree);
290     
291     if (A_SUCCESS(status)) {
292         if (pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET] != 0) {
293             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
294                 ("AR3K Config: MinBoot exit command event status failed: %d \n", 
295                             pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET]));
296             status = A_ECOMM;            
297         } else {
298             AR_DEBUG_PRINTF(ATH_DEBUG_INFO, 
299                                 ("AR3K Config: MinBoot Exit Command Complete (Success) \n"));
300             A_MDELAY(1);
301         }
302     } else {
303         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: MinBoot Exit Failed! \n"));    
304     }
305     
306     if (pBufferToFree != NULL) {
307         A_FREE(pBufferToFree);    
308     }
309     
310     return status;                                              
311 }
312                                  
313 static A_STATUS AR3KConfigureSendHCIReset(AR3K_CONFIG_INFO *pConfig)
314 {
315     A_STATUS status = A_OK;
316     A_UINT8 hciResetCommand[] = {0x03,0x0c,0x0};
317     A_UINT8 *pEvent = NULL;
318     A_UINT8 *pBufferToFree = NULL;
319
320     status = SendHCICommandWaitCommandComplete( pConfig,
321                                                 hciResetCommand,
322                                                 sizeof(hciResetCommand),
323                                                 &pEvent,
324                                                 &pBufferToFree );
325
326     if (A_FAILED(status)) {
327         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI reset failed! \n"));
328     }
329
330     if (pBufferToFree != NULL) {
331         A_FREE(pBufferToFree);
332     }
333
334     return status;
335 }
336
337 static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
338 {
339     A_STATUS  status;
340     /* AR3K vendor specific command for Host Wakeup Config */
341     A_CHAR    hostWakeupConfig[] = {0x31,0xFC,0x18,
342                                     0x02,0x00,0x00,0x00,
343                                     0x01,0x00,0x00,0x00,
344                                     TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00,    //idle timeout in ms
345                                     0x00,0x00,0x00,0x00,
346                                     TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00,    //wakeup timeout in ms
347                                     0x00,0x00,0x00,0x00};
348     /* AR3K vendor specific command for Target Wakeup Config */
349     A_CHAR    targetWakeupConfig[] = {0x31,0xFC,0x18,
350                                       0x04,0x00,0x00,0x00,
351                                       0x01,0x00,0x00,0x00,
352                                       TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00,  //idle timeout in ms
353                                       0x00,0x00,0x00,0x00,
354                                       TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00,  //wakeup timeout in ms
355                                       0x00,0x00,0x00,0x00};
356     /* AR3K vendor specific command for Host Wakeup Enable */
357     A_CHAR    hostWakeupEnable[] = {0x31,0xFC,0x4,
358                                     0x01,0x00,0x00,0x00};
359     /* AR3K vendor specific command for Target Wakeup Enable */
360     A_CHAR    targetWakeupEnable[] = {0x31,0xFC,0x4,
361                                       0x06,0x00,0x00,0x00};
362     /* AR3K vendor specific command for Sleep Enable */
363     A_CHAR    sleepEnable[] = {0x4,0xFC,0x1,
364                                0x1};
365     A_UINT8   *pEvent = NULL;
366     A_UINT8   *pBufferToFree = NULL;
367     
368     if (0 != pConfig->IdleTimeout) {
369         A_UINT8 idle_lsb = pConfig->IdleTimeout & 0xFF;
370         A_UINT8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8;
371         hostWakeupConfig[11] = targetWakeupConfig[11] = idle_lsb;
372         hostWakeupConfig[12] = targetWakeupConfig[12] = idle_msb;
373     }
374
375     if (0 != pConfig->WakeupTimeout) {
376         hostWakeupConfig[19] = targetWakeupConfig[19] = (pConfig->WakeupTimeout & 0xFF);
377     }
378
379     status = SendHCICommandWaitCommandComplete(pConfig,
380                                                hostWakeupConfig,
381                                                sizeof(hostWakeupConfig),
382                                                &pEvent,
383                                                &pBufferToFree);
384     if (pBufferToFree != NULL) {
385         A_FREE(pBufferToFree);    
386     }
387     if (A_FAILED(status)) {
388         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Config Failed! \n"));    
389         return status;
390     }
391     
392     pEvent = NULL;
393     pBufferToFree = NULL;
394     status = SendHCICommandWaitCommandComplete(pConfig,
395                                                targetWakeupConfig,
396                                                sizeof(targetWakeupConfig),
397                                                &pEvent,
398                                                &pBufferToFree);
399     if (pBufferToFree != NULL) {
400         A_FREE(pBufferToFree);    
401     }
402     if (A_FAILED(status)) {
403         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Config Failed! \n"));    
404         return status;
405     }
406
407     pEvent = NULL;
408     pBufferToFree = NULL;
409     status = SendHCICommandWaitCommandComplete(pConfig,
410                                                hostWakeupEnable,
411                                                sizeof(hostWakeupEnable),
412                                                &pEvent,
413                                                &pBufferToFree);
414     if (pBufferToFree != NULL) {
415         A_FREE(pBufferToFree);    
416     }
417     if (A_FAILED(status)) {
418         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Enable Failed! \n"));    
419         return status;
420     }
421
422     pEvent = NULL;
423     pBufferToFree = NULL;
424     status = SendHCICommandWaitCommandComplete(pConfig,
425                                                targetWakeupEnable,
426                                                sizeof(targetWakeupEnable),
427                                                &pEvent,
428                                                &pBufferToFree);
429     if (pBufferToFree != NULL) {
430         A_FREE(pBufferToFree);    
431     }
432     if (A_FAILED(status)) {
433         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Enable Failed! \n"));    
434         return status;
435     }
436
437     pEvent = NULL;
438     pBufferToFree = NULL;
439     status = SendHCICommandWaitCommandComplete(pConfig,
440                                                sleepEnable,
441                                                sizeof(sleepEnable),
442                                                &pEvent,
443                                                &pBufferToFree);
444     if (pBufferToFree != NULL) {
445         A_FREE(pBufferToFree);    
446     }
447     if (A_FAILED(status)) {
448         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Sleep Enable Failed! \n"));    
449     }
450     
451     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Enable TLPM Completed (status = %d) \n",status));
452
453     return status;                                              
454 }
455
456 A_STATUS AR3KConfigure(AR3K_CONFIG_INFO *pConfig)
457 {
458     A_STATUS        status = A_OK; 
459         
460     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuring AR3K ...\n"));
461                                 
462     do {
463         
464         if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) {
465             status = A_EINVAL;
466             break;    
467         }
468         
469             /* disable asynchronous recv while we issue commands and receive events synchronously */
470         status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,FALSE);
471         if (A_FAILED(status)) {
472             break;    
473         }
474       
475         if (pConfig->Flags & AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT) {
476             status =  AR3KExitMinBoot(pConfig);   
477             if (A_FAILED(status)) {
478                 break;    
479             }    
480         }
481         
482        
483         /* Load patching and PST file if available*/
484         if (A_OK != AthPSInitialize(pConfig)) {
485             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch Download Failed!\n"));
486         }
487
488         /* Send HCI reset to make PS tags take effect*/
489         AR3KConfigureSendHCIReset(pConfig);
490
491         if (pConfig->Flags & 
492                 (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
493             status = AR3KConfigureHCIBaud(pConfig);      
494             if (A_FAILED(status)) {
495                 break;    
496             }
497         }     
498
499
500
501         if (pConfig->PwrMgmtEnabled) {
502             /* the delay is required after the previous HCI reset before further
503              * HCI commands can be issued
504              */
505             A_MDELAY(200);
506             AR3KEnableTLPM(pConfig);
507         }
508                
509            /* re-enable asynchronous recv */
510         status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,TRUE);
511         if (A_FAILED(status)) {
512             break;    
513         }     
514     
515     
516     } while (FALSE);   
517     
518   
519     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuration Complete (status = %d) \n",status));
520     
521     return status;
522 }
523
524 A_STATUS AR3KConfigureExit(void *config)
525 {
526     A_STATUS        status = A_OK; 
527     AR3K_CONFIG_INFO *pConfig = (AR3K_CONFIG_INFO *)config;
528         
529     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleaning up AR3K ...\n"));
530                                 
531     do {
532         
533         if ((pConfig->pHCIDev == NULL) || (pConfig->pHCIProps == NULL) || (pConfig->pHIFDevice == NULL)) {
534             status = A_EINVAL;
535             break;    
536         }
537         
538             /* disable asynchronous recv while we issue commands and receive events synchronously */
539         status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,FALSE);
540         if (A_FAILED(status)) {
541             break;    
542         }
543       
544         if (pConfig->Flags & 
545                 (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
546             status = AR3KConfigureHCIBaud(pConfig);      
547             if (A_FAILED(status)) {
548                 break;    
549             }
550         }
551
552            /* re-enable asynchronous recv */
553         status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,TRUE);
554         if (A_FAILED(status)) {
555             break;    
556         }     
557     
558     
559     } while (FALSE);   
560     
561   
562     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleanup Complete (status = %d) \n",status));
563     
564     return status;
565 }
566