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-10-01#$
14 $Rev: 11078 $
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 PMi_WaitBusyMethod = PMi_WAITBUSY_METHOD_CPUMODE | PMi_WAITBUSY_METHOD_CPSR | PMi_WAITBUSY_METHOD_IME;
2570 while( PM_SendUtilityCommand(command, 0, &result) != PM_SUCCESS )
2571 {
2572 //---- Wait
2573 OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
2574 PMi_WaitBusy();
2575 }
2576 if ( result == SPI_PXI_RESULT_SUCCESS )
2577 {
2578 break;
2579 }
2580
2581 //---- Wait
2582 OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
2583 }
2584
2585 (void)OS_DisableInterrupts();
2586
2587 //---- Stop all DMA
2588 MI_StopAllDma();
2589 MI_StopAllNDma();
2590
2591 //---- Finalize debugger
2592 PMi_FinalizeDebugger();
2593
2594 OSi_TerminateCore();
2595 //This point will never be reached
2596 }
2597 #include <twl/ltdmain_end.h>
2598 #endif
2599
2600 /*---------------------------------------------------------------------------*
2601 Name: PMi_LCDOnAvoidReset
2602
2603 Description: Force to power on LCD to avoid the following.
2604 On USG, the operation of power off with LCD-ON may cause reset hardware not power off
2605 because of PMIC of the specified maker.
2606
2607 Arguments: None.
2608
2609 Returns: None.
2610 *---------------------------------------------------------------------------*/
PMi_LCDOnAvoidReset(void)2611 static void PMi_LCDOnAvoidReset(void)
2612 {
2613 BOOL preMethod;
2614
2615 //---- Wait while specified period for LCD (0x360000sysClock == about 106 ms)
2616 OS_SpinWaitSysCycles(PMi_LCD_WAIT_SYS_CYCLES);
2617
2618 //---- Force to set LCD power on
2619 preMethod = PMi_WaitBusyMethod;
2620 PMi_WaitBusyMethod = PMi_WAITBUSY_METHOD_CPUMODE | PMi_WAITBUSY_METHOD_CPSR | PMi_WAITBUSY_METHOD_IME;
2621 if (PM_GetLCDPower() != PM_LCD_POWER_ON)
2622 {
2623 //---- Set backlight off (for avoiding appearance of afterimage)
2624 while( PM_SetBackLight(PM_LCD_ALL, PM_BACKLIGHT_OFF) != PM_RESULT_SUCCESS )
2625 {
2626 OS_SpinWait(HW_CPU_CLOCK_ARM9 / 100);
2627 }
2628
2629 while (!PM_SetLCDPower(PM_LCD_POWER_ON))
2630 {
2631 OS_SpinWait(PMi_PXI_WAIT_TICK);
2632 }
2633 }
2634 PMi_WaitBusyMethod = preMethod;
2635 }
2636
2637 #ifndef SDK_FINALROM
2638 //================================================================================
2639 // DIRECT REGISTER OPERATION (for DEBUG)
2640 //================================================================================
2641 /*---------------------------------------------------------------------------*
2642 Name: PMi_ReadRegisterAsync
2643
2644 Description: Sends read register command to ARM7.
2645
2646 Arguments: registerAddr: PMIC register number (0-3)
2647 buffer: Buffer to store register value
2648 callback: Callback function
2649 arg: Callback argument
2650
2651 Returns: Result of issuing command.
2652 PM_RESULT_BUSY: Busy.
2653 PM_RESULT_SUCCESS: Success.
2654 *---------------------------------------------------------------------------*/
PMi_ReadRegisterAsync(u16 registerAddr,u16 * buffer,PMCallback callback,void * arg)2655 u32 PMi_ReadRegisterAsync(u16 registerAddr, u16 *buffer, PMCallback callback, void *arg)
2656 {
2657 return PM_SendUtilityCommandAsync(PMi_UTIL_READREG, registerAddr, buffer, callback, arg);
2658 }
PMi_ReadRegister(u16 registerAddr,u16 * buffer)2659 u32 PMi_ReadRegister(u16 registerAddr, u16 *buffer)
2660 {
2661 return PM_SendUtilityCommand(PMi_UTIL_READREG, registerAddr, buffer);
2662 }
2663 /*---------------------------------------------------------------------------*
2664 Name: PMi_WriteRegisterAsync
2665
2666 Description: Sends write register command to ARM7.
2667
2668 Arguments: registerAddr: PMIC register number (0-3)
2669 data: Data written to PMIC register
2670 callback: Callback function
2671 arg: Callback argument
2672
2673 Returns: Result of issuing command.
2674 PM_RESULT_BUSY: Busy
2675 PM_RESULT_SUCCESS: Success
2676 *---------------------------------------------------------------------------*/
PMi_WriteRegisterAsync(u16 registerAddr,u16 data,PMCallback callback,void * arg)2677 u32 PMi_WriteRegisterAsync(u16 registerAddr, u16 data, PMCallback callback, void *arg)
2678 {
2679 return PM_SendUtilityCommandAsync(PMi_UTIL_WRITEREG, (u16)((registerAddr<<8) | (data&0xff)), NULL, callback, arg);
2680 }
2681
PMi_WriteRegister(u16 registerAddr,u16 data)2682 u32 PMi_WriteRegister(u16 registerAddr, u16 data)
2683 {
2684 return PM_SendUtilityCommand(PMi_UTIL_WRITEREG, (u16)((registerAddr<<8) | (data&0xff)), NULL);
2685 }
2686 #endif
2687
2688 /*---------------------------------------------------------------------------*
2689 Name: PMi_SetDispOffCount
2690
2691 Description: Records disp from counter for internal use.
2692
2693 Arguments: None.
2694
2695 Returns: None.
2696 *---------------------------------------------------------------------------*/
PMi_SetDispOffCount(void)2697 void PMi_SetDispOffCount(void)
2698 {
2699 PMi_DispOffCount = OS_GetVBlankCount();
2700 }
2701
2702 //================================================================================
2703 // DUMP (for DEBUG)
2704 //================================================================================
2705 #ifndef SDK_FINALROM
2706 /*---------------------------------------------------------------------------*
2707 Name: PM_DumpSleepCallback
2708
2709 Description: Dumps sleep callbacks (for debug).
2710
2711 Arguments: None.
2712
2713 Returns: None.
2714 *---------------------------------------------------------------------------*/
PM_DumpSleepCallback(void)2715 void PM_DumpSleepCallback(void)
2716 {
2717 PMGenCallbackInfo *p;
2718
2719 p = PMi_PreSleepCallbackList;
2720 OS_TPrintf("----PreSleep Callback\n");
2721 while(p)
2722 {
2723 OS_TPrintf("[%08x] (prio=%d) (arg=%x)\n", p->callback, p->priority, p->arg);
2724 p = p->next;
2725 }
2726
2727 p = PMi_PostSleepCallbackList;
2728 OS_TPrintf("----PostSleep Callback\n");
2729 while(p)
2730 {
2731 OS_TPrintf("[%08x] (prio=%d) (arg=%x)\n", p->callback, p->priority, p->arg);
2732 p = p->next;
2733 }
2734 }
2735
2736 #ifdef SDK_TWL
2737 #include <twl/ltdmain_begin.h>
2738 /*---------------------------------------------------------------------------*
2739 Name: PM_DumpExitCallback
2740
2741 Description: Dumps exit callbacks (for debug).
2742
2743 Arguments: None.
2744
2745 Returns: None.
2746 *---------------------------------------------------------------------------*/
PM_DumpExitCallback(void)2747 void PM_DumpExitCallback(void)
2748 {
2749 PMGenCallbackInfo *p;
2750
2751 p = PMi_PreExitCallbackList;
2752 OS_TPrintf("----PreExit Callback\n");
2753 while(p)
2754 {
2755 OS_TPrintf("[%08x] (prio=%d) (arg=%x)\n", p->callback, p->priority, p->arg);
2756 p = p->next;
2757 }
2758
2759 p = PMi_PostExitCallbackList;
2760 OS_TPrintf("----PostExit Callback\n");
2761 while(p)
2762 {
2763 OS_TPrintf("[%08x] (prio=%d) (arg=%x)\n", p->callback, p->priority, p->arg);
2764 p = p->next;
2765 }
2766 }
2767 #include <twl/ltdmain_end.h>
2768 #endif //ifdef SDK_TWL
2769 #endif //ifndef SDK_FINALROM
2770
2771 //================================================================================
2772 // LOCK for RESET/EXIT
2773 //================================================================================
2774 #ifdef SDK_TWL
2775 #include <twl/ltdmain_begin.h>
2776 /*---------------------------------------------------------------------------*
2777 Name: PMi_TryLockForReset
2778
2779 Description: Tries to lock. This is for the forced reset and pushing battery button.
2780
2781 Arguments: None.
2782
2783 Returns: TRUE: Lock succeeded.
2784 FALSE: Lock failed.
2785 *---------------------------------------------------------------------------*/
2786 static volatile BOOL isLockedReset = FALSE;
PMi_TryLockForReset(void)2787 BOOL PMi_TryLockForReset(void)
2788 {
2789 OSIntrMode e = OS_DisableInterrupts();
2790
2791 //---- Try lock
2792 if ( isLockedReset )
2793 {
2794 (void)OS_RestoreInterrupts(e);
2795 return FALSE;
2796 }
2797 isLockedReset = TRUE;
2798
2799 (void)OS_RestoreInterrupts(e);
2800 return TRUE;
2801 }
2802 #include <twl/ltdmain_end.h>
2803 #endif // ifdef SDK_TWL
2804