1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - PM
3   File:     pm.c
4 
5   Copyright 2003-2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2009-02-19#$
14   $Rev: 10039 $
15   $Author: yada $
16  *---------------------------------------------------------------------------*/
17 #include <nitro/spi/ARM9/pm.h>
18 #include <nitro/pxi.h>
19 #include <nitro/gx.h>
20 #include <nitro/spi/common/config.h>
21 #include <nitro/ctrdg.h>
22 #include <nitro/mb.h>
23 #ifdef SDK_TWL
24 #include "../../os/common/include/application_jump_private.h"
25 #endif
26 
27 //---------------- for IS-TWL-DEBUGGER
28 #ifdef          SDK_LINK_ISTD
29 # pragma warn_extracomma off
30 # include       <istdbglib.h>          // has extra comma in enum
31 # pragma warn_extracomma reset
32 #endif
33 
34 //---- PM work area
35 typedef struct
36 {
37 	//---- lock flag
38     BOOL    lock;
39 
40 	//---- callback
41     PMCallback callback;
42     void   *callbackArg;
43 
44 	//---- free work area
45     void   *work;
46 }
47 PMiWork;
48 
49 #define PMi_LCD_WAIT_SYS_CYCLES  0x360000
50 #define PMi_PXI_WAIT_TICK        10
51 
52 //---- compare method
53 #define PMi_COMPARE_GT           0    // compare by '>'
54 #define PMi_COMPARE_GE           1    // compare by '>='
55 
56 //----------------
57 #define PMi_SetCallback( func, arg ) \
58     do{ \
59 		PMi_Work.callback    = (func);          \
60 	    PMi_Work.callbackArg = (arg);           \
61 	} while(0)
62 
63 //----------------
PMi_MakeData1(u32 bit,u32 seq,u32 command,u32 data)64 inline u32 PMi_MakeData1(u32 bit, u32 seq, u32 command, u32 data)
65 {
66     return (bit) | ((seq) << SPI_PXI_INDEX_SHIFT) | ((command) << 8) | ((data) & 0xff);
67 }
68 
69 //----------------
PMi_MakeData2(u32 bit,u32 seq,u32 data)70 inline u32 PMi_MakeData2(u32 bit, u32 seq, u32 data)
71 {
72     return (bit) | ((seq) << SPI_PXI_INDEX_SHIFT) | ((data) & 0xffff);
73 }
74 
75 static void PMi_TryToSendPxiDataTillSuccess( u32* sendData, int num  );
76 static u32 PMi_ForceToPowerOff(void);
77 static void PMi_CallPostExitCallbackAndReset(BOOL isExit);
78 
79 //---------------- lock
80 static BOOL PMi_Lock(void);
81 
82 //---------------- wait unlock
83 static void PMi_WaitBusy(void);
84 
85 //---------------- dummy callback
86 void    PMi_DummyCallback(u32 result, void *arg);
87 
88 //---------------- callback list operation
89 static void PMi_InsertList(PMGenCallbackInfo **listp, PMGenCallbackInfo *info, int priority, int method);
90 static void PMi_DeleteList(PMGenCallbackInfo **listp, PMGenCallbackInfo *info);
91 static void PMi_ClearList(PMGenCallbackInfo **listp);
92 static void PMi_ExecuteList(PMGenCallbackInfo *listp);
93 
94 #ifdef SDK_TWL
95 static void PMi_FinalizeDebugger(void);
96 #include <twl/ltdmain_begin.h>
97 static void PMi_ProceedToExit(PMExitFactor factor);
98 static void PMi_ClearPreExitCallback(void);
99 static void PMi_ClearPostExitCallback(void);
100 #include <twl/ltdmain_end.h>
101 #endif
102 
103 static void PMi_LCDOnAvoidReset(void);
104 
105 static PMiWork PMi_Work;
106 
107 static volatile BOOL PMi_SleepEndFlag;
108 
109 //---- VBlank count LCD turned off
110 static u32 PMi_LCDCount;
111 static u32 PMi_DispOffCount;
112 
113 //---- callback list
114 static PMSleepCallbackInfo        *PMi_PreSleepCallbackList = NULL;
115 static PMSleepCallbackInfo        *PMi_PostSleepCallbackList = NULL;
116 #ifdef SDK_TWL
117 #include <twl/ltdmain_begin.h>
118 static PMExitCallbackInfo         *PMi_PreExitCallbackList = NULL;
119 static PMExitCallbackInfo         *PMi_PostExitCallbackList = NULL;
120 static PMBatteryLowCallbackInfo    PMi_BatteryLowCallbackInfo = {NULL,NULL,NULL};
121 #include <twl/ltdmain_end.h>
122 #endif
123 
124 //---- mic power config
125 static u32 PMi_SetAmp(PMAmpSwitch status);
126 static PMAmpSwitch sAmpSwitch = PM_AMP_OFF;
127 
128 //---- auto reset/shutdown flag
129 #ifdef SDK_TWL
130 static BOOL PMi_AutoExitFlag = TRUE;
131 #ifndef SDK_FINALROM
132 static BOOL PMi_ExitSequenceFlag = FALSE;
133 #endif
134 static PMExitFactor PMi_ExitFactor = PM_EXIT_FACTOR_NONE;
135 #endif
136 static u32 PMi_PreDmaCnt[4];
137 
138 #define PMi_WAITBUSY_METHOD_CPUMODE   (1<<1)
139 #define PMi_WAITBUSY_METHOD_CPSR      (1<<2)
140 #define PMi_WAITBUSY_METHOD_IME       (1<<3)
141 static BOOL PMi_WaitBusyMethod = PMi_WAITBUSY_METHOD_CPUMODE;
142 
143 //================================================================
144 //      INTERNAL FUNCTIONS
145 //================================================================
146 //----------------------------------------------------------------
147 //  PMi_Lock
148 //       return FALSE if locked.
149 //       else lock and return TRUE.
150 //
PMi_Lock(void)151 static BOOL PMi_Lock(void)
152 {
153     OSIntrMode enabled = OS_DisableInterrupts();
154 
155     //---- check whether locked
156     if (PMi_Work.lock)
157     {
158         (void)OS_RestoreInterrupts(enabled);
159         return FALSE;
160     }
161 
162 	//---- lock
163     PMi_Work.lock = TRUE;
164     (void)OS_RestoreInterrupts(enabled);
165 
166     return TRUE;
167 }
168 
169 
170 extern void PXIi_HandlerRecvFifoNotEmpty(void);
171 //----------------------------------------------------------------
172 //  PMi_WaitBusy_forUsual / PMi_WaitBusy_forPowerOff
173 //
174 //       wait while locked
175 //
PMi_WaitBusy(void)176 static void PMi_WaitBusy(void)
177 {
178     volatile BOOL *p = &PMi_Work.lock;
179 
180     while (*p)
181     {
182         if ( (    PMi_WaitBusyMethod & PMi_WAITBUSY_METHOD_CPUMODE && OS_GetProcMode() == OS_PROCMODE_IRQ )
183              || ( PMi_WaitBusyMethod & PMi_WAITBUSY_METHOD_CPSR && OS_GetCpsrIrq() == OS_INTRMODE_IRQ_DISABLE )
184              || ( PMi_WaitBusyMethod & PMi_WAITBUSY_METHOD_IME && OS_GetIrq() == OS_IME_DISABLE ) )
185         {
186             PXIi_HandlerRecvFifoNotEmpty();
187         }
188     }
189 }
190 
191 //----------------------------------------------------------------
192 //  PMi_DummyCallback
193 //
PMi_DummyCallback(u32 result,void * arg)194 static void PMi_DummyCallback(u32 result, void *arg)
195 {
196 	if ( arg )
197 	{
198 		*(u32 *)arg = result;
199 	}
200 }
201 
202 //----------------------------------------------------------------
203 //   PMi_CallCallbackAndUnlock
204 //
PMi_CallCallbackAndUnlock(u32 result)205 static void PMi_CallCallbackAndUnlock(u32 result)
206 {
207     PMCallback callback = PMi_Work.callback;
208     void       *arg     = PMi_Work.callbackArg;
209 
210 	PMi_Work.lock = FALSE;
211 
212 	//---- call callback
213     if (callback)
214     {
215         PMi_Work.callback = NULL;
216         (callback) (result, arg);
217     }
218 }
219 
220 
221 //================================================================
222 //      INIT
223 //================================================================
224 /*---------------------------------------------------------------------------*
225   Name:         PM_Init
226 
227   Description:  initializes PM
228 
229   Arguments:    None.
230 
231   Returns:      None.
232  *---------------------------------------------------------------------------*/
PM_Init(void)233 void PM_Init(void)
234 {
235 	static u16 PMi_IsInit = FALSE;
236 
237     if (PMi_IsInit)
238     {
239         return;
240     }
241     PMi_IsInit = TRUE;
242 
243     //---- initialize work area
244     PMi_Work.lock = FALSE;
245     PMi_Work.callback = NULL;
246 
247 #ifdef SDK_TWL
248     *(u32*)HW_RESET_LOCK_FLAG_BUF = PM_RESET_FLAG_NONE;
249 #endif
250 
251     //---- wait for till ARM7 PXI library start
252     PXI_Init();
253     while (!PXI_IsCallbackReady(PXI_FIFO_TAG_PM, PXI_PROC_ARM7))
254     {
255 		SVC_WaitByLoop(100);
256     }
257 
258     //---- set receive callback
259     PXI_SetFifoRecvCallback(PXI_FIFO_TAG_PM, PMi_CommonCallback);
260 
261     //---- init LCD count
262     PMi_LCDCount = PMi_DispOffCount = OS_GetVBlankCount();
263 }
264 
265 //================================================================
266 //      PXI CALLBACK
267 //================================================================
268 /*---------------------------------------------------------------------------*
269   Name:         PMi_CommonCallback
270 
271   Description:  callback to receive data from PXI
272 
273   Arguments:    tag  : tag from PXI (unused)
274                 data: data from PXI
275                 err  : error bit
276 
277   Returns:      None.
278  *---------------------------------------------------------------------------*/
PMi_CommonCallback(PXIFifoTag tag,u32 data,BOOL err)279 void PMi_CommonCallback(PXIFifoTag tag, u32 data, BOOL err)
280 {
281 #pragma unused( tag )
282 
283     u16     command;
284     u16     pxiResult;
285 	BOOL    callCallback = TRUE;
286 
287     command = (u16)((data & SPI_PXI_RESULT_COMMAND_MASK) >> SPI_PXI_RESULT_COMMAND_SHIFT);
288     pxiResult = (u16)((data & SPI_PXI_RESULT_DATA_MASK) >> SPI_PXI_RESULT_DATA_SHIFT);
289 
290     //---- check PXI communication error
291     if (err)
292     {
293         switch ( command )
294         {
295         case SPI_PXI_COMMAND_PM_SLEEP_START:
296         case SPI_PXI_COMMAND_PM_UTILITY:
297             pxiResult = PM_RESULT_BUSY;
298             break;
299 
300         default:
301             pxiResult = PM_RESULT_ERROR;
302         }
303 
304         PMi_CallCallbackAndUnlock(pxiResult);
305         return;
306     }
307 
308 	switch( command )
309 	{
310 	    case SPI_PXI_COMMAND_PM_SLEEP_START:
311             // do nothing
312             break;
313 
314             //---- result for utility
315 		case SPI_PXI_COMMAND_PM_UTILITY:
316             if (PMi_Work.work)
317             {
318                 *(u16*)PMi_Work.work = (u16)pxiResult;
319             }
320             pxiResult = (u16)PM_RESULT_SUCCESS;
321 			break;
322 
323 			//---- sync with arm7
324 		case SPI_PXI_COMMAND_PM_SYNC:
325 			pxiResult = (u16)PM_RESULT_SUCCESS;
326             break;
327 
328 			//---- end of sleep
329 		case SPI_PXI_COMMAND_PM_SLEEP_END:
330 			PMi_SleepEndFlag = TRUE;
331 			break;
332 
333 #ifdef SDK_TWL
334 			// Send notification of power-down/reset from ARM7.
335 		case SPI_PXI_COMMAND_PM_NOTIFY:
336 			switch( pxiResult )
337 			{
338 				case PM_NOTIFY_POWER_SWITCH:
339 					OS_TPrintf("[ARM9] Pushed power button.\n" );
340 					PMi_ProceedToExit(PM_EXIT_FACTOR_PWSW);
341                     *(u32*)HW_RESET_LOCK_FLAG_BUF = PM_RESET_FLAG_FORCED;
342 					break;
343 
344 				case PM_NOTIFY_SHUTDOWN:
345 					OS_TPrintf("[ARM9] Shutdown\n" );
346 					// do nothing
347 					break;
348 
349 				case PM_NOTIFY_RESET_HARDWARE:
350 					OS_TPrintf("[ARM9] Reset Hardware\n" );
351 					// do nothing
352 					break;
353 				case PM_NOTIFY_BATTERY_LOW:
354 					OS_TPrintf("[ARM9] Battery low\n" );
355 					if ( PMi_BatteryLowCallbackInfo.callback )
356 					{
357 						(PMi_BatteryLowCallbackInfo.callback)(PMi_BatteryLowCallbackInfo.arg);
358 					}
359 					break;
360 				case PM_NOTIFY_BATTERY_EMPTY:
361 					OS_TPrintf("[ARM9] Battery empty\n" );
362 					PMi_ProceedToExit(PM_EXIT_FACTOR_BATTERY);
363                     *(u32*)HW_RESET_LOCK_FLAG_BUF = PM_RESET_FLAG_FORCED;
364 					break;
365 				default:
366 					OS_TPrintf("[ARM9] unknown %x\n", pxiResult );
367 					break;
368 			}
369 
370 			callCallback = FALSE;
371 			break;
372 
373 #endif	/* SDK_TWL */
374 	}
375 
376 	if ( callCallback )
377 	{
378 		PMi_CallCallbackAndUnlock(pxiResult);
379 	}
380 }
381 
382 //================================================================================
383 //           SEND COMMAND TO ARM7
384 //================================================================================
385 #define PMi_UNUSED_RESULT 0xffff0000  //value that should never be returned
386 
PMi_TryToSendPxiDataTillSuccess(u32 * sendData,int num)387 void PMi_TryToSendPxiDataTillSuccess( u32* sendData, int num  )
388 {
389     int n;
390     volatile u32 result;
391     while(1)
392     {
393         while(PMi_Lock())
394         {
395         }
396 
397         result = PMi_UNUSED_RESULT;
398 
399         //---- command
400         PMi_SetCallback(PMi_DummyCallback, (void*)&result);
401         for( n=0; n<num; n++ )
402         {
403             PMi_SendPxiData( sendData[n] );
404         }
405 
406         //----wait for finishing command
407         while(result == PMi_UNUSED_RESULT)
408         {
409         }
410         if ( result == SPI_PXI_RESULT_SUCCESS )
411         {
412             break;
413         }
414 
415         //---- wait
416         OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
417     }
418 }
419 
420 /*---------------------------------------------------------------------------*
421   Name:         PMi_SendSleepStart
422 
423   Description:  send SLEEP START command to ARM7
424 
425   Arguments:    trigger    : factors to wake up | backlight status to recover
426                 keyIntrData : key pattern and logic in waking up by key interrupt
427 
428   Returns:      result of issuing command
429                 always return PM_RESULT_SUCCESS
430  *---------------------------------------------------------------------------*/
PMi_SendSleepStart(u16 trigger,u16 keyIntrData)431 u32 PMi_SendSleepStart(u16 trigger, u16 keyIntrData)
432 {
433     u32 sendData[2];
434 
435     //---- send SYNC
436     sendData[0] =  PMi_MakeData1(SPI_PXI_START_BIT | SPI_PXI_END_BIT, 0, SPI_PXI_COMMAND_PM_SYNC, 0);
437     PMi_TryToSendPxiDataTillSuccess( sendData, 1 );
438 
439     //---- turn LCD off
440     while( PMi_SetLCDPower(PM_LCD_POWER_OFF, PM_LED_BLINK_LOW, FALSE, TRUE) != TRUE )
441     {
442         // no need to insert spinwait (because wait in PMi_SetLCDPower)
443     }
444 
445     //---- send SLEEP_START
446     sendData[0] = PMi_MakeData1(SPI_PXI_START_BIT, 0, SPI_PXI_COMMAND_PM_SLEEP_START, trigger);
447     sendData[1] = PMi_MakeData2(SPI_PXI_END_BIT,   1, keyIntrData);
448     PMi_TryToSendPxiDataTillSuccess( sendData, 2 );
449 
450     return PM_SUCCESS;
451 }
452 
453 /*---------------------------------------------------------------------------*
454   Name:         PM_SendUtilityCommandAsync / PM_SendUtilityCommand
455 
456   Description:  send utility command to ARM7
457 
458   Arguments:    number   : action number ( PM_UTIL_xxx in spi/common/pm_common.h )
459                 parameter : parameter for utility command
460                 callback: callback called in finishing proc
461                 arg: argument of callback
462 
463   Returns:      result of issuing command
464                 PM_RESULT_BUSY    : busy because other PM function uses SPI
465                 PM_RESULT_SUCCESS : success
466  *---------------------------------------------------------------------------*/
PM_SendUtilityCommandAsync(u32 number,u16 parameter,u16 * retValue,PMCallback callback,void * arg)467 u32 PM_SendUtilityCommandAsync(u32 number, u16 parameter, u16* retValue, PMCallback callback, void *arg)
468 {
469     //---- check whether locked
470     if (!PMi_Lock())
471     {
472         return PM_BUSY;
473     }
474     PMi_SetCallback(callback, arg);
475 	PMi_Work.work = (void*)retValue;
476 
477 	PMi_SendPxiData( PMi_MakeData1(SPI_PXI_START_BIT, 0, SPI_PXI_COMMAND_PM_UTILITY, number) );
478 	PMi_SendPxiData( PMi_MakeData2(SPI_PXI_END_BIT, 1, parameter) );
479 
480     return PM_SUCCESS;
481 }
482 
483 //---------------- sync version
PM_SendUtilityCommand(u32 number,u16 parameter,u16 * retValue)484 u32 PM_SendUtilityCommand(u32 number, u16 parameter, u16* retValue)
485 {
486     u32     commandResult;
487     u32     sendResult = PM_SendUtilityCommandAsync(number, parameter, retValue, PMi_DummyCallback, &commandResult);
488     if (sendResult == PM_SUCCESS)
489     {
490         PMi_WaitBusy();
491         return commandResult;
492     }
493     return sendResult;
494 }
495 
496 //================================================================================
497 //           ACTION ABOUT PMIC
498 //================================================================================
499 /*---------------------------------------------------------------------------*
500   Name:         PMi_SetLEDAsync / PMi_SetLED
501 
502   Description:  change LED status
503 
504   Arguments:    status : PM_LED_ON         : on
505                          PM_LED_BLINK_HIGH : blinking in high speed
506                          PM_LED_BLINK_LOW  : blinking in low speed
507                 callback: callback function
508                 arg: callback argument
509 
510   Returns:      result.
511                 PM_RESULT_SUCCESS : success to exec command
512                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
513  *---------------------------------------------------------------------------*/
514 //---------------- async version
PMi_SetLEDAsync(PMLEDStatus status,PMCallback callback,void * arg)515 u32 PMi_SetLEDAsync(PMLEDStatus status, PMCallback callback, void *arg)
516 {
517     u32     command;
518 
519     switch (status)
520     {
521     case PM_LED_ON:
522         command = PM_UTIL_LED_ON;
523         break;
524     case PM_LED_BLINK_HIGH:
525         command = PM_UTIL_LED_BLINK_HIGH_SPEED;
526         break;
527     case PM_LED_BLINK_LOW:
528         command = PM_UTIL_LED_BLINK_LOW_SPEED;
529         break;
530     default:
531         command = 0;
532     }
533 
534     return (command) ? PM_SendUtilityCommandAsync(command, 0, NULL, callback, arg) : PM_INVALID_COMMAND;
535 }
536 
537 //---------------- sync version
PMi_SetLED(PMLEDStatus status)538 u32 PMi_SetLED(PMLEDStatus status)
539 {
540     u32     commandResult;
541     u32     sendResult = PMi_SetLEDAsync(status, PMi_DummyCallback, &commandResult);
542     if (sendResult == PM_SUCCESS)
543     {
544         PMi_WaitBusy();
545         return commandResult;
546     }
547     return sendResult;
548 }
549 
550 /*---------------------------------------------------------------------------*
551   Name:         PM_SetBackLightAsync / PM_SetBackLight
552 
553   Description:  change backlight switch
554 
555   Arguments:    targer   : target LCD.
556                            PM_LCD_TOP    : top LCD
557                            PM_LCD_BOTTOM : bottom LCD
558                            PM_LCD_ALL    : top and bottom LCD
559                 sw : switch of top LCD.
560                            PM_BACKLIGHT_OFF : off
561                            PM_BACKLIGHT_ON  : on
562                 callback: callback function
563                 arg: callback argument
564 
565   Returns:      result.
566                 PM_RESULT_SUCCESS : success to exec command
567                 PM_INVALID_COMMAND : bad status given
568                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
569  *---------------------------------------------------------------------------*/
570 //---------------- async version
PM_SetBackLightAsync(PMLCDTarget target,PMBackLightSwitch sw,PMCallback callback,void * arg)571 u32 PM_SetBackLightAsync(PMLCDTarget target, PMBackLightSwitch sw, PMCallback callback, void *arg)
572 {
573     u32     command = 0;
574 
575     if (target == PM_LCD_TOP)
576     {
577         if (sw == PM_BACKLIGHT_ON)
578         {
579             command = PM_UTIL_LCD2_BACKLIGHT_ON;
580         }
581         if (sw == PM_BACKLIGHT_OFF)
582         {
583             command = PM_UTIL_LCD2_BACKLIGHT_OFF;
584         }
585     }
586     else if (target == PM_LCD_BOTTOM)
587     {
588         if (sw == PM_BACKLIGHT_ON)
589         {
590             command = PM_UTIL_LCD1_BACKLIGHT_ON;
591         }
592         if (sw == PM_BACKLIGHT_OFF)
593         {
594             command = PM_UTIL_LCD1_BACKLIGHT_OFF;
595         }
596     }
597     else if (target == PM_LCD_ALL)
598     {
599         if (sw == PM_BACKLIGHT_ON)
600         {
601             command = PM_UTIL_LCD12_BACKLIGHT_ON;
602         }
603         if (sw == PM_BACKLIGHT_OFF)
604         {
605             command = PM_UTIL_LCD12_BACKLIGHT_OFF;
606         }
607     }
608 
609     return (command) ? PM_SendUtilityCommandAsync(command, 0, NULL, callback, arg) : PM_INVALID_COMMAND;
610 }
611 
612 //---------------- sync version
PM_SetBackLight(PMLCDTarget target,PMBackLightSwitch sw)613 u32 PM_SetBackLight(PMLCDTarget target, PMBackLightSwitch sw)
614 {
615     u32     commandResult;
616     u32     sendResult = PM_SetBackLightAsync(target, sw, PMi_DummyCallback, &commandResult);
617     if (sendResult == PM_SUCCESS)
618     {
619         PMi_WaitBusy();
620         return commandResult;
621     }
622     return sendResult;
623 }
624 
625 /*---------------------------------------------------------------------------*
626   Name:         PMi_SetSoundPowerAsync / PMi_SetSoundPower
627 
628   Description:  change sound power switch
629 
630   Arguments:    sw : switch of sound power
631                           PM_SOUND_POWER_OFF : off
632                           PM_SOUND_POWER_ON  : on
633                 callback: callback function
634                 arg: callback argument
635 
636   Returns:      result.
637                 PM_RESULT_SUCCESS : success to exec command
638                 PM_INVALID_COMMAND : bad status given
639                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
640  *---------------------------------------------------------------------------*/
641 //---------------- async version
PMi_SetSoundPowerAsync(PMSoundPowerSwitch sw,PMCallback callback,void * arg)642 u32 PMi_SetSoundPowerAsync(PMSoundPowerSwitch sw, PMCallback callback, void *arg)
643 {
644     u32     command;
645 
646     switch (sw)
647     {
648     case PM_SOUND_POWER_ON:
649         command = PM_UTIL_SOUND_POWER_ON;
650         break;
651     case PM_SOUND_POWER_OFF:
652         command = PM_UTIL_SOUND_POWER_OFF;
653         break;
654     default:
655         command = 0;
656     }
657 
658     return (command) ? PM_SendUtilityCommandAsync(command, 0, NULL, callback, arg) : PM_INVALID_COMMAND;
659 }
660 
661 //---------------- sync version
PMi_SetSoundPower(PMSoundPowerSwitch sw)662 u32 PMi_SetSoundPower(PMSoundPowerSwitch sw)
663 {
664     u32     commandResult;
665     u32     sendResult = PMi_SetSoundPowerAsync(sw, PMi_DummyCallback, &commandResult);
666     if (sendResult == PM_SUCCESS)
667     {
668         PMi_WaitBusy();
669         return commandResult;
670     }
671     return sendResult;
672 }
673 
674 /*---------------------------------------------------------------------------*
675   Name:         PMi_SetSoundVolumeAsync / PMi_SetSoundVolume
676 
677   Description:  change sound volume control switch
678 
679   Arguments:    sw : switch of sound volume control
680                           PM_SOUND_VOLUME_ON  : on
681                           PM_SOUND_VOLUME_OFF : off
682                 callback: callback function
683                 arg: callback argument
684 
685   Returns:      result.
686                 PM_RESULT_SUCCESS : success to exec command
687                 PM_INVALID_COMMAND : bad status given
688                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
689  *---------------------------------------------------------------------------*/
690 //---------------- async version
PMi_SetSoundVolumeAsync(PMSoundVolumeSwitch sw,PMCallback callback,void * arg)691 u32 PMi_SetSoundVolumeAsync(PMSoundVolumeSwitch sw, PMCallback callback, void *arg)
692 {
693     u32     command;
694 
695     switch (sw)
696     {
697     case PM_SOUND_VOLUME_ON:
698         command = PM_UTIL_SOUND_VOL_CTRL_ON;
699         break;
700     case PM_SOUND_VOLUME_OFF:
701         command = PM_UTIL_SOUND_VOL_CTRL_OFF;
702         break;
703     default:
704         command = 0;
705     }
706 
707     return (command) ? PM_SendUtilityCommandAsync(command, 0, NULL, callback, arg) : PM_INVALID_COMMAND;
708 }
709 
710 //---------------- sync version
PMi_SetSoundVolume(PMSoundVolumeSwitch sw)711 u32 PMi_SetSoundVolume(PMSoundVolumeSwitch sw)
712 {
713     u32     commandResult;
714     u32     sendResult = PMi_SetSoundVolumeAsync(sw, PMi_DummyCallback, &commandResult);
715     if (sendResult == PM_SUCCESS)
716     {
717         PMi_WaitBusy();
718         return commandResult;
719     }
720     return sendResult;
721 }
722 
723 /*---------------------------------------------------------------------------*
724   Name:         PM_ForceToPowerOffAsync / PMi_ForceToPowerOff / PM_ForceToPowerOff
725 
726   Description:  force to turn off main power
727 
728   Arguments:    callback: callback function
729                 arg: callback argument
730 
731   Returns:      (PM_ForceToPowerOffAsync / PMi_ForceToPowerOff)
732                 result.
733                 PM_RESULT_SUCCESS : success to exec command
734                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
735 
736                 (PM_ForceToPowerOff)
737                 PM_RESULT_SUCCESS : success to exec command
738 
739                 If success, you may not be able to do anything because power is off.
740  *---------------------------------------------------------------------------*/
741 //---------------- async version
PM_ForceToPowerOffAsync(PMCallback callback,void * arg)742 u32 PM_ForceToPowerOffAsync(PMCallback callback, void *arg)
743 {
744 #ifdef SDK_TWL
745 	//---- set exit factors
746 	PMi_ExitFactor = PM_EXIT_FACTOR_USER;
747 #endif
748 
749 	//---- force to set LCD on avoid PMIC bug
750 	PMi_LCDOnAvoidReset();
751 
752 #ifdef SDK_TWL
753 	if ( OS_IsRunOnTwl() )
754 	{
755 		//---- call exit callbacks
756 		PMi_ExecuteList(PMi_PostExitCallbackList);
757 	}
758 #endif
759 
760     return PM_SendUtilityCommandAsync(PM_UTIL_FORCE_POWER_OFF, 0, NULL, callback, arg);
761 }
762 
763 //---------------- sync version
PMi_ForceToPowerOff(void)764 static u32 PMi_ForceToPowerOff(void)
765 {
766     u32     commandResult;
767     u32     sendResult = PM_ForceToPowerOffAsync(PMi_DummyCallback, &commandResult);
768     if (sendResult == PM_SUCCESS)
769     {
770         PMi_WaitBusyMethod = PMi_WAITBUSY_METHOD_CPSR | PMi_WAITBUSY_METHOD_IME;
771         PMi_WaitBusy();
772         PMi_WaitBusyMethod = PMi_WAITBUSY_METHOD_CPUMODE;
773         return commandResult;
774     }
775     return sendResult;
776 }
777 //---------------- wait version
PM_ForceToPowerOff(void)778 u32 PM_ForceToPowerOff(void)
779 {
780     while( PMi_ForceToPowerOff() != PM_RESULT_SUCCESS )
781     {
782         OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
783     }
784 
785     (void)OS_DisableInterrupts();
786 
787     //---- stop all dma
788     MI_StopAllDma();
789 #ifdef SDK_TWL
790 	if ( OS_IsRunOnTwl() )
791 	{
792 		MI_StopAllNDma();
793 	}
794 #endif
795 
796     //---- Loop intentionally
797     while (1)
798     {
799         OS_Halt();
800     }
801 
802     //---- just avoid warning
803     return PM_RESULT_SUCCESS;
804 }
805 
806 /*---------------------------------------------------------------------------*
807   Name:         PM_SetAmpAsync / PM_SetAmp
808 
809   Description:  switch amp
810 
811   Arguments:    sw : switch of programmable gain amp
812                           PM_AMP_ON   : on
813                           PM_AMP_OFF  : off
814                 callback: callback function
815                 arg: callback argument
816 
817   Returns:      result.
818                 PM_RESULT_SUCCESS : success to exec command
819                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
820  *---------------------------------------------------------------------------*/
821 //---------------- async version
PM_SetAmpAsync(PMAmpSwitch status,PMCallback callback,void * arg)822 u32 PM_SetAmpAsync(PMAmpSwitch status, PMCallback callback, void *arg)
823 {
824 	return PM_SendUtilityCommandAsync(PM_UTIL_SET_AMP, (u16)status, NULL, callback, arg );
825 }
826 
827 //---------------- sync version
PM_SetAmp(PMAmpSwitch status)828 u32 PM_SetAmp(PMAmpSwitch status)
829 {
830     //---- remember mic power flag
831     sAmpSwitch = status;
832     return PMi_SetAmp(status);
833 }
834 
835 //---------------- sync version
PMi_SetAmp(PMAmpSwitch status)836 static u32 PMi_SetAmp(PMAmpSwitch status)
837 {
838     if (PM_GetLCDPower())
839     {
840 		//---- change amp status in case of LCD-ON only
841 		return PM_SendUtilityCommand(PM_UTIL_SET_AMP, (u16)status, NULL );
842 	}
843 	else
844 	{
845 		return PM_RESULT_SUCCESS;
846 	}
847 }
848 
849 /*---------------------------------------------------------------------------*
850   Name:         PM_SetAmpGainAsync / PM_SetAmpGain
851 
852   Description:  change amp gain
853 
854   Arguments:    gain      : gain
855                           PM_AMPGAIN_20   : gain=20
856                           PM_AMPGAIN_40   : gain=40
857                           PM_AMPGAIN_80   : gain=80
858                           PM_AMPGAIN_160  : gain=160
859                 callback: callback function
860                 arg: callback argument
861 
862   Returns:      result.
863                 PM_RESULT_SUCCESS : success to exec command
864                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
865  *---------------------------------------------------------------------------*/
866 //---------------- async version
PM_SetAmpGainAsync(PMAmpGain gain,PMCallback callback,void * arg)867 u32 PM_SetAmpGainAsync(PMAmpGain gain, PMCallback callback, void *arg)
868 {
869 	return PM_SendUtilityCommandAsync(PM_UTIL_SET_AMPGAIN, (u16)gain, NULL, callback, arg );
870 }
871 
872 //---------------- sync version
PM_SetAmpGain(PMAmpGain gain)873 u32 PM_SetAmpGain(PMAmpGain gain)
874 {
875 	return PM_SendUtilityCommand(PM_UTIL_SET_AMPGAIN, (u16)gain, NULL );
876 }
877 
878 #ifdef SDK_TWL
879 /*---------------------------------------------------------------------------*
880   Name:         PM_SetAmpGainLevelAsync / PM_SetAmpGainLevel
881 
882   Description:  change amp gain
883 
884   Arguments:    level:  Gain. Range is 0 - 119 (0dB - 59.5dB).
885                            (119 is defined as PM_AMPGAIN_LEVEL_MAX)
886 
887                 callback: callback function
888                 arg: callback argument
889 
890   Returns:      result.
891                 PM_RESULT_SUCCESS : success to exec command
892                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
893  *---------------------------------------------------------------------------*/
894 //---------------- async version
PM_SetAmpGainLevelAsync(u8 level,PMCallback callback,void * arg)895 u32 PM_SetAmpGainLevelAsync(u8 level, PMCallback callback, void *arg)
896 {
897 	SDK_ASSERT( level <= PM_AMPGAIN_LEVEL_MAX );
898 	return PM_SendUtilityCommandAsync(PM_UTIL_SET_AMPGAIN_LEVEL, (u16)level, NULL, callback, arg );
899 }
900 
901 //---------------- sync version
PM_SetAmpGainLevel(u8 level)902 u32 PM_SetAmpGainLevel(u8 level)
903 {
904 	SDK_ASSERT( level <= PM_AMPGAIN_LEVEL_MAX );
905 	return PM_SendUtilityCommand(PM_UTIL_SET_AMPGAIN_LEVEL, (u16)level, NULL );
906 }
907 #endif
908 
909 //================================================================================
910 //           GET STATUS FROM ARM7
911 //================================================================================
912 /*---------------------------------------------------------------------------*
913   Name:         PM_GetBattery
914 
915   Description:  get battery status
916 
917   Arguments:    batteryBuf  : buffer to store result
918 
919   Returns:      result.
920                 PM_RESULT_SUCCESS : success to exec command
921                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
922  *---------------------------------------------------------------------------*/
PM_GetBattery(PMBattery * batteryBuf)923 u32 PM_GetBattery(PMBattery *batteryBuf)
924 {
925 	u16 status;
926 	u32 result = PM_SendUtilityCommand(PM_UTIL_GET_STATUS, PM_UTIL_PARAM_BATTERY, &status);
927 
928 	if ( result == PM_RESULT_SUCCESS )
929 	{
930 		if (batteryBuf)
931 		{
932 			*batteryBuf = status? PM_BATTERY_LOW: PM_BATTERY_HIGH;
933 		}
934 	}
935 	return result;
936 }
937 
938 /*---------------------------------------------------------------------------*
939   Name:         PM_GetBatteryLevel
940 
941   Description:  Gets battery level.
942 
943   Arguments:    levelBuf:  buffer to store result
944                      The range of values is from PM_BATTERY_LEVEL_MIN to PM_BATTERY_LEVEL_MAX.
945 
946   Returns:      result.
947                 PM_RESULT_SUCCESS : success to exec command
948                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
949                 PM_RESULT_ERROR    : cannot use this function (running in NITRO mode).
950  *---------------------------------------------------------------------------*/
951 #ifdef SDK_TWL
952 #include <twl/ltdmain_begin.h>
PMi_GetBatteryLevelCore(PMBatteryLevel * levelBuf)953 static u32 PMi_GetBatteryLevelCore(PMBatteryLevel *levelBuf)
954 {
955     u16 status;
956     u32 result = PM_SendUtilityCommand(PM_UTIL_GET_STATUS, PM_UTIL_PARAM_BATTERY_LEVEL, &status);
957 
958     if ( result == PM_RESULT_SUCCESS )
959     {
960         if (levelBuf)
961         {
962             *levelBuf = (PMBatteryLevel)status;
963         }
964     }
965     return result;
966 }
967 #include <twl/ltdmain_end.h>
968 
PM_GetBatteryLevel(PMBatteryLevel * levelBuf)969 u32 PM_GetBatteryLevel(PMBatteryLevel *levelBuf)
970 {
971 	if ( OS_IsRunOnTwl() )
972 	{
973 		return PMi_GetBatteryLevelCore(levelBuf);
974 	}
975 	else
976 	{
977 		return PM_RESULT_ERROR;
978 	}
979 }
980 
981 #endif
982 
983 /*---------------------------------------------------------------------------*
984   Name:         PM_GetACAdapter
985 
986   Description:  Checks whether AC power adaptor is connected.
987 
988   Arguments:    isConnectedBuf:  buffer to store result
989                        TRUE: Connected.
990                        FALSE: Not connected.
991 
992   Returns:      result.
993                 PM_RESULT_SUCCESS : success to exec command
994                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
995                 PM_RESULT_ERROR    : cannot use this function (running in NITRO mode).
996  *---------------------------------------------------------------------------*/
997 #ifdef SDK_TWL
998 
999 #include <twl/ltdmain_begin.h>
PMi_GetACAdapterCore(BOOL * isConnectedBuf)1000 static u32 PMi_GetACAdapterCore(BOOL *isConnectedBuf)
1001 {
1002     u16 status;
1003     u32 result = PM_SendUtilityCommand(PM_UTIL_GET_STATUS, PM_UTIL_PARAM_AC_ADAPTER, &status);
1004 
1005     if ( result == PM_RESULT_SUCCESS )
1006     {
1007         if (isConnectedBuf)
1008         {
1009             *isConnectedBuf = status? TRUE: FALSE;
1010         }
1011     }
1012     return result;
1013 }
1014 #include <twl/ltdmain_end.h>
1015 
PM_GetACAdapter(BOOL * isConnectedBuf)1016 u32 PM_GetACAdapter(BOOL *isConnectedBuf)
1017 {
1018 	if ( OS_IsRunOnTwl() )
1019 	{
1020 		return PMi_GetACAdapterCore(isConnectedBuf);
1021 	}
1022 	else
1023 	{
1024 		return PM_RESULT_ERROR;
1025 	}
1026 }
1027 #endif
1028 
1029 /*---------------------------------------------------------------------------*
1030   Name:         PM_GetBackLight
1031 
1032   Description:  get backlight status
1033 
1034   Arguments:    top    : buffer to set result of top LCD
1035                 bottom : buffer to set result of bottom LCD
1036 
1037   Returns:      result.
1038                 PM_RESULT_SUCCESS : success to exec command
1039                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
1040  *---------------------------------------------------------------------------*/
PM_GetBackLight(PMBackLightSwitch * top,PMBackLightSwitch * bottom)1041 u32 PM_GetBackLight(PMBackLightSwitch *top, PMBackLightSwitch *bottom)
1042 {
1043 	u16 status;
1044 	u32 result = PM_SendUtilityCommand(PM_UTIL_GET_STATUS, PM_UTIL_PARAM_BACKLIGHT, &status);
1045 
1046 	if ( result == PM_RESULT_SUCCESS )
1047 	{
1048 		if (top)
1049 		{
1050             *top = (status & PMIC_CTL_BKLT2) ? PM_BACKLIGHT_ON : PM_BACKLIGHT_OFF;
1051 		}
1052 		if (bottom)
1053 		{
1054             *bottom = (status & PMIC_CTL_BKLT1) ? PM_BACKLIGHT_ON : PM_BACKLIGHT_OFF;
1055 		}
1056 	}
1057     return result;
1058 }
1059 
1060 /*---------------------------------------------------------------------------*
1061   Name:         PMi_GetSoundPower
1062 
1063   Description:  get status of sound power switch
1064 
1065   Arguments:    swBuf  : buffer to store result
1066 
1067   Returns:      result.
1068                 PM_RESULT_SUCCESS : success to exec command
1069                 PM_RESULT_ERROR    : some error occurred in ARM7
1070  *---------------------------------------------------------------------------*/
PMi_GetSoundPower(PMSoundPowerSwitch * swBuf)1071 u32 PMi_GetSoundPower(PMSoundPowerSwitch *swBuf)
1072 {
1073 	u16 status;
1074 	u32 result = PM_SendUtilityCommand(PM_UTIL_GET_STATUS, PM_UTIL_PARAM_SOUND_POWER, &status);
1075 
1076 	if ( result == PM_RESULT_SUCCESS )
1077 	{
1078 		if (swBuf)
1079 		{
1080             *swBuf = status? PM_SOUND_POWER_ON : PM_SOUND_POWER_OFF;
1081 		}
1082 	}
1083     return result;
1084 }
1085 
1086 /*---------------------------------------------------------------------------*
1087   Name:         PMi_GetSoundVolume
1088 
1089   Description:  get status of sound volume control switch
1090 
1091   Arguments:    swBuf  : buffer to store result
1092 
1093   Returns:      result.
1094                 PM_RESULT_SUCCESS : success to exec command
1095                 PM_RESULT_ERROR    : some error occurred in ARM7
1096  *---------------------------------------------------------------------------*/
PMi_GetSoundVolume(PMSoundVolumeSwitch * swBuf)1097 u32 PMi_GetSoundVolume(PMSoundVolumeSwitch *swBuf)
1098 {
1099 	u16 status;
1100 	u32 result = PM_SendUtilityCommand(PM_UTIL_GET_STATUS, PM_UTIL_PARAM_SOUND_VOLUME, &status);
1101 
1102 	if ( result == PM_RESULT_SUCCESS )
1103 	{
1104 		if (swBuf)
1105 		{
1106 			*swBuf = status? PM_SOUND_VOLUME_ON : PM_SOUND_VOLUME_OFF;
1107 		}
1108 	}
1109     return result;
1110 }
1111 
1112 /*---------------------------------------------------------------------------*
1113   Name:         PM_GetAmp
1114 
1115   Description:  get status of amp switch
1116 
1117   Arguments:    swBuf  : buffer to store result
1118 
1119   Returns:      result.
1120                 PM_RESULT_SUCCESS : success to exec command
1121                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
1122  *---------------------------------------------------------------------------*/
PM_GetAmp(PMAmpSwitch * swBuf)1123 u32 PM_GetAmp(PMAmpSwitch *swBuf)
1124 {
1125 	u16 status;
1126 	u32 result = PM_SendUtilityCommand(PM_UTIL_GET_STATUS, PM_UTIL_PARAM_AMP, &status);
1127 
1128 	if ( result == PM_RESULT_SUCCESS )
1129 	{
1130 		if (swBuf)
1131 		{
1132 			*swBuf = status? PM_AMP_ON: PM_AMP_OFF;
1133 		}
1134 	}
1135     return result;
1136 }
1137 
1138 /*---------------------------------------------------------------------------*
1139   Name:         PM_GetAmpGain
1140 
1141   Description:  get status of amp gain
1142 
1143   Arguments:    gainBuf  : buffer to store result
1144 
1145   Returns:      result.
1146                 PM_RESULT_SUCCESS : success to exec command
1147                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
1148  *---------------------------------------------------------------------------*/
PM_GetAmpGain(PMAmpGain * gainBuf)1149 u32 PM_GetAmpGain(PMAmpGain *gainBuf)
1150 {
1151 	u16 status;
1152 	u32 result = PM_SendUtilityCommand(PM_UTIL_GET_STATUS, PM_UTIL_PARAM_AMPGAIN, &status);
1153 
1154 	if ( result == PM_RESULT_SUCCESS )
1155 	{
1156 		if (gainBuf)
1157 		{
1158 			*gainBuf = (PMAmpGain)status;
1159 		}
1160 	}
1161     return result;
1162 }
1163 
1164 #ifdef SDK_TWL
1165 /*---------------------------------------------------------------------------*
1166   Name:         PM_GetAmpGainLevel
1167 
1168   Description:  Gets level of amp gain.
1169 
1170   Arguments:    levelBuf:  buffer to store result
1171 
1172   Returns:      result.
1173                 PM_RESULT_SUCCESS : success to exec command
1174                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
1175  *---------------------------------------------------------------------------*/
PM_GetAmpGainLevel(u8 * levelBuf)1176 u32 PM_GetAmpGainLevel(u8 *levelBuf)
1177 {
1178 	u16 status;
1179 	u32 result = PM_SendUtilityCommand(PM_UTIL_GET_STATUS, PM_UTIL_PARAM_AMPGAIN_LEVEL, &status);
1180 
1181 	if ( result == PM_RESULT_SUCCESS )
1182 	{
1183 		if (levelBuf)
1184 		{
1185 			*levelBuf = (u8)status;
1186 		}
1187 	}
1188 	return result;
1189 }
1190 #endif
1191 
1192 //================================================================================
1193 //           WIRELESS LED
1194 //================================================================================
1195 #ifdef SDK_TWL
1196 /*---------------------------------------------------------------------------*
1197   Name:         PMi_SetWirelessLED
1198 
1199   Description:  get status of amp gain
1200 
1201   Arguments:    sw : PM_WIRELESS_LED_ON  ... ON
1202                      PM_WIRELESS_LED_OFF ... OFF
1203 
1204   Returns:      result.
1205                 PM_RESULT_SUCCESS : success to exec command
1206                 PM_RESULT_ERROR    : some error occurred in ARM7
1207  *---------------------------------------------------------------------------*/
PMi_SetWirelessLED(PMWirelessLEDStatus sw)1208 u32 PMi_SetWirelessLED( PMWirelessLEDStatus sw )
1209 {
1210 	return PM_SendUtilityCommand( PM_UTIL_WIRELESS_LED, (u16)sw, NULL );
1211 }
1212 #endif  //ifdef SDK_TWL
1213 
1214 //================================================================================
1215 //           SEND DATA TO ARM7
1216 //================================================================================
1217 /*---------------------------------------------------------------------------*
1218   Name:         PMi_SendPxiData
1219 
1220   Description:  send data via PXI
1221 
1222   Arguments:    data: data to send
1223 
1224   Returns:      None.
1225  *---------------------------------------------------------------------------*/
PMi_SendPxiData(u32 data)1226 void PMi_SendPxiData(u32 data)
1227 {
1228     while (PXI_SendWordByFifo(PXI_FIFO_TAG_PM, data, FALSE) != PXI_FIFO_SUCCESS)
1229     {
1230         // do nothing
1231     }
1232 }
1233 
1234 //================================================================================
1235 //           SLEEP
1236 //================================================================================
1237 /*---------------------------------------------------------------------------*
1238   Name:         PMi_PreSleepForDma
1239 
1240   Description:  Gets ready DMA to sleep mode.
1241 
1242   Arguments:    None.
1243 
1244   Returns:      None.
1245  *---------------------------------------------------------------------------*/
1246 #ifdef SDK_TWL
1247 #include <twl/ltdmain_begin.h>
PMi_PreSleepForNdma(u32 i)1248 static void PMi_PreSleepForNdma(u32 i)
1249 {
1250     vu32 *ndmaCntp = (vu32*)MI_NDMA_REGADDR(i, MI_NDMA_REG_CNT_WOFFSET);
1251     if ( *ndmaCntp & MI_NDMA_IMM_MODE_ON )
1252     {
1253         // Normally when starting up a new DMA, the continuous mode setting is invalid
1254         MI_WaitNDma(i);
1255         return;
1256     }
1257     switch ( *ndmaCntp & MI_NDMA_TIMING_MASK )
1258     {
1259         case MI_NDMA_TIMING_CARD:
1260             // Card DMA is normally in continuous mode
1261             // DMA will not restart if there is a wait for the memory controller to stop
1262             while (reg_MI_MCCNT1 & REG_MI_MCCNT1_START_MASK)
1263             {
1264             }
1265             break;
1266         case MI_NDMA_TIMING_DISP_MMEM:
1267         case MI_NDMA_TIMING_DISP:
1268             // The main memory display DMA and the display synch DMA stop after completion of one screen of DMA, even in continuous mode
1269             //
1270             MI_WaitNDma(i);
1271         case MI_NDMA_TIMING_CAMERA:
1272             // Once the camera enters standby mode, the camera DMA does not complete even if execution waits, so it is forced to stop
1273             //
1274             //   CAMERA_DmaPipeInfinity is continuous mode
1275             //   CAMERA_DmaRecv* are normal mode
1276             MI_StopNDma(i);
1277             break;
1278         default:
1279             // If not in continuous mode, wait for completion of DMA
1280             if ( ! (*ndmaCntp & MI_NDMA_CONTINUOUS_ON) )
1281             {
1282                 MI_WaitNDma(i);
1283             }
1284             // If in continuous mode, force DMA to stop
1285             // MI_NDMA_TIMING_TIMER0 through MI_NDMA_TIMING_TIMER3 (These exist because if it is forced to resume, it will start from the beginning and not do what the user intended)
1286             // MI_NDMA_TIMING_V_BLANK (MI_DMA_CONTINUOUS_ON is not yet used with publicly disclosed functions)
1287             // MI_NDMA_TIMING_H_BLANK  (MI_DMA_CONTINUOUS_ON is used with publicly disclosed functions, but if neglected, a buffer overrun will occur)
1288             // MI_NDMA_TIMING_GXFIFO (MI_DMA_CONTINUOUS_ON is not yet used with publicly disclosed functions)
1289             else
1290             {
1291                 MI_StopNDma(i);
1292                 SDK_WARNING( FALSE, "[ARM9] Force to stop NDMA%d before sleep.", i );
1293             }
1294             break;
1295     }
1296 }
1297 #include <twl/ltdmain_end.h>
1298 #endif
PMi_PreSleepForDma(void)1299 static void PMi_PreSleepForDma(void)
1300 {
1301     u32 i;
1302 
1303     for (i=0; i<=MI_DMA_MAX_NUM; i++)
1304     {
1305         // Old DMA
1306         {
1307             vu32 *dmaCntp = (vu32*)MI_DMA_REGADDR(i, MI_DMA_REG_CNT_WOFFSET);
1308 
1309             PMi_PreDmaCnt[i] = *dmaCntp;
1310 
1311             switch ( *dmaCntp & MI_DMA_TIMING_MASK )
1312             {
1313                 case MI_DMA_TIMING_CARD:
1314                     // Card DMA is normally in continuous mode
1315                     // DMA will not restart if there is a wait for the memory controller to stop
1316                     while (reg_MI_MCCNT1 & REG_MI_MCCNT1_START_MASK)
1317                     {
1318                     }
1319                     break;
1320                 case MI_DMA_TIMING_DISP_MMEM:
1321                 case MI_DMA_TIMING_DISP:
1322                     // The main memory display DMA and the display synch DMA stop after completion of one screen of DMA, even in continuous mode
1323                     //
1324                     MI_WaitDma(i);
1325                     break;
1326                 default:
1327                     // If not in continuous mode, wait for completion of DMA
1328                     if ( ! (*dmaCntp & MI_DMA_CONTINUOUS_ON) )
1329                     {
1330                         MI_WaitDma(i);
1331                     }
1332                     // If in continuous mode, force DMA to stop
1333                     // MI_DMA_TIMING_IMM  (when used with MI_DMA_CONTINUOUS_ON, the CPU cannot operate and runs out of control)
1334                     // MI_DMA_TIMING_V_BLANK (MI_DMA_CONTINUOUS_ON is not yet used with publicly disclosed functions)
1335                     // MI_DMA_TIMING_H_BLANK (MI_DMA_CONTINUOUS_ON is used with publicly disclosed functions, but if neglected, a buffer overrun will occur)
1336                     // MI_DMA_TIMING_CARTRIDGE  (Even if using MI_DMA_CONTINUOUS_ON, resetting is necessary because DMA requests during sleep are cancelled)
1337                     // MI_DMA_TIMING_GXFIFO (MI_DMA_CONTINUOUS_ON is not yet used with publicly disclosed functions)
1338                     else
1339                     {
1340                         MI_StopDma(i);
1341                         SDK_WARNING( FALSE, "[ARM9] Force to stop DMA%d before sleep.", i );
1342                     }
1343                     break;
1344             }
1345         }
1346 #ifdef SDK_TWL
1347         // New DMA
1348         if (OS_IsRunOnTwl())
1349         {
1350             PMi_PreSleepForNdma(i);
1351         }
1352 #endif // SDK_TWL
1353     }
1354 }
1355 /*---------------------------------------------------------------------------*
1356   Name:         PMi_PostSleepForDma
1357 
1358   Description:  Resumes DMA from sleep mode.
1359 
1360   Arguments:    None.
1361 
1362   Returns:      None.
1363  *---------------------------------------------------------------------------*/
1364 #ifdef SDK_TWL
1365 #include <twl/ltdmain_begin.h>
PMi_PostSleepForNdma(u32 i)1366 static void PMi_PostSleepForNdma(u32 i)
1367 {
1368     vu32 *ndmaCntp = (vu32*)MI_NDMA_REGADDR(i, MI_NDMA_REG_CNT_WOFFSET);
1369     if ( *ndmaCntp & MI_NDMA_IMM_MODE_ON )
1370     {
1371         // Normally when starting up a new DMA, the continuous mode setting is invalid
1372         return;
1373     }
1374     switch ( *ndmaCntp & MI_NDMA_TIMING_MASK )
1375     {
1376         case MI_NDMA_TIMING_V_BLANK:
1377         case MI_NDMA_TIMING_H_BLANK:
1378             // If in continuous mode, restart DMA (for testing)
1379             if ( *ndmaCntp & MI_NDMA_CONTINUOUS_ON )
1380             {
1381                 *ndmaCntp |= MI_NDMA_ENABLE;
1382             }
1383             break;
1384     }
1385 }
1386 #include <twl/ltdmain_end.h>
1387 #endif
PMi_PostSleepForDma(void)1388 static void PMi_PostSleepForDma(void)
1389 {
1390     u32 i;
1391 
1392     for (i=0; i<=MI_DMA_MAX_NUM; i++)
1393     {
1394         // Old DMA
1395         {
1396             vu32 *dmaCntp = (vu32*)MI_DMA_REGADDR(i, MI_DMA_REG_CNT_WOFFSET);
1397             u32 preCnt = PMi_PreDmaCnt[i];
1398 
1399             switch ( preCnt & MI_DMA_TIMING_MASK )
1400             {
1401                 case MI_DMA_TIMING_V_BLANK:
1402                 case MI_DMA_TIMING_H_BLANK:
1403                 case MI_DMA_TIMING_CARTRIDGE:
1404                     // If in continuous mode, restart DMA (for testing)
1405                     if ( preCnt & MI_DMA_CONTINUOUS_ON )
1406                     {
1407                         *dmaCntp = preCnt;
1408                     }
1409                     break;
1410             }
1411         }
1412 #ifdef SDK_TWL
1413         // New DMA
1414         if (OS_IsRunOnTwl())
1415         {
1416             PMi_PostSleepForNdma(i);
1417         }
1418 #endif // SDK_TWL
1419     }
1420 }
1421 
1422 /*---------------------------------------------------------------------------*
1423   Name:         PM_GoSleepMode
1424 
1425   Description:  go to be in sleep mode
1426 
1427   Arguments:    trigger    : factors to return from being on sleep
1428                 logic: key logic to key interrupt
1429                              PM_PAD_LOGIC_AND : occur interrupt at all specified button pushed
1430                              PM_PAD_LOGIC_OR  : occur interrupt at one of specified buttons pushed
1431                 keyPattern : keys to wakeup
1432 
1433   Returns:      None.
1434  *---------------------------------------------------------------------------*/
PM_GoSleepMode(PMWakeUpTrigger trigger,PMLogic logic,u16 keyPattern)1435 void PM_GoSleepMode(PMWakeUpTrigger trigger, PMLogic logic, u16 keyPattern)
1436 {
1437     BOOL    prepIrq;                   // IME
1438     OSIntrMode prepIntrMode;           // CPSR-IRQ
1439     OSIrqMask prepIntrMask;            // IE
1440     BOOL    powerOffFlag = FALSE;
1441 
1442     PMBackLightSwitch preTop;
1443     PMBackLightSwitch preBottom;
1444 
1445     u32     preGX;
1446     u32     preGXS;
1447     PMLCDPower preLCDPower;
1448 
1449     //---- call pre-callbacks
1450     PMi_ExecuteList(PMi_PreSleepCallbackList);
1451 
1452     //---- disable all interrupt
1453     prepIrq = OS_DisableIrq();
1454     prepIntrMode = OS_DisableInterrupts();
1455     prepIntrMask = OS_DisableIrqMask( OS_IE_MASK_ALL );
1456 
1457     //---- interrupt setting
1458 	{
1459 		// enable PXI from ARM7 and TIMER0(if needed)
1460 		OSIntrMode intr = OS_IE_FIFO_RECV | (OS_IsTickAvailable()? OS_IE_TIMER0: 0 );
1461 		(void)OS_SetIrqMask( intr );
1462 	}
1463     (void)OS_RestoreInterrupts(prepIntrMode);
1464     (void)OS_EnableIrq();
1465 
1466     //---- check card trigger
1467     if (trigger & PM_TRIGGER_CARD)
1468     {
1469 		OSBootType type = OS_GetBootType();
1470 		//---- if multiboot child or NAND application, ignore card check flag
1471 		if ( type == OS_BOOTTYPE_DOWNLOAD_MB || type == OS_BOOTTYPE_NAND )
1472 		{
1473             trigger &= ~PM_TRIGGER_CARD;
1474 		}
1475     }
1476 
1477     //---- check cartridge trigger
1478     if (trigger & PM_TRIGGER_CARTRIDGE)
1479     {
1480         //---- if running on TWL or cartridge does not exist, ignore cartridge check flag
1481         if ( OS_IsRunOnTwl() || !CTRDG_IsExisting() )
1482         {
1483             trigger &= ~PM_TRIGGER_CARTRIDGE;
1484         }
1485     }
1486 
1487     //---- remember gx state
1488     preGX = reg_GX_DISPCNT;
1489     preGXS = reg_GXS_DB_DISPCNT;
1490     preLCDPower = PM_GetLCDPower();
1491 
1492     //---- set backlight off
1493     while( PM_GetBackLight(&preTop, &preBottom) != PM_RESULT_SUCCESS )
1494     {
1495         OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
1496     }
1497     while( PM_SetBackLight(PM_LCD_ALL, PM_BACKLIGHT_OFF) != PM_RESULT_SUCCESS )
1498     {
1499         OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
1500     }
1501 
1502     //---- wait a few frames after backlight off for avoiding appearance of afterimage
1503     {
1504         vu32    vcount = OS_GetVBlankCount();
1505         while (vcount == OS_GetVBlankCount())
1506         {
1507         }
1508         vcount = OS_GetVBlankCount();
1509 
1510         reg_GX_DISPCNT = reg_GX_DISPCNT & ~REG_GX_DISPCNT_MODE_MASK;    // main screen off
1511         GXS_DispOff();
1512 
1513         while (vcount == OS_GetVBlankCount())
1514         {
1515         }
1516         vcount = OS_GetVBlankCount();
1517         while (vcount == OS_GetVBlankCount())
1518         {
1519         }
1520     }
1521 
1522     PMi_PreSleepForDma();
1523 
1524     //---- send SLEEP_START command to ARM7
1525 	PMi_SleepEndFlag = FALSE;
1526     {
1527         u16     param = (u16)(trigger
1528 							  | (preTop? PM_BACKLIGHT_RECOVER_TOP_ON: PM_BACKLIGHT_RECOVER_TOP_OFF)
1529 							  | (preBottom? PM_BACKLIGHT_RECOVER_BOTTOM_ON: PM_BACKLIGHT_RECOVER_BOTTOM_OFF));
1530 
1531         (void)PMi_SendSleepStart(param, (u16)(logic | keyPattern));
1532     }
1533 
1534     //==== Halt ================
1535 	while( ! PMi_SleepEndFlag )
1536 	{
1537 		OS_Halt();
1538 	}
1539     //==========================
1540 
1541     //---- check card remove
1542     if ((trigger & PM_TRIGGER_CARD) && (OS_GetRequestIrqMask() & OS_IE_CARD_IREQ))
1543     {
1544         powerOffFlag = TRUE;
1545     }
1546 
1547     //---- turn LCD on, and restore gx state
1548     if (!powerOffFlag)
1549     {
1550         if (preLCDPower == PM_LCD_POWER_ON)
1551         {
1552             while( PMi_SetLCDPower(PM_LCD_POWER_ON, PM_LED_ON, TRUE, TRUE) != TRUE )
1553             {
1554                 // no need to insert spinwait (because wait in PMi_SetLCDPower)
1555             }
1556         }
1557         else
1558         {
1559             while( PMi_SetLED(PM_LED_ON) != PM_RESULT_SUCCESS )
1560             {
1561                 OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
1562             }
1563         }
1564 
1565         reg_GX_DISPCNT = preGX;
1566         reg_GXS_DB_DISPCNT = preGXS;
1567     }
1568 
1569 	//---- wait while specified period for LCD (0x360000sysClock == about 106ms)
1570     OS_SpinWaitSysCycles(PMi_LCD_WAIT_SYS_CYCLES);
1571 
1572     //---- restore all interrupts
1573     (void)OS_DisableInterrupts();
1574     (void)OS_SetIrqMask(prepIntrMask);
1575     (void)OS_RestoreInterrupts(prepIntrMode);
1576     (void)OS_RestoreIrq(prepIrq);
1577 
1578     //---- power off if needed
1579     if (powerOffFlag)
1580     {
1581         (void)PM_ForceToPowerOff();
1582     }
1583 
1584     //---- call post-callbacks
1585     PMi_ExecuteList(PMi_PostSleepCallbackList);
1586 }
1587 
1588 //================================================================================
1589 //             LCD
1590 //================================================================================
1591 /*---------------------------------------------------------------------------*
1592   Name:         PMi_SetLCDPower
1593 
1594   Description:  turn on/off LCD power
1595 
1596   Arguments:    sw : switch
1597                    PM_LCD_POWER_ON : on
1598                    PM_LCD_POWER_ON : off
1599                 led : LED status
1600                    PM_LED_NONE : not touch
1601                    PM_LED_ON
1602                    PM_LED_BLINK_HIGH
1603                    PM_LED_BLINK_LOW
1604                 skip : whether skip wait
1605                    TRUE: skip
1606                    FALSE: wait
1607                 isSync: whether this function is sync version
1608                    TRUE: sync
1609                    FALSE: async
1610 
1611   Returns:      TRUE   if success
1612                 FALSE  if fail
1613  *---------------------------------------------------------------------------*/
1614 #define PMi_WAIT_FRAME_AFTER_LCDOFF  7
1615 #define PMi_WAIT_FRAME_AFTER_GXDISP  2
1616 
PMi_SetLCDPower(PMLCDPower sw,PMLEDStatus led,BOOL skip,BOOL isSync)1617 BOOL PMi_SetLCDPower(PMLCDPower sw, PMLEDStatus led, BOOL skip, BOOL isSync)
1618 {
1619     switch (sw)
1620     {
1621     case PM_LCD_POWER_ON:
1622         // compare with counter in which LCD power was turned off.
1623         //     the reason of waiting 100ms: The interval switching LCD power
1624         //     from OFF to ON must be more than 100ms. if short than that,
1625         //     PMIC will be shut down and never recover itself.
1626         if (!skip && OS_GetVBlankCount() - PMi_LCDCount <= PMi_WAIT_FRAME_AFTER_LCDOFF)
1627         {
1628             return FALSE;
1629         }
1630 
1631         //---- LED
1632         if (led != PM_LED_NONE)
1633         {
1634             if (isSync)
1635             {
1636                 while( PMi_SetLED(led) != PM_RESULT_SUCCESS )
1637                 {
1638                     OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
1639                 }
1640             }
1641             else
1642             {
1643                 while( PMi_SetLEDAsync(led, NULL, NULL) != PM_RESULT_SUCCESS )
1644                 {
1645                     OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
1646                 }
1647             }
1648         }
1649 
1650         (void)GXi_PowerLCD(TRUE);
1651 
1652 		//---- recover mic power flag
1653 		while( PMi_SetAmp(sAmpSwitch) != PM_RESULT_SUCCESS )
1654         {
1655             OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
1656         }
1657         break;
1658 
1659     case PM_LCD_POWER_OFF:
1660 		//---- force to turn mic power off
1661         while( PMi_SetAmp(PM_AMP_OFF) != PM_RESULT_SUCCESS )
1662         {
1663             OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
1664         }
1665 
1666 		//---- need 2 VBlank after GX_DispOff()
1667 		if ( OS_GetVBlankCount() - PMi_DispOffCount <= PMi_WAIT_FRAME_AFTER_GXDISP )
1668 		{
1669 			OS_WaitVBlankIntr();
1670 			OS_WaitVBlankIntr(); // twice.
1671 		}
1672 
1673 		//---- LCD power off
1674         (void)GXi_PowerLCD(FALSE);
1675 
1676         //---- remember LCD off timing
1677         PMi_LCDCount = OS_GetVBlankCount();
1678 
1679         //---- LED
1680         if (led != PM_LED_NONE)
1681         {
1682             if (isSync)
1683             {
1684                 while( PMi_SetLED(led) != PM_RESULT_SUCCESS )
1685                 {
1686                     OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
1687                 }
1688             }
1689             else
1690             {
1691                 while( PMi_SetLEDAsync(led, NULL, NULL) != PM_RESULT_SUCCESS )
1692                 {
1693                     OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
1694                 }
1695             }
1696         }
1697         break;
1698 
1699     default:
1700         // do nothing
1701         break;
1702     }
1703 
1704     return TRUE;
1705 }
1706 
1707 /*---------------------------------------------------------------------------*
1708   Name:         PM_SetLCDPower
1709 
1710   Description:  turn on/off LCD power.
1711                 when undefined SDK_NO_THREAD (= thread is valid),
1712                 Tick system and Alarm system are needed.
1713 
1714                 This function is the synchronous version.
1715 
1716   Arguments:    sw : switch
1717                    PM_LCD_POWER_ON : on
1718                    PM_LCD_POWER_OFF : off
1719 
1720   Returns:      TRUE   if success
1721                 FALSE  if fail. Perhaps interval of LCD off->on is too short.
1722  *---------------------------------------------------------------------------*/
PM_SetLCDPower(PMLCDPower sw)1723 BOOL PM_SetLCDPower(PMLCDPower sw)
1724 {
1725     if (sw != PM_LCD_POWER_ON)
1726     {
1727         sw = PM_LCD_POWER_OFF;
1728         if (GX_IsDispOn()) // To turn the LCD OFF, first make very sure to set the GX_DispOff status
1729         {
1730             GX_DispOff();
1731         }
1732     }
1733     return PMi_SetLCDPower(sw, PM_LED_NONE /*not touch */ , FALSE, TRUE);
1734 }
1735 
1736 /*---------------------------------------------------------------------------*
1737   Name:         PM_GetLCDPower
1738 
1739   Description:  get status of LCD power
1740 
1741   Arguments:    None.
1742 
1743   Returns:      status.
1744                 PM_LCD_POWER_ON : on
1745                 PM_LCD_POWER_OFF : off
1746  *---------------------------------------------------------------------------*/
PM_GetLCDPower(void)1747 PMLCDPower PM_GetLCDPower(void)
1748 {
1749     return (reg_GX_POWCNT & REG_GX_POWCNT_LCD_MASK) ? PM_LCD_POWER_ON : PM_LCD_POWER_OFF;
1750 }
1751 
1752 /*---------------------------------------------------------------------------*
1753   Name:         PMi_GetLCDOffCount
1754 
1755   Description:  get counter value LCD turned off
1756 
1757   Arguments:    None.
1758 
1759   Returns:      counter value
1760  *---------------------------------------------------------------------------*/
PMi_GetLCDOffCount(void)1761 u32 PMi_GetLCDOffCount(void)
1762 {
1763     return PMi_LCDCount;
1764 }
1765 
1766 
1767 //================================================================================
1768 //             LED
1769 //================================================================================
1770 /*---------------------------------------------------------------------------*
1771   Name:         PMi_SendLEDPatternCommandAsync
1772 
1773   Description:  set up LED blink pattern
1774 
1775   Arguments:    pattern: LED blink pattern
1776                 callback: callback function
1777                 arg: callback argument
1778 
1779   Returns:      result of issuing command
1780                 PM_RESULT_BUSY    : busy
1781                 PM_RESULT_SUCCESS : success
1782  *---------------------------------------------------------------------------*/
1783 //---------------- async version
PMi_SendLEDPatternCommandAsync(PMLEDPattern pattern,PMCallback callback,void * arg)1784 u32 PMi_SendLEDPatternCommandAsync(PMLEDPattern pattern, PMCallback callback, void *arg)
1785 {
1786 	return PM_SendUtilityCommandAsync(PM_UTIL_SET_BLINK, pattern, NULL, callback, arg);
1787 }
1788 
1789 //---------------- sync version
PMi_SendLEDPatternCommand(PMLEDPattern pattern)1790 u32 PMi_SendLEDPatternCommand(PMLEDPattern pattern)
1791 {
1792 	return PM_SendUtilityCommand(PM_UTIL_SET_BLINK, pattern, NULL);
1793 }
1794 
1795 /*---------------------------------------------------------------------------*
1796   Name:         PMi_GetLEDPattern
1797 
1798   Description:  get current LED blink pattern
1799 
1800   Arguments:    pattern: LED blink pattern
1801                 callback: callback function
1802                 arg: callback argument
1803 
1804   Returns:      result of issuing command
1805                 PM_RESULT_SUCCESS : success
1806                 PM_RESULT_BUSY    : busy because other device or other PM function uses SPI
1807  *---------------------------------------------------------------------------*/
1808 //---------------- async version
PM_GetLEDPatternAsync(PMLEDPattern * patternBuf,PMCallback callback,void * arg)1809 u32 PM_GetLEDPatternAsync(PMLEDPattern *patternBuf, PMCallback callback, void *arg)
1810 {
1811 	return PM_SendUtilityCommandAsync(PM_UTIL_GET_STATUS, PM_UTIL_PARAM_BLINK, (u16*)&patternBuf, callback, arg);
1812 }
1813 
1814 //---------------- sync version
PM_GetLEDPattern(PMLEDPattern * patternBuf)1815 u32 PM_GetLEDPattern(PMLEDPattern *patternBuf)
1816 {
1817 	u16 status;
1818 	u32 result = PM_SendUtilityCommand(PM_UTIL_GET_STATUS, PM_UTIL_PARAM_BLINK, &status);
1819 
1820 	if ( result == PM_RESULT_SUCCESS )
1821 	{
1822 		if (patternBuf)
1823 		{
1824 			*patternBuf = (PMLEDPattern)status;
1825 		}
1826 	}
1827     return result;
1828 }
1829 
1830 //================================================================================
1831 //             CALLBACK LIST OPERATION (general)
1832 //================================================================================
1833 /*---------------------------------------------------------------------------*
1834   Name:         PMi_InsertList
1835 
1836   Description:  insert callback to callback info list as specified priority.
1837                 subroutine of PM_Add*CallbackInfo().
1838 
1839   Arguments:    listp : callback info list pointer
1840                 info: callback info to delete
1841                 priority: priority
1842                 method        : comparison operator
1843 
1844   Returns:      None.
1845  *---------------------------------------------------------------------------*/
PMi_InsertList(PMGenCallbackInfo ** listp,PMGenCallbackInfo * info,int priority,int method)1846 static void PMi_InsertList(PMGenCallbackInfo **listp, PMGenCallbackInfo *info, int priority, int method)
1847 {
1848 	OSIntrMode intr;
1849 	PMGenCallbackInfo *p;
1850 	PMGenCallbackInfo *pre;
1851 
1852 	if (!listp)
1853 	{
1854 		return;
1855 	}
1856 
1857 	info->priority = priority;
1858 
1859 	intr = OS_DisableInterrupts();
1860 	p = *listp;
1861 	pre = NULL;
1862 
1863 	while (p)
1864 	{
1865 		//---- found the position to insert
1866 		if (method == PMi_COMPARE_GT && p->priority > priority )
1867 		{
1868 			break;
1869 		}
1870 		if (method == PMi_COMPARE_GE && p->priority >= priority )
1871 		{
1872 			break;
1873 		}
1874 
1875 		pre = p;
1876 		p = p->next;
1877 	}
1878 
1879 	if ( p )
1880 	{
1881 		info->next = p;
1882 	}
1883 	else
1884 	{
1885 		info->next = NULL;
1886 	}
1887 
1888 
1889 	if ( pre )
1890 	{
1891 		pre->next = info;
1892 	}
1893 	else
1894 	{
1895 		//---- add to top
1896 		*listp = info;
1897 	}
1898 
1899     (void)OS_RestoreInterrupts(intr);
1900 }
1901 
1902 /*---------------------------------------------------------------------------*
1903   Name:         PMi_DeleteList
1904 
1905   Description:  delete callback info from callback info list.
1906                 subroutine of PM_Delete*CallbackInfo().
1907 
1908   Arguments:    listp : callback info list pointer
1909                 info: callback info to delete
1910 
1911   Returns:      None.
1912  *---------------------------------------------------------------------------*/
PMi_DeleteList(PMGenCallbackInfo ** listp,PMGenCallbackInfo * info)1913 static void PMi_DeleteList(PMGenCallbackInfo **listp, PMGenCallbackInfo *info)
1914 {
1915     OSIntrMode  intr;
1916     PMGenCallbackInfo *p = *listp;
1917     PMGenCallbackInfo *pre;
1918 
1919     if (!listp)
1920     {
1921         return;
1922     }
1923 
1924     intr = OS_DisableInterrupts();
1925     pre = p = *listp;
1926     while (p)
1927     {
1928         //---- one to delete?
1929         if (p == info)
1930         {
1931             if (p == pre)
1932             {
1933                 *listp = p->next;
1934             }
1935             else
1936             {
1937                 pre->next = p->next;
1938             }
1939             break;
1940         }
1941 
1942         pre = p;
1943         p = p->next;
1944     }
1945     (void)OS_RestoreInterrupts(intr);
1946 }
1947 
1948 /*---------------------------------------------------------------------------*
1949   Name:         PMi_ClearList
1950 
1951   Description:  clear callback list
1952 
1953   Arguments:    listp : callback info list pointer
1954 
1955   Returns:      None.
1956  *---------------------------------------------------------------------------*/
PMi_ClearList(PMGenCallbackInfo ** listp)1957 static void PMi_ClearList(PMGenCallbackInfo **listp)
1958 {
1959 	listp = NULL;
1960 }
1961 
1962 /*---------------------------------------------------------------------------*
1963   Name:         PMi_ExecuteList
1964 
1965   Description:  execute each callback registered to info list
1966 
1967   Arguments:    listp : callback info list pointer
1968 
1969   Returns:      None.
1970  *---------------------------------------------------------------------------*/
PMi_ExecuteList(PMGenCallbackInfo * listp)1971 static void PMi_ExecuteList(PMGenCallbackInfo *listp)
1972 {
1973     while (listp)
1974     {
1975         (listp->callback) (listp->arg);
1976 
1977         listp = listp->next;
1978     }
1979 }
1980 
1981 //================================================================================
1982 //             SLEEP CALLBACK
1983 //================================================================================
1984 /*---------------------------------------------------------------------------*
1985   Name:         PM_AppendPreSleepCallback
1986 
1987   Description:  append callback info to pre-callback info list
1988 
1989   Arguments:    info: callback info to append
1990 
1991   Returns:      None.
1992  *---------------------------------------------------------------------------*/
PM_AppendPreSleepCallback(PMSleepCallbackInfo * info)1993 void PM_AppendPreSleepCallback(PMSleepCallbackInfo *info)
1994 {
1995 	PMi_InsertList(&PMi_PreSleepCallbackList, info, PM_CALLBACK_PRIORITY_MAX, PMi_COMPARE_GT);
1996 }
1997 
1998 /*---------------------------------------------------------------------------*
1999   Name:         PM_PrependPreSleepCallback
2000 
2001   Description:  Prepends callback info to pre-callback info list
2002 
2003   Arguments:    info: callback info to prepend
2004 
2005   Returns:      None.
2006  *---------------------------------------------------------------------------*/
PM_PrependPreSleepCallback(PMSleepCallbackInfo * info)2007 void PM_PrependPreSleepCallback(PMSleepCallbackInfo *info)
2008 {
2009 	PMi_InsertList(&PMi_PreSleepCallbackList, info, PM_CALLBACK_PRIORITY_MIN, PMi_COMPARE_GE);
2010 }
2011 
2012 /*---------------------------------------------------------------------------*
2013   Name:         PM_AppendPostSleepCallback
2014 
2015   Description:  append callback info to post-callback info list
2016 
2017   Arguments:    info: callback info to append
2018 
2019   Returns:      None.
2020  *---------------------------------------------------------------------------*/
PM_AppendPostSleepCallback(PMSleepCallbackInfo * info)2021 void PM_AppendPostSleepCallback(PMSleepCallbackInfo *info)
2022 {
2023 	PMi_InsertList(&PMi_PostSleepCallbackList, info, PM_CALLBACK_PRIORITY_MAX, PMi_COMPARE_GT);
2024 }
2025 
2026 /*---------------------------------------------------------------------------*
2027   Name:         PM_PrependPostSleepCallback
2028 
2029   Description:  prepend callback info to post-callback info list
2030 
2031   Arguments:    info: callback info to prepend
2032 
2033   Returns:      None.
2034  *---------------------------------------------------------------------------*/
PM_PrependPostSleepCallback(PMSleepCallbackInfo * info)2035 void PM_PrependPostSleepCallback(PMSleepCallbackInfo *info)
2036 {
2037 	PMi_InsertList(&PMi_PostSleepCallbackList, info, PM_CALLBACK_PRIORITY_MIN, PMi_COMPARE_GE);
2038 }
2039 
2040 /*---------------------------------------------------------------------------*
2041   Name:         PM_InsertPreSleepCallback
2042 
2043   Description:  insert callback info to post-callback info list
2044 
2045   Arguments:    info: callback info to add
2046                 priority: priority
2047 
2048   Returns:      None.
2049  *---------------------------------------------------------------------------*/
PMi_InsertPreSleepCallbackEx(PMSleepCallbackInfo * info,int priority)2050 void PMi_InsertPreSleepCallbackEx(PMSleepCallbackInfo *info, int priority)
2051 {
2052 	SDK_ASSERT(PM_CALLBACK_PRIORITY_SYSMIN <= priority && priority <= PM_CALLBACK_PRIORITY_SYSMAX );
2053 	PMi_InsertList(&PMi_PreSleepCallbackList, info, priority, PMi_COMPARE_GT);
2054 }
PM_InsertPreSleepCallback(PMSleepCallbackInfo * info,int priority)2055 void PM_InsertPreSleepCallback(PMSleepCallbackInfo *info, int priority)
2056 {
2057 	SDK_ASSERT(PM_CALLBACK_PRIORITY_MIN <= priority && priority <= PM_CALLBACK_PRIORITY_MAX );
2058 	PMi_InsertPreSleepCallbackEx(info, priority);
2059 }
2060 
2061 /*---------------------------------------------------------------------------*
2062   Name:         PM_InsertPostSleepCallback
2063 
2064   Description:  insert callback info to post-callback info list
2065 
2066   Arguments:    info: callback info to add
2067                 priority: priority
2068 
2069   Returns:      None.
2070  *---------------------------------------------------------------------------*/
PMi_InsertPostSleepCallbackEx(PMSleepCallbackInfo * info,int priority)2071 void PMi_InsertPostSleepCallbackEx(PMSleepCallbackInfo *info, int priority)
2072 {
2073 	SDK_ASSERT(PM_CALLBACK_PRIORITY_SYSMIN <= priority && priority <= PM_CALLBACK_PRIORITY_SYSMAX );
2074 	PMi_InsertList(&PMi_PostSleepCallbackList, info, priority, PMi_COMPARE_GT);
2075 }
PM_InsertPostSleepCallback(PMSleepCallbackInfo * info,int priority)2076 void PM_InsertPostSleepCallback(PMSleepCallbackInfo *info, int priority)
2077 {
2078 	SDK_ASSERT(PM_CALLBACK_PRIORITY_MIN <= priority && priority <= PM_CALLBACK_PRIORITY_MAX );
2079 	PMi_InsertPostSleepCallbackEx(info, priority);
2080 }
2081 
2082 /*---------------------------------------------------------------------------*
2083   Name:         PM_DeletePreSleepCallback
2084 
2085   Description:  delete callback info from pre-callback info list
2086 
2087   Arguments:    info: callback info to delete
2088 
2089   Returns:      None.
2090  *---------------------------------------------------------------------------*/
PM_DeletePreSleepCallback(PMSleepCallbackInfo * info)2091 void PM_DeletePreSleepCallback(PMSleepCallbackInfo *info)
2092 {
2093     PMi_DeleteList(&PMi_PreSleepCallbackList, info);
2094 }
2095 
2096 /*---------------------------------------------------------------------------*
2097   Name:         PM_DeletePostSleepCallback
2098 
2099   Description:  delete callback info from post-callback info list
2100 
2101   Arguments:    info: callback info to delete
2102 
2103   Returns:      None.
2104  *---------------------------------------------------------------------------*/
PM_DeletePostSleepCallback(PMSleepCallbackInfo * info)2105 void PM_DeletePostSleepCallback(PMSleepCallbackInfo *info)
2106 {
2107     PMi_DeleteList(&PMi_PostSleepCallbackList, info);
2108 }
2109 
2110 /*---------------------------------------------------------------------------*
2111   Name:         PM_ClearPreSleepCallback
2112 
2113   Description:  clear pre-callback info list
2114 
2115   Arguments:    None.
2116 
2117   Returns:      None.
2118  *---------------------------------------------------------------------------*/
PM_ClearPreSleepCallback(void)2119 void PM_ClearPreSleepCallback(void)
2120 {
2121     PMi_ClearList(&PMi_PreSleepCallbackList);
2122 }
2123 
2124 /*---------------------------------------------------------------------------*
2125   Name:         PM_ClearPostSleepCallback
2126 
2127   Description:  clear post-callback info list
2128 
2129   Arguments:    None.
2130 
2131   Returns:      None.
2132  *---------------------------------------------------------------------------*/
PM_ClearPostSleepCallback(void)2133 void PM_ClearPostSleepCallback(void)
2134 {
2135     PMi_ClearList(&PMi_PostSleepCallbackList);
2136 }
2137 
2138 #ifdef SDK_TWL
2139 #include <twl/ltdmain_begin.h>
2140 //================================================================================
2141 //             SHUTDOWN / RESET HARDWARE (TWL)
2142 //================================================================================
2143 /*---------------------------------------------------------------------------*
2144   Name:         PMi_ProceedToExit
2145 
2146   Description:  Runs before shutdown or reset of hardware.
2147 
2148   Arguments:    None.
2149 
2150   Returns:      None.
2151  *---------------------------------------------------------------------------*/
PMi_ProceedToExit(PMExitFactor factor)2152 static void PMi_ProceedToExit(PMExitFactor factor)
2153 {
2154     //---- check if reset already
2155     if ( ! PMi_TryLockForReset() )
2156     {
2157         return;
2158     }
2159 
2160 	//---- set exit factors
2161 	PMi_ExitFactor = factor;
2162 
2163 #ifndef SDK_FINALROM
2164 	//---- declare to enter exit sequence
2165 	PMi_ExitSequenceFlag = TRUE;
2166 #endif
2167 
2168 	//---- call exit callbacks
2169     PMi_ExecuteList(PMi_PreExitCallbackList);
2170 
2171 	if ( PMi_AutoExitFlag )
2172 	{
2173 		//---- tell ARM7 that ARM9 is ready to shut down
2174 		PM_ReadyToExit();
2175 		// This point will not be reached
2176 	}
2177 }
2178 
2179 /*---------------------------------------------------------------------------*
2180   Name:         PM_ReadyToExit
2181 
2182   Description:  Tells ARM7 that ARM9 is ready to exit.
2183 
2184   Arguments:    None.
2185 
2186   Returns:      None.
2187                 (This function will never return.)
2188  *---------------------------------------------------------------------------*/
PM_ReadyToExit(void)2189 void PM_ReadyToExit(void)
2190 {
2191 #ifndef SDK_FINALROM
2192 	SDK_ASSERT( PMi_ExitSequenceFlag == TRUE );
2193 #endif
2194 
2195     PMi_CallPostExitCallbackAndReset(TRUE);
2196     //This point will never be reached
2197 }
2198 
2199 /*---------------------------------------------------------------------------*
2200   Name:         PMi_FinalizeDebugger
2201 
2202   Description:  Finalizes the debugger.
2203 
2204   Arguments:    None.
2205 
2206   Returns:      None.
2207  *---------------------------------------------------------------------------*/
PMi_FinalizeDebugger(void)2208 static void PMi_FinalizeDebugger(void)
2209 {
2210     //---- sync with ARM7
2211     OSi_SetSyncValue( OSi_SYNCVAL_NOT_READY );
2212     OSi_SyncWithOtherProc( OSi_SYNCTYPE_SENDER, (void*)HW_INIT_LOCK_BUF );
2213     OSi_SyncWithOtherProc( OSi_SYNCTYPE_RECVER, (void*)HW_INIT_LOCK_BUF );
2214 
2215     (void)OS_DisableInterrupts();
2216 
2217 #ifndef SDK_FINALROM
2218     //---- finalize debugger for TS board
2219     if ( OSi_DetectDebugger() & OS_CONSOLE_TWLDEBUGGER )
2220     {
2221         _ISTDbgLib_OnBeforeResetHard();
2222     }
2223 #endif
2224 
2225 	//---- sync with ARM7
2226 	OSi_SetSyncValue( OSi_SYNCVAL_READY );
2227 }
2228 
2229 /*---------------------------------------------------------------------------*
2230   Name:         PM_GetExitFactor
2231 
2232   Description:  Get factors which caused exit.
2233 
2234   Arguments:    None.
2235 
2236   Returns:      factors:  PM_EXIT_FACTOR_PWSW    ... Power switch was pressed.
2237                           PM_EXIT_FACTOR_BATTERY ... Battery low.
2238                           PM_EXIT_FACTOR_USER    ... Called PM_ForceToResetHardware.
2239                           PM_EXIT_FACTOR_NONE    ... Not set yet.
2240  *---------------------------------------------------------------------------*/
PM_GetExitFactor(void)2241 PMExitFactor PM_GetExitFactor(void)
2242 {
2243 	return PMi_ExitFactor;
2244 }
2245 
2246 /*---------------------------------------------------------------------------*
2247   Name:         PM_AppendPreExitCallback
2248 
2249   Description:  Appends exit callback info to pre-callback info list.
2250 
2251   Arguments:    info: callback info to append
2252 
2253   Returns:      None.
2254  *---------------------------------------------------------------------------*/
PM_AppendPreExitCallback(PMExitCallbackInfo * info)2255 void PM_AppendPreExitCallback( PMExitCallbackInfo *info )
2256 {
2257 	PMi_InsertList(&PMi_PreExitCallbackList, info, PM_CALLBACK_PRIORITY_MAX, PMi_COMPARE_GT);
2258 }
2259 
2260 /*---------------------------------------------------------------------------*
2261   Name:         PM_AppendPostExitCallback
2262 
2263   Description:  Appends exit callback info to post-callback info list.
2264 
2265   Arguments:    info: callback info to append
2266 
2267   Returns:      None.
2268  *---------------------------------------------------------------------------*/
PM_AppendPostExitCallback(PMExitCallbackInfo * info)2269 void PM_AppendPostExitCallback( PMExitCallbackInfo *info )
2270 {
2271 	PMi_InsertList(&PMi_PostExitCallbackList, info, PM_CALLBACK_PRIORITY_MAX, PMi_COMPARE_GT);
2272 }
2273 
2274 /*---------------------------------------------------------------------------*
2275   Name:         PM_PrependPreExitCallback
2276 
2277   Description:  Prepends exit callback info to pre-callback info list.
2278 
2279   Arguments:    info: callback info to prepend
2280 
2281   Returns:      None.
2282  *---------------------------------------------------------------------------*/
PM_PrependPreExitCallback(PMExitCallbackInfo * info)2283 void PM_PrependPreExitCallback( PMExitCallbackInfo *info )
2284 {
2285 	PMi_InsertList(&PMi_PreExitCallbackList, info, PM_CALLBACK_PRIORITY_MIN, PMi_COMPARE_GE);
2286 }
2287 
2288 /*---------------------------------------------------------------------------*
2289   Name:         PM_PrependPostExitCallback
2290 
2291   Description:  Prepends exit callback info to post-callback info list.
2292 
2293   Arguments:    info: callback info to prepend
2294 
2295   Returns:      None.
2296  *---------------------------------------------------------------------------*/
PM_PrependPostExitCallback(PMExitCallbackInfo * info)2297 void PM_PrependPostExitCallback( PMExitCallbackInfo *info )
2298 {
2299 	PMi_InsertList(&PMi_PostExitCallbackList, info, PM_CALLBACK_PRIORITY_MIN, PMi_COMPARE_GE);
2300 }
2301 
2302 /*---------------------------------------------------------------------------*
2303   Name:         PM_InsertPreExitCallback
2304 
2305   Description:  Inserts an exit callback info into pre-callback info list.
2306 
2307   Arguments:    info: callback info to add
2308                 priority: priority
2309 
2310   Returns:      None.
2311  *---------------------------------------------------------------------------*/
PMi_InsertPreExitCallbackEx(PMExitCallbackInfo * info,int priority)2312 void PMi_InsertPreExitCallbackEx( PMExitCallbackInfo *info, int priority )
2313 {
2314 	SDK_ASSERT(PM_CALLBACK_PRIORITY_SYSMIN <= priority && priority <= PM_CALLBACK_PRIORITY_SYSMAX );
2315 	PMi_InsertList(&PMi_PreExitCallbackList, info, priority, PMi_COMPARE_GT);
2316 }
PM_InsertPreExitCallback(PMExitCallbackInfo * info,int priority)2317 void PM_InsertPreExitCallback( PMExitCallbackInfo *info, int priority )
2318 {
2319 	SDK_ASSERT(PM_CALLBACK_PRIORITY_MIN <= priority && priority <= PM_CALLBACK_PRIORITY_MAX );
2320 	PMi_InsertPreExitCallbackEx( info, priority );
2321 }
2322 
2323 /*---------------------------------------------------------------------------*
2324   Name:         PM_InsertPostExitCallback
2325 
2326   Description:  Inserts an exit callback info into post-callback info list.
2327 
2328   Arguments:    info: callback info to add
2329                 priority: priority
2330 
2331   Returns:      None.
2332  *---------------------------------------------------------------------------*/
PMi_InsertPostExitCallbackEx(PMExitCallbackInfo * info,int priority)2333 void PMi_InsertPostExitCallbackEx( PMExitCallbackInfo *info, int priority )
2334 {
2335 	SDK_ASSERT(PM_CALLBACK_PRIORITY_SYSMIN <= priority && priority <= PM_CALLBACK_PRIORITY_SYSMAX );
2336 	PMi_InsertList(&PMi_PostExitCallbackList, info, priority, PMi_COMPARE_GT);
2337 }
PM_InsertPostExitCallback(PMExitCallbackInfo * info,int priority)2338 void PM_InsertPostExitCallback( PMExitCallbackInfo *info, int priority )
2339 {
2340 	SDK_ASSERT(PM_CALLBACK_PRIORITY_MIN <= priority && priority <= PM_CALLBACK_PRIORITY_MAX );
2341 	PMi_InsertPostExitCallbackEx( info, priority );
2342 }
2343 
2344 /*---------------------------------------------------------------------------*
2345   Name:         PM_DeletePreExitCallback
2346 
2347   Description:  Deletes exit callback info from pre-callback info list.
2348 
2349   Arguments:    info: callback info to delete
2350 
2351   Returns:      None.
2352  *---------------------------------------------------------------------------*/
PM_DeletePreExitCallback(PMExitCallbackInfo * info)2353 void PM_DeletePreExitCallback( PMExitCallbackInfo *info )
2354 {
2355     PMi_DeleteList(&PMi_PreExitCallbackList, info);
2356 }
2357 
2358 /*---------------------------------------------------------------------------*
2359   Name:         PM_DeletePostExitCallback
2360 
2361   Description:  Deletes exit callback info from post-callback info list.
2362 
2363   Arguments:    info: callback info to delete
2364 
2365   Returns:      None.
2366  *---------------------------------------------------------------------------*/
PM_DeletePostExitCallback(PMExitCallbackInfo * info)2367 void PM_DeletePostExitCallback( PMExitCallbackInfo *info )
2368 {
2369     PMi_DeleteList(&PMi_PostExitCallbackList, info);
2370 }
2371 
2372 /*---------------------------------------------------------------------------*
2373   Name:         PMi_ClearPreExitCallback
2374 
2375   Description:  Clears the exit pre-callback info list.
2376 
2377   Arguments:    None.
2378 
2379   Returns:      None.
2380  *---------------------------------------------------------------------------*/
PMi_ClearPreExitCallback(void)2381 static void PMi_ClearPreExitCallback(void)
2382 {
2383     PMi_ClearList(&PMi_PreExitCallbackList);
2384 }
2385 
2386 /*---------------------------------------------------------------------------*
2387   Name:         PMi_ClearPostExitCallback
2388 
2389   Description:  Clears the exit post-callback info list.
2390 
2391   Arguments:    None.
2392 
2393   Returns:      None.
2394  *---------------------------------------------------------------------------*/
PMi_ClearPostExitCallback(void)2395 static void PMi_ClearPostExitCallback(void)
2396 {
2397     PMi_ClearList(&PMi_PostExitCallbackList);
2398 }
2399 
2400 /*---------------------------------------------------------------------------*
2401   Name:         PMi_ExecutePreExitCallbackList
2402 
2403   Description:  Executes the exit pre-callback info list.
2404 
2405   Arguments:    None.
2406 
2407   Returns:      None.
2408  *---------------------------------------------------------------------------*/
PMi_ExecutePreExitCallbackList(void)2409 void PMi_ExecutePreExitCallbackList(void)
2410 {
2411     PMi_ExecuteList(PMi_PreExitCallbackList);
2412 }
2413 
2414 /*---------------------------------------------------------------------------*
2415   Name:         PMi_ExecutePostExitCallbackList
2416 
2417   Description:  Executes the exit post-callback info list.
2418 
2419   Arguments:    None.
2420 
2421   Returns:      None.
2422  *---------------------------------------------------------------------------*/
PMi_ExecutePostExitCallbackList(void)2423 void PMi_ExecutePostExitCallbackList(void)
2424 {
2425     PMi_ExecuteList(PMi_PostExitCallbackList);
2426 }
2427 
2428 /*---------------------------------------------------------------------------*
2429   Name:         PMi_ExecuteAllListsOfExitCallback
2430 
2431   Description:  Executes all callbacks registered to info lists.
2432 
2433   Arguments:    None.
2434 
2435   Returns:      None.
2436  *---------------------------------------------------------------------------*/
PMi_ExecuteAllListsOfExitCallback(void)2437 void PMi_ExecuteAllListsOfExitCallback(void)
2438 {
2439     PMi_ExecuteList(PMi_PreExitCallbackList);
2440     PMi_ExecuteList(PMi_PostExitCallbackList);
2441 }
2442 
2443 /*---------------------------------------------------------------------------*
2444   Name:         PM_SetAutoExit
2445 
2446   Description:  Sets flag indicating whether to automatically shutdown/reset after callbacks.
2447 
2448   Arguments:    sw : TRUE  ... Shutdown/reset after callback automatically.
2449                      FALSE ... Do not shutdown/reset after callback.
2450 
2451   Returns:      None.
2452  *---------------------------------------------------------------------------*/
PM_SetAutoExit(BOOL sw)2453 void PM_SetAutoExit( BOOL sw )
2454 {
2455 	PMi_AutoExitFlag = sw;
2456 }
2457 /*---------------------------------------------------------------------------*
2458   Name:         PM_GetAutoExit
2459 
2460   Description:  Gets the current setting of AutoExit.
2461 
2462   Arguments:    None.
2463 
2464   Returns:      TRUE  ... Shutdown/reset after callback automatically.
2465                 FALSE ... Do not shutdown/reset after callback.
2466  *---------------------------------------------------------------------------*/
PM_GetAutoExit(void)2467 BOOL PM_GetAutoExit(void)
2468 {
2469 	return PMi_AutoExitFlag;
2470 }
2471 
2472 //================================================================================
2473 //             BATTERY CALLBACK
2474 //================================================================================
2475 /*---------------------------------------------------------------------------*
2476   Name:         PM_SetBatteryLowCallback
2477 
2478   Description:  Sets the low battery callback.
2479 
2480   Arguments:    callback: Callback called when low battery is detected.
2481                 arg: callback argument
2482 
2483   Returns:      None.
2484  *---------------------------------------------------------------------------*/
PM_SetBatteryLowCallback(PMBatteryLowCallback callback,void * arg)2485 void PM_SetBatteryLowCallback( PMBatteryLowCallback callback, void* arg )
2486 {
2487 	PMi_BatteryLowCallbackInfo.callback = callback;
2488 	PMi_BatteryLowCallbackInfo.arg = arg;
2489 }
2490 
2491 //================================================================================
2492 //             RESET HARDWARE (TWL)
2493 //================================================================================
2494 /*---------------------------------------------------------------------------*
2495   Name:         PM_ForceToResetHardware
2496 
2497   Description:  Tells the ARM7 to reset hardware.
2498 
2499   Arguments:    None.
2500 
2501   Returns:      None.
2502  *---------------------------------------------------------------------------*/
PM_ForceToResetHardware(void)2503 void PM_ForceToResetHardware(void)
2504 {
2505     //---- set exit factors
2506     PMi_ExitFactor = PM_EXIT_FACTOR_USER;
2507 
2508     PMi_CallPostExitCallbackAndReset(FALSE);
2509     //This point will never be reached
2510 }
2511 
2512 /*---------------------------------------------------------------------------*
2513   Name:         PMi_CallPostExitCallbackAndReset
2514 
2515   Description:  Calls post exit callbacks and resets hardware.
2516 
2517   Arguments:    isExit : TRUE  ... EXIT (HARDWARERESET or SHUTDOWN)
2518                          FALSE ... HARDWARERESET
2519 
2520   Returns:      None.
2521  *---------------------------------------------------------------------------*/
PMi_CallPostExitCallbackAndReset(BOOL isExit)2522 static void PMi_CallPostExitCallbackAndReset(BOOL isExit)
2523 {
2524     //---- call exit callbacks
2525     PMi_ExecuteList(PMi_PostExitCallbackList);
2526 
2527     //---- display off
2528     GX_DispOff();
2529     GXS_DispOff();
2530 
2531     //---- wait 2 V-Blanks at least
2532     {
2533         int n;
2534         for( n=0; n<3; n++ )
2535         {
2536             u32 count = OS_GetVBlankCount();
2537             while( count == OS_GetVBlankCount() )
2538             {
2539             }
2540         }
2541     }
2542 
2543     //---- send EXIT or RESET command
2544     while(1)
2545     {
2546         u16 result;
2547         u32 command = isExit? PM_UTIL_FORCE_EXIT: PM_UTIL_FORCE_RESET_HARDWARE;
2548 
2549         //---- exit if 'forced' is specified.
2550         if ( *(u32*)HW_RESET_LOCK_FLAG_BUF == PM_RESET_FLAG_FORCED )
2551         {
2552             command = PM_UTIL_FORCE_EXIT;
2553 
2554             //---- clear launcher param
2555             ((LauncherParam*)HW_PARAM_LAUNCH_PARAM)->header.magicCode = 0;
2556         }
2557 
2558         while( PM_SendUtilityCommand(command, 0, &result) != PM_SUCCESS )
2559         {
2560             //---- wait
2561             OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
2562         }
2563         if ( result == SPI_PXI_RESULT_SUCCESS )
2564         {
2565             break;
2566         }
2567 
2568         //---- wait
2569         OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
2570     }
2571 
2572     (void)OS_DisableInterrupts();
2573 
2574     //---- stop all dma
2575     MI_StopAllDma();
2576     MI_StopAllNDma();
2577 
2578     //---- finalize debugger
2579     PMi_FinalizeDebugger();
2580 
2581     OSi_TerminateCore();
2582     //This point will never be reached
2583 }
2584 #include <twl/ltdmain_end.h>
2585 #endif
2586 
2587 /*---------------------------------------------------------------------------*
2588   Name:         PMi_LCDOnAvoidReset
2589 
2590   Description:  Force to power on LCD to avoid the following:
2591                 On USG, the operation of power off with LCD-ON may cause reset hardware not power off
2592                 because of PMIC of the specified maker.
2593 
2594   Arguments:    None.
2595 
2596   Returns:      None.
2597  *---------------------------------------------------------------------------*/
PMi_LCDOnAvoidReset(void)2598 static void PMi_LCDOnAvoidReset(void)
2599 {
2600     BOOL preMethod;
2601 
2602 	//---- wait while specified period for LCD (0x360000sysClock == about 106ms)
2603 	OS_SpinWaitSysCycles(PMi_LCD_WAIT_SYS_CYCLES);
2604 
2605 	//---- force to set LCD power on
2606     preMethod = PMi_WaitBusyMethod;
2607     PMi_WaitBusyMethod = PMi_WAITBUSY_METHOD_CPUMODE | PMi_WAITBUSY_METHOD_CPSR | PMi_WAITBUSY_METHOD_IME;
2608 	if (PM_GetLCDPower() != PM_LCD_POWER_ON)
2609 	{
2610 		//---- set backlight off (for avoiding appearance of afterimage)
2611         while( PM_SetBackLight(PM_LCD_ALL, PM_BACKLIGHT_OFF) != PM_RESULT_SUCCESS )
2612         {
2613             OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
2614         }
2615 
2616 		while (!PM_SetLCDPower(PM_LCD_POWER_ON))
2617 		{
2618 			OS_SpinWait(PMi_PXI_WAIT_TICK);
2619 		}
2620 	}
2621     PMi_WaitBusyMethod = preMethod;
2622 }
2623 
2624 #ifndef SDK_FINALROM
2625 //================================================================================
2626 //     DIRECT REGISTER OPERATION (for DEBUG)
2627 //================================================================================
2628 /*---------------------------------------------------------------------------*
2629   Name:         PMi_ReadRegisterAsync
2630 
2631   Description:  send read register command  to ARM7
2632 
2633   Arguments:    registerAddr : PMIC register number (0-3)
2634                 buffer: buffer to store register value
2635                 callback: callback function
2636                 arg: callback argument
2637 
2638   Returns:      result of issuing command
2639                 PM_RESULT_BUSY    : busy
2640                 PM_RESULT_SUCCESS : success
2641  *---------------------------------------------------------------------------*/
PMi_ReadRegisterAsync(u16 registerAddr,u16 * buffer,PMCallback callback,void * arg)2642 u32 PMi_ReadRegisterAsync(u16 registerAddr, u16 *buffer, PMCallback callback, void *arg)
2643 {
2644 	return PM_SendUtilityCommandAsync(PMi_UTIL_READREG, registerAddr, buffer, callback, arg);
2645 }
PMi_ReadRegister(u16 registerAddr,u16 * buffer)2646 u32 PMi_ReadRegister(u16 registerAddr, u16 *buffer)
2647 {
2648 	return PM_SendUtilityCommand(PMi_UTIL_READREG, registerAddr, buffer);
2649 }
2650 /*---------------------------------------------------------------------------*
2651   Name:         PMi_WriteRegisterAsync
2652 
2653   Description:  send write register command to ARM7
2654 
2655   Arguments:    registerAddr : PMIC register number (0-3)
2656                 data: data written to PMIC register
2657                 callback: callback function
2658                 arg: callback argument
2659 
2660   Returns:      result of issuing command
2661                 PM_RESULT_BUSY    : busy
2662                 PM_RESULT_SUCCESS : success
2663  *---------------------------------------------------------------------------*/
PMi_WriteRegisterAsync(u16 registerAddr,u16 data,PMCallback callback,void * arg)2664 u32 PMi_WriteRegisterAsync(u16 registerAddr, u16 data, PMCallback callback, void *arg)
2665 {
2666 	return PM_SendUtilityCommandAsync(PMi_UTIL_WRITEREG, (u16)((registerAddr<<8) | (data&0xff)), NULL, callback, arg);
2667 }
2668 
PMi_WriteRegister(u16 registerAddr,u16 data)2669 u32 PMi_WriteRegister(u16 registerAddr, u16 data)
2670 {
2671 	return PM_SendUtilityCommand(PMi_UTIL_WRITEREG, (u16)((registerAddr<<8) | (data&0xff)), NULL);
2672 }
2673 #endif
2674 
2675 /*---------------------------------------------------------------------------*
2676   Name:         PMi_SetDispOffCount
2677 
2678   Description:  Records disp off counter for internal use.
2679 
2680   Arguments:    None.
2681 
2682   Returns:      None.
2683  *---------------------------------------------------------------------------*/
PMi_SetDispOffCount(void)2684 void PMi_SetDispOffCount(void)
2685 {
2686 	PMi_DispOffCount = OS_GetVBlankCount();
2687 }
2688 
2689 //================================================================================
2690 //   DUMP (for DEBUG)
2691 //================================================================================
2692 #ifndef SDK_FINALROM
2693 /*---------------------------------------------------------------------------*
2694   Name:         PM_DumpSleepCallback
2695 
2696   Description:  Dumps sleep callbacks (for debug).
2697 
2698   Arguments:    None.
2699 
2700   Returns:      None.
2701  *---------------------------------------------------------------------------*/
PM_DumpSleepCallback(void)2702 void PM_DumpSleepCallback(void)
2703 {
2704 	PMGenCallbackInfo *p;
2705 
2706 	p = PMi_PreSleepCallbackList;
2707 	OS_TPrintf("----PreSleep Callback\n");
2708 	while(p)
2709 	{
2710 		OS_TPrintf("[%08x] (prio=%d) (arg=%x)\n", p->callback, p->priority, p->arg);
2711 		p = p->next;
2712 	}
2713 
2714 	p = PMi_PostSleepCallbackList;
2715 	OS_TPrintf("----PostSleep Callback\n");
2716 	while(p)
2717 	{
2718 		OS_TPrintf("[%08x] (prio=%d) (arg=%x)\n", p->callback, p->priority, p->arg);
2719 		p = p->next;
2720 	}
2721 }
2722 
2723 #ifdef SDK_TWL
2724 #include <twl/ltdmain_begin.h>
2725 /*---------------------------------------------------------------------------*
2726   Name:         PM_DumpExitCallback
2727 
2728   Description:  Dumps exit callbacks (for debug).
2729 
2730   Arguments:    None.
2731 
2732   Returns:      None.
2733  *---------------------------------------------------------------------------*/
PM_DumpExitCallback(void)2734 void PM_DumpExitCallback(void)
2735 {
2736 	PMGenCallbackInfo *p;
2737 
2738 	p = PMi_PreExitCallbackList;
2739 	OS_TPrintf("----PreExit Callback\n");
2740 	while(p)
2741 	{
2742 		OS_TPrintf("[%08x] (prio=%d) (arg=%x)\n", p->callback, p->priority, p->arg);
2743 		p = p->next;
2744 	}
2745 
2746 	p = PMi_PostExitCallbackList;
2747 	OS_TPrintf("----PostExit Callback\n");
2748 	while(p)
2749 	{
2750 		OS_TPrintf("[%08x] (prio=%d) (arg=%x)\n", p->callback, p->priority, p->arg);
2751 		p = p->next;
2752 	}
2753 }
2754 #include <twl/ltdmain_end.h>
2755 #endif //ifdef SDK_TWL
2756 #endif //ifndef SDK_FINALROM
2757 
2758 //================================================================================
2759 //   LOCK for RESET/EXIT
2760 //================================================================================
2761 #ifdef SDK_TWL
2762 #include <twl/ltdmain_begin.h>
2763 /*---------------------------------------------------------------------------*
2764   Name:         PMi_TryLockForReset
2765 
2766   Description:  Tries to lock. This is for the forced reset and pushing battery button.
2767 
2768   Arguments:    None.
2769 
2770   Returns:      TRUE  ... Lock succeeded.
2771                 FALSE ... Lock failed.
2772  *---------------------------------------------------------------------------*/
2773 static volatile BOOL isLockedReset = FALSE;
PMi_TryLockForReset(void)2774 BOOL PMi_TryLockForReset(void)
2775 {
2776     OSIntrMode e = OS_DisableInterrupts();
2777 
2778     //---- try lock
2779     if ( isLockedReset )
2780     {
2781         (void)OS_RestoreInterrupts(e);
2782         return FALSE;
2783     }
2784     isLockedReset = TRUE;
2785 
2786     (void)OS_RestoreInterrupts(e);
2787     return TRUE;
2788 }
2789 #include <twl/ltdmain_end.h>
2790 #endif // ifdef SDK_TWL
2791