Wednesday, September 17, 2008

Adding Low Power modes in PXA - P4

So far,we have discussed about how to put pxa into low power mode, how to wake it up, and briefly on how operating system restore things to the prior state after a transition to low power mode. Now lets put the bits and pieces together and see how windows ce does the low power mode transition in case of PXA.


As I have mentioned in the previous posts, we need to add the wakeup configuration first and then put the processor in to the low power mode.

For purpoes of explaining the concept, I will how to add a wakeup for GPIO 11 which is connected to the activity line of a communication module.

Adding the wakeup source
1) In OAL interrupt code(intr.c and bsp_cfg.h), add the code for creating a new interrupt corresponding to the wakeup source.

bsp_cfg.h - Add the new sysintr for the wakeup line

....
#define SYSINTR_COMMMOD_WAKEPUP (SYSINTR_FIRMWARE+22)
....


intr.c - map the sysintr to gpio 11 and add code for managing that
BOOL BSPIntrInit()
{
....
OALIntrStaticTranslate (SYSINTR_COMMMOD_WAKEPUP,IRQ_GPIOXX_2_GPIO11);
....
}


2) In OAL power code (power.c), add code for setting the pwer register. In mainstone bsp, the wakeups are register while OS starts (BSPPowerOffInit function)and the pwer value is written only while going into low power mode (BSPPowerOff).

BSPSetWakeSrc function - add a case for gpio 11 and set the gpio11 bit in the pPwer global variable. This variable will be written to the actual PWER register while going into suspend.

......
case IRQ_GPIOXX_2_GPIO11:
pPwer->gpio11 = 1;
OALMSG(1, ( L"BSPSetWakeSrc: IRQ Communication module source\r\n", irq));
break;
......


BSPGetWakeSrc function - add case for gpio 11 here also.This function to return the IRQ value if the PEDR (Power manager edge detect register) bit for gpio 11 is set.

....
else if (pPedr->gpio11)
{
*pSrcIrq = IRQ_GPIOXX_2_GPIO11;
}
....

BSPPowerOffInit function - use the OALIoCtlHalEnableWake function to set the global variable (g_oalWakeMask, an array) with the sysintr value corresponding to gpio11.
UINT32 commSysIntr = SYSINTR_COMMMOD_WAKEPUP;
...

OALIoCtlHalEnableWake(IOCTL_HAL_ENABLE_WAKE, &commSysIntr, sizeof(commSysIntr), NULL, 0, NULL);
...



While the BSPPowerOff function finds out which sysintr is mapped as a wakeup using OALPowerWakeSource and OALIntrTranslateSysIntr functions and sets the pwer bits with BSPSetWakeSrc function call.

When system resumes, BSPGetWakeSrc is used to get the wake cause and is stored in g_oalWakeSource variable which can be retrieved using kernel ioctl IOCTL_HAL_GET_WAKE_SOURCE



0 comments: