RFC [1/3] - SoC, CPU LPS, Tickless idle and Device power management
Thomas, Ramesh
***This part is merged***
https://gerrit.zephyrproject.org/r/#/c/148/ https://gerrit.zephyrproject.org/r/#/c/149/ https://gerrit.zephyrproject.org/r/#/c/150/ https://gerrit.zephyrproject.org/r/#/c/151/ Kernel SOC power management hook infrastructure in Zephyr ----------------------------------------------------------------------- This infrastructure provides hooks at locations where the kernel goes to idle to enable the PM service application to do suspend operations around them. This infrastructure can be used by power manager app to implement PM policy and to put system to various power states. A sample PM application is provided as an example to demonstrate how to use these hooks and the states it uses (listed below) are for demonstration purpose. It is up to the implementer of the PM service app to design their own. 1. LPS: CPU is put in low power states like C2. The CPU states are not lost. Woken up by any interrupt. 2. Deep Sleep: The SoC is put in deep sleep state saving most power. In this state, CPU power is off while SRAM contents are retained. Woken up by deep sleep wake up events of SoC. On wake up, execution will resume from reset vector. 3. Tickless Idle power saving: Zephyr kernel has its own idling called Tickless idle. PM service can take advantage of this by turning off peripherals to save more power when the hook infrastructure notifies it before going to idle. It will be notified again when kernel exits the tickless idle state when it can restore states it altered. The hook functions: These functions must be implemented by the power management service app. a) int _sys_soc_suspend(int32_t ticks) param ticks: - the upcoming kernel idle time return: - non-zero value if it uses its own idle or deep sleep. If a zero value is returned, then kernel will enter its own idle. Details: This is called immediately before the kernel prepares to go into its idle state. The PM service, based on the amount of idle time available, chooses an appropriate power policy comparing the wake latencies involved. For CPU low power states it would put the CPU in states like C2. For SoC deep sleep states, it would do the required SoC specific operation. In these, it would return a non-zero value indicating it has fully handled the idle and the kernel will not enter its own idle. For tickless idle power saving, the PM service app can turn off as many peripherals it requires and then returns a zero value. The zero return value would indicate to the kernel that it should do its own idle. This function is entered with interrupts disabled. It should re-enable interrupts if it does its own idle or deep sleep. If it returns zero then it should not enable interrupts so the kernel can go to idle state without interruption. b) void _sys_soc_resume(void) Details: The main purpose of this hook is to notify PM service of exit from SoC deep sleep state, CPU low power and tickless idle exit. Any states altered at _sys_soc_suspend() should be restored in this function. This hook function is called from 2 different locations in the kernel. PM service will check its internal states to determine which state the system recovering from. Following are the 2 different locations where it called from: 1. At kernel start recovering from deep sleep or entering cold boot. Deep sleep causes all CPU states to be lost so the system resumes at the reset vector taking the same path as cold boot. Since kernel does not save any state to identify whether it is recovering from cold boot or deep sleep, it would call this function in both cases. PM service can use SoC specific sticky registers that can retain values across deep sleep to identify whether it is resuming from deep sleep. In the case of cold boot, these registers would get reset. If it is cold boot then this function should return immediately doing nothing. If it is recovering from deep sleep then it should restore states including CPU registers and stack stored in _sys_soc_suspend(). Execution context should then switch to execution inside _sys_soc_suspend() at the location where it put the system to deep sleep. In this location, this function is called using a temporary stack that is also used by interrupts. It is important that this function switches to the stack that was saved during _sys_soc_suspend before interrupts are enabled when returning from _sys_soc_suspend() to avoid interfering with interrupt handlers use of this stack. 2. After the exit of tickless idle or a low power CPU state from the context of the ISR that caused the exit. In this case, PM service will restore altered states and return. |
|