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