Merge branch 'for-linus' of git://github.com/richardweinberger/linux
[pandora-kernel.git] / drivers / staging / bcm / led_control.c
1 #include "headers.h"
2
3 #define STATUS_IMAGE_CHECKSUM_MISMATCH -199
4 #define EVENT_SIGNALED 1
5
6 static B_UINT16 CFG_CalculateChecksum(B_UINT8 *pu8Buffer, B_UINT32 u32Size)
7 {
8         B_UINT16        u16CheckSum=0;
9         while(u32Size--) {
10                 u16CheckSum += (B_UINT8)~(*pu8Buffer);
11             pu8Buffer++;
12         }
13         return u16CheckSum;
14 }
15 BOOLEAN IsReqGpioIsLedInNVM(PMINI_ADAPTER Adapter, UINT gpios)
16 {
17         INT Status ;
18         Status = (Adapter->gpioBitMap & gpios) ^ gpios ;
19         if(Status)
20                 return FALSE;
21         else
22                 return TRUE;
23 }
24
25 static INT LED_Blink(PMINI_ADAPTER Adapter, UINT GPIO_Num, UCHAR uiLedIndex, ULONG timeout, INT num_of_time, LedEventInfo_t currdriverstate)
26 {
27         int Status = STATUS_SUCCESS;
28         BOOLEAN bInfinite = FALSE;
29
30         /*Check if num_of_time is -ve. If yes, blink led in infinite loop*/
31         if(num_of_time < 0)
32         {
33                 bInfinite = TRUE;
34                 num_of_time = 1;
35         }
36         while(num_of_time)
37         {
38
39                 if(currdriverstate == Adapter->DriverState)
40                         TURN_ON_LED(GPIO_Num, uiLedIndex);
41
42                 /*Wait for timeout after setting on the LED*/
43                 Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
44                                         currdriverstate != Adapter->DriverState || kthread_should_stop(),
45                                         msecs_to_jiffies(timeout));
46
47                 if(kthread_should_stop())
48                 {
49                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
50                         Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED;
51                         TURN_OFF_LED(GPIO_Num, uiLedIndex);
52                         Status=EVENT_SIGNALED;
53                         break;
54                 }
55                 if(Status)
56                 {
57                         TURN_OFF_LED(GPIO_Num, uiLedIndex);
58                         Status=EVENT_SIGNALED;
59                         break;
60                 }
61
62                 TURN_OFF_LED(GPIO_Num, uiLedIndex);
63                 Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
64                                         currdriverstate!= Adapter->DriverState || kthread_should_stop(),
65                                         msecs_to_jiffies(timeout));
66                 if(bInfinite == FALSE)
67                         num_of_time--;
68         }
69         return Status;
70 }
71
72 static INT ScaleRateofTransfer(ULONG rate)
73 {
74         if(rate <= 3)
75                 return rate;
76         else if((rate > 3) && (rate <= 100))
77                 return 5;
78         else if((rate > 100) && (rate <= 200))
79                 return 6;
80         else if((rate > 200) && (rate <= 300))
81                 return 7;
82         else if((rate > 300) && (rate <= 400))
83                 return 8;
84         else if((rate > 400) && (rate <= 500))
85                 return 9;
86         else if((rate > 500) && (rate <= 600))
87                 return 10;
88         else
89                 return MAX_NUM_OF_BLINKS;
90 }
91
92
93
94 static INT LED_Proportional_Blink(PMINI_ADAPTER Adapter, UCHAR GPIO_Num_tx,
95                 UCHAR uiTxLedIndex, UCHAR GPIO_Num_rx, UCHAR uiRxLedIndex, LedEventInfo_t currdriverstate)
96 {
97         /* Initial values of TX and RX packets*/
98         ULONG64 Initial_num_of_packts_tx = 0, Initial_num_of_packts_rx = 0;
99         /*values of TX and RX packets after 1 sec*/
100         ULONG64 Final_num_of_packts_tx = 0, Final_num_of_packts_rx = 0;
101         /*Rate of transfer of Tx and Rx in 1 sec*/
102         ULONG64 rate_of_transfer_tx = 0, rate_of_transfer_rx = 0;
103         int Status = STATUS_SUCCESS;
104         INT num_of_time = 0, num_of_time_tx = 0, num_of_time_rx = 0;
105         UINT remDelay = 0;
106         BOOLEAN bBlinkBothLED = TRUE;
107         //UINT GPIO_num = DISABLE_GPIO_NUM;
108         ulong timeout = 0;
109
110         /*Read initial value of packets sent/received */
111         Initial_num_of_packts_tx = Adapter->dev->stats.tx_packets;
112         Initial_num_of_packts_rx = Adapter->dev->stats.rx_packets;
113
114         /*Scale the rate of transfer to no of blinks.*/
115         num_of_time_tx= ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
116         num_of_time_rx= ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
117
118         while((Adapter->device_removed == FALSE))
119         {
120                 timeout = 50;
121                 /*Blink Tx and Rx LED when both Tx and Rx is in normal bandwidth*/
122                 if(bBlinkBothLED)
123                 {
124                         /*Assign minimum number of blinks of either Tx or Rx.*/
125                         if(num_of_time_tx > num_of_time_rx)
126                                 num_of_time = num_of_time_rx;
127                         else
128                                 num_of_time = num_of_time_tx;
129                         if(num_of_time > 0)
130                         {
131                                 /*Blink both Tx and Rx LEDs*/
132                                 if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout, num_of_time,currdriverstate)
133                                                         == EVENT_SIGNALED)
134                                 {
135                                         return EVENT_SIGNALED;
136                                 }
137                                 if(LED_Blink(Adapter, 1<<GPIO_Num_rx, uiRxLedIndex, timeout, num_of_time,currdriverstate)
138                                                         == EVENT_SIGNALED)
139                                 {
140                                         return EVENT_SIGNALED;
141                                 }
142
143                         }
144
145                         if(num_of_time == num_of_time_tx)
146                         {
147                                 /*Blink pending rate of Rx*/
148                                 if(LED_Blink(Adapter, (1 << GPIO_Num_rx), uiRxLedIndex, timeout,
149                                                 num_of_time_rx-num_of_time,currdriverstate) == EVENT_SIGNALED)
150                                 {
151                                         return EVENT_SIGNALED;
152                                 }
153                                 num_of_time = num_of_time_rx;
154                         }
155                         else
156                         {
157                                 /*Blink pending rate of Tx*/
158                                 if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout,
159                                         num_of_time_tx-num_of_time,currdriverstate) == EVENT_SIGNALED)
160                                 {
161                                         return EVENT_SIGNALED;
162                                 }
163                                 num_of_time = num_of_time_tx;
164                         }
165                 }
166                 else
167                 {
168                         if(num_of_time == num_of_time_tx)
169                         {
170                                 /*Blink pending rate of Rx*/
171                                 if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout, num_of_time,currdriverstate)
172                                                         == EVENT_SIGNALED)
173                                 {
174                                         return EVENT_SIGNALED;
175                                 }
176                         }
177                         else
178                         {
179                                 /*Blink pending rate of Tx*/
180                                 if(LED_Blink(Adapter, 1<<GPIO_Num_rx, uiRxLedIndex, timeout,
181                                                 num_of_time,currdriverstate) == EVENT_SIGNALED)
182                                 {
183                                         return EVENT_SIGNALED;
184                                 }
185                         }
186                 }
187                 /* If Tx/Rx rate is less than maximum blinks per second,
188                          * wait till delay completes to 1 second
189                          */
190                 remDelay = MAX_NUM_OF_BLINKS - num_of_time;
191                 if(remDelay > 0)
192                 {
193                         timeout= 100 * remDelay;
194                         Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
195                                                 currdriverstate!= Adapter->DriverState ||kthread_should_stop() ,
196                                                 msecs_to_jiffies (timeout));
197
198                         if(kthread_should_stop())
199                         {
200                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
201                                 Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED;
202                                 return EVENT_SIGNALED;
203                         }
204                         if(Status)
205                                 return EVENT_SIGNALED;
206                 }
207
208                 /*Turn off both Tx and Rx LEDs before next second*/
209                 TURN_OFF_LED(1<<GPIO_Num_tx, uiTxLedIndex);
210                 TURN_OFF_LED(1<<GPIO_Num_rx, uiTxLedIndex);
211
212                 /*
213                  * Read the Tx & Rx packets transmission after 1 second and
214                  * calculate rate of transfer
215                  */
216                 Final_num_of_packts_tx = Adapter->dev->stats.tx_packets;
217                 Final_num_of_packts_rx = Adapter->dev->stats.rx_packets;
218
219                 rate_of_transfer_tx = Final_num_of_packts_tx - Initial_num_of_packts_tx;
220                 rate_of_transfer_rx = Final_num_of_packts_rx - Initial_num_of_packts_rx;
221
222                 /*Read initial value of packets sent/received */
223                 Initial_num_of_packts_tx = Final_num_of_packts_tx;
224                 Initial_num_of_packts_rx = Final_num_of_packts_rx ;
225
226                 /*Scale the rate of transfer to no of blinks.*/
227                 num_of_time_tx= ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
228                 num_of_time_rx= ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
229
230         }
231         return Status;
232 }
233
234
235 //-----------------------------------------------------------------------------
236 // Procedure:   ValidateDSDParamsChecksum
237 //
238 // Description: Reads DSD Params and validates checkusm.
239 //
240 // Arguments:
241 //      Adapter - Pointer to Adapter structure.
242 //      ulParamOffset - Start offset of the DSD parameter to be read and validated.
243 //      usParamLen - Length of the DSD Parameter.
244 //
245 // Returns:
246 //  <OSAL_STATUS_CODE>
247 //-----------------------------------------------------------------------------
248
249 static INT ValidateDSDParamsChecksum(
250                                                                                                         PMINI_ADAPTER Adapter,
251                                                                                                         ULONG  ulParamOffset,
252                                                                                                         USHORT usParamLen )
253 {
254         INT Status = STATUS_SUCCESS;
255         PUCHAR puBuffer                     = NULL;
256         USHORT usChksmOrg                   = 0;
257         USHORT usChecksumCalculated = 0;
258
259         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",ulParamOffset, usParamLen);
260
261         puBuffer = kmalloc(usParamLen, GFP_KERNEL);
262         if(!puBuffer)
263         {
264                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum Allocation failed");
265                 return -ENOMEM;
266
267         }
268
269     //
270     //  Read the DSD data from the parameter offset.
271     //
272         if(STATUS_SUCCESS != BeceemNVMRead(Adapter,(PUINT)puBuffer,ulParamOffset,usParamLen))
273         {
274                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
275                 Status=STATUS_IMAGE_CHECKSUM_MISMATCH;
276                 goto exit;
277         }
278
279         //
280         //      Calculate the checksum of the data read from the DSD parameter.
281         //
282         usChecksumCalculated = CFG_CalculateChecksum(puBuffer,usParamLen);
283         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: usCheckSumCalculated = 0x%x\n", usChecksumCalculated);
284
285         //
286         //      End of the DSD parameter will have a TWO bytes checksum stored in it. Read it and compare with the calculated
287         //      Checksum.
288         //
289         if(STATUS_SUCCESS != BeceemNVMRead(Adapter,(PUINT)&usChksmOrg,ulParamOffset+usParamLen,2))
290         {
291                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
292                 Status=STATUS_IMAGE_CHECKSUM_MISMATCH;
293                 goto exit;
294         }
295         usChksmOrg = ntohs(usChksmOrg);
296         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: usChksmOrg = 0x%x", usChksmOrg);
297
298         //
299         //      Compare the checksum calculated with the checksum read from DSD section
300         //
301         if(usChecksumCalculated ^ usChksmOrg)
302         {
303                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum: Checksums don't match");
304                 Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
305                 goto exit;
306         }
307
308 exit:
309         kfree(puBuffer);
310         return Status;
311 }
312
313
314 //-----------------------------------------------------------------------------
315 // Procedure:   ValidateHWParmStructure
316 //
317 // Description: Validates HW Parameters.
318 //
319 // Arguments:
320 //      Adapter - Pointer to Adapter structure.
321 //      ulHwParamOffset - Start offset of the HW parameter Section to be read and validated.
322 //
323 // Returns:
324 //  <OSAL_STATUS_CODE>
325 //-----------------------------------------------------------------------------
326
327 static INT ValidateHWParmStructure(PMINI_ADAPTER Adapter, ULONG ulHwParamOffset)
328 {
329
330         INT Status = STATUS_SUCCESS ;
331         USHORT HwParamLen = 0;
332         // Add DSD start offset to the hwParamOffset to get the actual address.
333         ulHwParamOffset += DSD_START_OFFSET;
334
335         /*Read the Length of HW_PARAM structure*/
336         BeceemNVMRead(Adapter,(PUINT)&HwParamLen,ulHwParamOffset,2);
337         HwParamLen = ntohs(HwParamLen);
338         if(0==HwParamLen || HwParamLen > Adapter->uiNVMDSDSize)
339         {
340                 return STATUS_IMAGE_CHECKSUM_MISMATCH;
341         }
342
343         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "LED Thread:HwParamLen = 0x%x", HwParamLen);
344         Status =ValidateDSDParamsChecksum(Adapter,ulHwParamOffset,HwParamLen);
345         return Status;
346 } /* ValidateHWParmStructure() */
347
348 static int ReadLEDInformationFromEEPROM(PMINI_ADAPTER Adapter, UCHAR GPIO_Array[])
349 {
350         int Status = STATUS_SUCCESS;
351
352         ULONG  dwReadValue              = 0;
353         USHORT usHwParamData    = 0;
354         USHORT usEEPROMVersion  = 0;
355         UCHAR  ucIndex                  = 0;
356         UCHAR  ucGPIOInfo[32]   = {0};
357
358         BeceemNVMRead(Adapter,(PUINT)&usEEPROMVersion,EEPROM_VERSION_OFFSET,2);
359
360         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"usEEPROMVersion: Minor:0x%X Major:0x%x",usEEPROMVersion&0xFF, ((usEEPROMVersion>>8)&0xFF));
361
362
363         if(((usEEPROMVersion>>8)&0xFF) < EEPROM_MAP5_MAJORVERSION)
364         {
365                 BeceemNVMRead(Adapter,(PUINT)&usHwParamData,EEPROM_HW_PARAM_POINTER_ADDRESS,2);
366                 usHwParamData = ntohs(usHwParamData);
367                 dwReadValue   = usHwParamData;
368         }
369         else
370         {
371                 //
372                 // Validate Compatibility section and then read HW param if compatibility section is valid.
373                 //
374                 Status = ValidateDSDParamsChecksum(Adapter,
375                                            DSD_START_OFFSET,
376                                            COMPATIBILITY_SECTION_LENGTH_MAP5);
377
378                 if(Status != STATUS_SUCCESS)
379                 {
380                         return Status;
381                 }
382                 BeceemNVMRead(Adapter,(PUINT)&dwReadValue,EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5,4);
383                 dwReadValue = ntohl(dwReadValue);
384         }
385
386
387         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Start address of HW_PARAM structure = 0x%lx",dwReadValue);
388
389         //
390         // Validate if the address read out is within the DSD.
391         // Adapter->uiNVMDSDSize gives whole DSD size inclusive of Autoinit.
392         // lower limit should be above DSD_START_OFFSET and
393         // upper limit should be below (Adapter->uiNVMDSDSize-DSD_START_OFFSET)
394         //
395         if(dwReadValue < DSD_START_OFFSET ||
396            dwReadValue > (Adapter->uiNVMDSDSize-DSD_START_OFFSET))
397         {
398                 return STATUS_IMAGE_CHECKSUM_MISMATCH;
399         }
400
401         Status = ValidateHWParmStructure(Adapter, dwReadValue);
402         if(Status){
403                 return Status;
404         }
405
406         /*
407           Add DSD_START_OFFSET to the offset read from the EEPROM.
408           This will give the actual start HW Parameters start address.
409           To read GPIO section, add GPIO offset further.
410         */
411
412         dwReadValue += DSD_START_OFFSET; // = start address of hw param section.
413         dwReadValue += GPIO_SECTION_START_OFFSET; // = GPIO start offset within HW Param section.
414
415         /* Read the GPIO values for 32 GPIOs from EEPROM and map the function
416          * number to GPIO pin number to GPIO_Array
417          */
418         BeceemNVMRead(Adapter, (UINT *)ucGPIOInfo,dwReadValue,32);
419         for(ucIndex = 0; ucIndex < 32; ucIndex++)
420          {
421
422                  switch(ucGPIOInfo[ucIndex])
423                         {
424                                 case RED_LED:
425                                 {
426                                         GPIO_Array[RED_LED] = ucIndex;
427                                         Adapter->gpioBitMap |= (1<<ucIndex);
428                                         break;
429                                 }
430                                 case BLUE_LED:
431                                 {
432                                         GPIO_Array[BLUE_LED] = ucIndex;
433                                         Adapter->gpioBitMap |= (1<<ucIndex);
434                                         break;
435                                 }
436                                 case YELLOW_LED:
437                                 {
438                                          GPIO_Array[YELLOW_LED] = ucIndex;
439                                          Adapter->gpioBitMap |= (1<<ucIndex);
440                                          break;
441                                 }
442                                 case GREEN_LED:
443                                 {
444                                         GPIO_Array[GREEN_LED] = ucIndex;
445                                         Adapter->gpioBitMap |= (1<<ucIndex);
446                                         break;
447                                 }
448                                 default:
449                                         break;
450                         }
451
452                 }
453                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"GPIO's bit map correspond to LED :0x%X",Adapter->gpioBitMap);
454          return Status;
455 }
456
457
458 static int ReadConfigFileStructure(PMINI_ADAPTER Adapter, BOOLEAN *bEnableThread)
459 {
460         int Status = STATUS_SUCCESS;
461         UCHAR GPIO_Array[NUM_OF_LEDS+1]; /*Array to store GPIO numbers from EEPROM*/
462         UINT uiIndex = 0;
463         UINT uiNum_of_LED_Type = 0;
464         PUCHAR puCFGData        = NULL;
465         UCHAR bData = 0;
466         memset(GPIO_Array, DISABLE_GPIO_NUM, NUM_OF_LEDS+1);
467
468         if(!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams))
469         {
470                 BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Target Params not Avail.\n");
471                 return -ENOENT;
472         }
473
474         /*Populate GPIO_Array with GPIO numbers for LED functions*/
475         /*Read the GPIO numbers from EEPROM*/
476         Status = ReadLEDInformationFromEEPROM(Adapter, GPIO_Array);
477         if(Status == STATUS_IMAGE_CHECKSUM_MISMATCH)
478         {
479                 *bEnableThread = FALSE;
480                 return STATUS_SUCCESS;
481         }
482         else if(Status)
483         {
484                 *bEnableThread = FALSE;
485                 return Status;
486         }
487   /*
488      * CONFIG file read successfully. Deallocate the memory of
489      * uiFileNameBufferSize
490      */
491         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Config file read successfully\n");
492         puCFGData = (PUCHAR) &Adapter->pstargetparams->HostDrvrConfig1;
493
494         /*
495          * Offset for HostDrvConfig1, HostDrvConfig2, HostDrvConfig3 which
496          * will have the information of LED type, LED on state for different
497          * driver state and LED blink state.
498          */
499
500         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
501         {
502                 bData = *puCFGData;
503
504                 /*Check Bit 8 for polarity. If it is set, polarity is reverse polarity*/
505                 if(bData & 0x80)
506                 {
507                         Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 0;
508                         /*unset the bit 8*/
509                         bData = bData & 0x7f;
510                 }
511
512                 Adapter->LEDInfo.LEDState[uiIndex].LED_Type = bData;
513                 if(bData <= NUM_OF_LEDS)
514                         Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = GPIO_Array[bData];
515                 else
516                         Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = DISABLE_GPIO_NUM;
517
518                 puCFGData++;
519                 bData = *puCFGData;
520                 Adapter->LEDInfo.LEDState[uiIndex].LED_On_State = bData;
521                 puCFGData++;
522                 bData = *puCFGData;
523                 Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State= bData;
524                 puCFGData++;
525         }
526
527         /*Check if all the LED settings are disabled. If it is disabled, dont launch the LED control thread.*/
528         for(uiIndex = 0; uiIndex<NUM_OF_LEDS; uiIndex++)
529         {
530                 if((Adapter->LEDInfo.LEDState[uiIndex].LED_Type == DISABLE_GPIO_NUM) ||
531                         (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0x7f) ||
532                         (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0))
533                         uiNum_of_LED_Type++;
534         }
535         if(uiNum_of_LED_Type >= NUM_OF_LEDS)
536                 *bEnableThread = FALSE;
537
538         return Status;
539 }
540 //--------------------------------------------------------------------------
541 // Procedure:   LedGpioInit
542 //
543 // Description: Initializes LED GPIOs. Makes the LED GPIOs to OUTPUT mode and make the
544 //                        initial state to be OFF.
545 //
546 // Arguments:
547 //      Adapter - Pointer to MINI_ADAPTER structure.
548 //
549 // Returns: VOID
550 //
551 //-----------------------------------------------------------------------------
552
553 static VOID LedGpioInit(PMINI_ADAPTER Adapter)
554 {
555         UINT uiResetValue = 0;
556         UINT uiIndex      = 0;
557
558         /* Set all LED GPIO Mode to output mode */
559         if(rdmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) <0)
560                 BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: RDM Failed\n");
561         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
562         {
563                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
564                         uiResetValue |= (1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
565                 TURN_OFF_LED(1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num,uiIndex);
566         }
567         if(wrmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) < 0)
568                 BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: WRM Failed\n");
569
570         Adapter->LEDInfo.bIdle_led_off =  FALSE;
571 }
572 //-----------------------------------------------------------------------------
573
574 static INT BcmGetGPIOPinInfo(PMINI_ADAPTER Adapter, UCHAR *GPIO_num_tx, UCHAR *GPIO_num_rx ,UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex,LedEventInfo_t currdriverstate)
575 {
576         UINT uiIndex = 0;
577
578         *GPIO_num_tx = DISABLE_GPIO_NUM;
579         *GPIO_num_rx = DISABLE_GPIO_NUM;
580
581         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
582         {
583
584                 if((currdriverstate == NORMAL_OPERATION)||
585                         (currdriverstate == IDLEMODE_EXIT)||
586                         (currdriverstate == FW_DOWNLOAD))
587                 {
588                         if(Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State & currdriverstate)
589                         {
590                                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
591                                 {
592                                         if(*GPIO_num_tx == DISABLE_GPIO_NUM)
593                                         {
594                                                 *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
595                                                 *uiLedTxIndex = uiIndex;
596                                         }
597                                         else
598                                         {
599                                                 *GPIO_num_rx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
600                                                 *uiLedRxIndex = uiIndex;
601                                         }
602                                 }
603                         }
604                 }
605                 else
606                 {
607                         if(Adapter->LEDInfo.LEDState[uiIndex].LED_On_State & currdriverstate)
608                         {
609                                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
610                                 {
611                                         *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
612                                         *uiLedTxIndex = uiIndex;
613                                 }
614                         }
615                 }
616         }
617         return STATUS_SUCCESS ;
618 }
619 static VOID LEDControlThread(PMINI_ADAPTER Adapter)
620 {
621         UINT uiIndex = 0;
622         UCHAR GPIO_num = 0;
623         UCHAR uiLedIndex = 0 ;
624         UINT uiResetValue = 0;
625         LedEventInfo_t currdriverstate = 0;
626         ulong timeout = 0;
627
628         INT Status = 0;
629
630         UCHAR  dummyGPIONum = 0;
631         UCHAR  dummyIndex = 0;
632
633         //currdriverstate = Adapter->DriverState;
634         Adapter->LEDInfo.bIdleMode_tx_from_host = FALSE;
635
636         /*Wait till event is triggered*/
637         //wait_event(Adapter->LEDInfo.notify_led_event,
638                         //      currdriverstate!= Adapter->DriverState);
639
640         GPIO_num = DISABLE_GPIO_NUM ;
641
642         while(TRUE)
643         {
644                 /*Wait till event is triggered*/
645                 if( (GPIO_num == DISABLE_GPIO_NUM)
646                                                 ||
647                         ((currdriverstate != FW_DOWNLOAD) &&
648                          (currdriverstate != NORMAL_OPERATION) &&
649                          (currdriverstate != LOWPOWER_MODE_ENTER))
650                                                 ||
651                          (currdriverstate == LED_THREAD_INACTIVE)       )
652                 {
653                         Status = wait_event_interruptible(Adapter->LEDInfo.notify_led_event,
654                                 currdriverstate != Adapter->DriverState || kthread_should_stop());
655                 }
656
657                 if(kthread_should_stop() || Adapter->device_removed )
658                 {
659                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
660                         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
661                         TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
662                         return ;//STATUS_FAILURE;
663                 }
664
665                 if(GPIO_num != DISABLE_GPIO_NUM)
666                 {
667                         TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
668                 }
669
670                 if(Adapter->LEDInfo.bLedInitDone == FALSE)
671                 {
672                         LedGpioInit(Adapter);
673                         Adapter->LEDInfo.bLedInitDone = TRUE;
674                 }
675
676                 switch(Adapter->DriverState)
677                 {
678                         case DRIVER_INIT:
679                         {
680                                 currdriverstate = DRIVER_INIT;//Adapter->DriverState;
681                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex, currdriverstate);
682
683                                 if(GPIO_num  != DISABLE_GPIO_NUM)
684                                 {
685                                         TURN_ON_LED(1<<GPIO_num, uiLedIndex);
686                                 }
687                         }
688                         break;
689                         case FW_DOWNLOAD:
690                         {
691                                 //BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FW_DN_DONE called\n");
692                                 currdriverstate = FW_DOWNLOAD;
693                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,  &uiLedIndex, &dummyIndex, currdriverstate);
694
695                                 if(GPIO_num != DISABLE_GPIO_NUM)
696                                 {
697                                         timeout = 50;
698                                         LED_Blink(Adapter, 1<<GPIO_num, uiLedIndex, timeout, -1,currdriverstate);
699                                 }
700                         }
701                         break;
702                         case FW_DOWNLOAD_DONE:
703                         {
704                                 currdriverstate = FW_DOWNLOAD_DONE;
705                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex,currdriverstate);
706                                 if(GPIO_num != DISABLE_GPIO_NUM)
707                                 {
708                                         TURN_ON_LED(1<<GPIO_num, uiLedIndex);
709                                 }
710                         }
711                         break;
712
713                         case SHUTDOWN_EXIT:
714                         //no break, continue to NO_NETWORK_ENTRY state as well.
715
716                         case NO_NETWORK_ENTRY:
717                         {
718                                 currdriverstate = NO_NETWORK_ENTRY;
719                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex,&dummyGPIONum,currdriverstate);
720                                 if(GPIO_num != DISABLE_GPIO_NUM)
721                                 {
722                                         TURN_ON_LED(1<<GPIO_num, uiLedIndex);
723                                 }
724                         }
725                         break;
726                         case NORMAL_OPERATION:
727                         {
728                                 UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
729                                 UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
730                                 UCHAR uiLEDTx = 0;
731                                 UCHAR uiLEDRx = 0;
732                                 currdriverstate = NORMAL_OPERATION;
733                                 Adapter->LEDInfo.bIdle_led_off =  FALSE;
734
735                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx, &GPIO_num_rx, &uiLEDTx,&uiLEDRx,currdriverstate);
736                                 if((GPIO_num_tx == DISABLE_GPIO_NUM) && (GPIO_num_rx == DISABLE_GPIO_NUM))
737                                 {
738                                         GPIO_num = DISABLE_GPIO_NUM ;
739                                 }
740                                 else
741                                 {
742                                         /*If single LED is selected, use same for both Tx and Rx*/
743                                         if(GPIO_num_tx == DISABLE_GPIO_NUM)
744                                         {
745                                                 GPIO_num_tx = GPIO_num_rx;
746                                                 uiLEDTx = uiLEDRx;
747                                         }
748                                         else if(GPIO_num_rx == DISABLE_GPIO_NUM)
749                                         {
750                                                 GPIO_num_rx = GPIO_num_tx;
751                                                 uiLEDRx = uiLEDTx;
752                                         }
753                                 /*Blink the LED in proportionate to Tx and Rx transmissions.*/
754                                         LED_Proportional_Blink(Adapter, GPIO_num_tx, uiLEDTx, GPIO_num_rx, uiLEDRx,currdriverstate);
755                                 }
756                         }
757                         break;
758                         case LOWPOWER_MODE_ENTER:
759                         {
760                                 currdriverstate  = LOWPOWER_MODE_ENTER;
761                                 if( DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING == Adapter->ulPowerSaveMode)
762                                 {
763                                         /* Turn OFF all the LED */
764                                         uiResetValue = 0;
765                                         for(uiIndex =0; uiIndex < NUM_OF_LEDS; uiIndex++)
766                                         {
767                                                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
768                                                 TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
769                                         }
770
771                                 }
772                                 /* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */
773                                 Adapter->LEDInfo.bLedInitDone = FALSE;
774                                 Adapter->LEDInfo.bIdle_led_off =  TRUE;
775                                 wake_up(&Adapter->LEDInfo.idleModeSyncEvent);
776                                 GPIO_num = DISABLE_GPIO_NUM;
777                                 break;
778                         }
779                         case IDLEMODE_CONTINUE:
780                         {
781                                 currdriverstate = IDLEMODE_CONTINUE;
782                                 GPIO_num = DISABLE_GPIO_NUM;
783                         }
784                         break;
785                         case IDLEMODE_EXIT:
786                         {
787                         }
788                         break;
789                         case DRIVER_HALT:
790                         {
791                                 currdriverstate = DRIVER_HALT;
792                                 GPIO_num = DISABLE_GPIO_NUM;
793                                 for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
794                                 {
795                                         if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
796                                                 DISABLE_GPIO_NUM)
797                                                 TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
798                                 }
799                                 //Adapter->DriverState = DRIVER_INIT;
800                         }
801                         break;
802                         case LED_THREAD_INACTIVE :
803                         {
804                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"InActivating LED thread...");
805                                 currdriverstate = LED_THREAD_INACTIVE;
806                                 Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_INACTIVELY ;
807                                 Adapter->LEDInfo.bLedInitDone = FALSE ;
808                                 //disable ALL LED
809                                 for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
810                                 {
811                                         if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
812                                                 DISABLE_GPIO_NUM)
813                                                 TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
814                                 }
815                         }
816                         break;
817                         case LED_THREAD_ACTIVE :
818                         {
819                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"Activating LED thread again...");
820                                 if(Adapter->LinkUpStatus == FALSE)
821                                         Adapter->DriverState = NO_NETWORK_ENTRY;
822                                 else
823                                         Adapter->DriverState = NORMAL_OPERATION;
824
825                                 Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY ;
826                         }
827                         break;
828                         //return;
829                         default:
830                                 break;
831                 }
832         }
833         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
834 }
835
836 int InitLedSettings(PMINI_ADAPTER Adapter)
837 {
838         int Status = STATUS_SUCCESS;
839         BOOLEAN bEnableThread = TRUE;
840         UCHAR uiIndex = 0;
841
842         /*Initially set BitPolarity to normal polarity. The bit 8 of LED type
843  *        is used to change the polarity of the LED.*/
844
845         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
846                 Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 1;
847         }
848
849         /*Read the LED settings of CONFIG file and map it to GPIO numbers in EEPROM*/
850         Status = ReadConfigFileStructure(Adapter, &bEnableThread);
851         if(STATUS_SUCCESS != Status)
852         {
853                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FAILED in ReadConfigFileStructure\n");
854                 return Status;
855         }
856
857         if(Adapter->LEDInfo.led_thread_running)
858         {
859                 if(bEnableThread)
860                         ;
861                 else
862                 {
863                         Adapter->DriverState = DRIVER_HALT;
864                         wake_up(&Adapter->LEDInfo.notify_led_event);
865                         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
866                 }
867
868         }
869
870         else if(bEnableThread)
871         {
872                 /*Create secondary thread to handle the LEDs*/
873                 init_waitqueue_head(&Adapter->LEDInfo.notify_led_event);
874                 init_waitqueue_head(&Adapter->LEDInfo.idleModeSyncEvent);
875                 Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY;
876                 Adapter->LEDInfo.bIdle_led_off =  FALSE;
877                 Adapter->LEDInfo.led_cntrl_threadid = kthread_run((int (*)(void *))
878             LEDControlThread, Adapter, "led_control_thread");
879                 if(IS_ERR(Adapter->LEDInfo.led_cntrl_threadid))
880         {
881                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Not able to spawn Kernel Thread\n");
882                         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
883                 return PTR_ERR(Adapter->LEDInfo.led_cntrl_threadid);
884         }
885         }
886         return Status;
887 }