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