PM Framework

Power Domain Framework
The Power Domain Framework is an important component in the overall Power Management Frameworks. It comprises of all the various power domain structures supported for the active SOCs.

Each power domain can have one or multiple clock domains which in turn are the host to various clocks. The Power domain management is the highest level of control available to transition the system level components.

The power domain can transition to a low power state only if all the clock domains registered for it have transitioned to a low power state. Current power domain framework needs a bit of a revamp and the proposal for the same has been mentioned under the head of Power Domain Cleanup.

Clock Domain Framework
The clock domain framework is the next important framework following the power domain framework. It comprises of all the various clock domain structures supported for the active SOCs.

Each clock domain can have one or multiple clocks which can be enabled or disabled individually.

The clock domain can transition to low power state only if all the clocks registered for it are disabled. Also there are Clock Domain Dependencies between various clock domains which determine the sleep and wakeup conditions for the given clock domain. Current clock domain framework needs a bit of a revamp and the proposal for the same has been mentioned under the head of Clock Domain Cleanup.

Power Domain Cleanup - The Approach
The following two phase approach is adopted for power domain cleanup


 * Phase 1 
 * Clean up instances of usage of PRM/ CM APIs outside power domain & clock domain frameworks. Move these instances to appropriate frameworks.
 * This work can go ahead; there is enough clarity - Rajendra
 * Need to figure out how to handle PRM FSM in some of the APIs - Rajendra & Benoit


 * Phase 2
 * Split the power domain and clock domain framework into platform and platform independent parts
 * Adopt the approach of doing the changes first and then moving
 * Some work has been done by Abhijit but need more discussions

More Details on Phase 2 - The Splitting Part
The powerdomain and clockdomain frameworks need to be redesigned in such a way that there is a platform independent part doing the usecounting et al and anything else that is platform independent and a platform dependent part which has platform specific implementations. The idea is to implement the platform specific hooks using function pointers which can then be called from platform independent part. This is the design that other power frameworks follow today, like the clock framework and Shared resource framework.

Structural Diagram of the Power Domain Revamp Design:



List of CPU Independent APIs:

pwrdm_lookup: Returns the handle of the specified power domain

pwrdm_for_each: Executes the given API for all registered power domains

pwrdm_add_clkdm: Attaches the specified clock domain to the power domain

pwrdm_del_clkdm: Detaches the specified clock domain to the power domain

pwrdm_for_each_clkdm: Executes the given API for all registered clock domains for the given power domain

pwrdm_get_mem_bank_count: Gives the number of memory banks registered for the given powerdomain

pwrdm_has_hdwr_sar: Tells whether a given power domain supports SAR or not

pwrdm_pre_transition: Calls the pre transition power domain state switch

pwrdm_post_transition: Calls the post transition power domain state switch

List of CPU Dependent APIs:

pwrdm_init: Registers all the listed power domains

pwrdm_set_next_pwrst: Prepares the power domain to enter the specified state

pwrdm_read_next_pwrst: Reads which state is the power domain supposed to enter

pwrdm_read_pwrst: Reads the current entered state of the power domain

pwrdm_read_prev_pwrst: Reads the earlier state before the power domain transitioned to the next state

pwrdm_clear_all_prev_pwrst: Clears the previous power state records for the given powerdomain

pwrdm_set_logic_retst: Set powerdomain logic power state while the power domain is in retention

pwrdm_set_mem_onst: Set memory power state while the power domain is ON

pwrdm_set_mem_retst: Set memory power state while power domain is in retention

pwrdm_read_logic_pwrst: Read current power domain logic retention power state

pwrdm_read_prev_logic_pwrst: Read previous power domain logic power state

pwrdm_read_logic_retst: Read next power domain logic power state

pwrdm_read_mem_pwrst: Read current memory bank power state

pwrdm_read_prev_mem_pwrst: Read previous memory bank power state

pwrdm_read_mem_retst: Read next memory bank power state

pwrdm_enable_hdwr_sar: enable automatic hardware SAR for the given power domain

pwrdm_disable_hdwr_sar: disable automatic hardware SAR for the given power domain

pwrdm_wait_transition: wait for power domain power transition to finish

pwrdm_state_switch: Switch the state of the power domain to the one specified

pwrdm_clkdm_state_switch: Switch the state of the clock domain in the power domain to the one specified

Implementation Details of CPU Dependent APIs

The function pointers have to be registered for calling the CPU specific execution part from the Platform independent part. There are two sets of implementations possible when it comes to linking the Public APIs to the CPU specific implementations.

(Group A) Individual API having a respective function pointer for implementation: Here the API has a one function pointer registered uniquely for itself. The parameters passed between the main API and the registered function will be just the same. The implementation will just differ from CPU to CPU. (These APIs will be hence forth referred to as Group A)

(Group B) Multiple APIs having a single function pointer registered for implementation: The APIs in this category will have a flag registered for them individually. They will have a single function pointer which they will call. The only additional part will be they will pass their individual flags for the CPU specific part to understand which API called the registered function. This technique would avoid the populating of too many function pointers. There would be two different function pointers for setting and reading the registers in this case. (These APIs will be hence forth referred to as Group B)

List of the specific APIs as per their Implementations:

Group A PWRDM_INIT PWRDM_WAIT_TRANSITION PWRDM_STATE_SWITCH

Group B

PWRDM_SET_NEXT_PWRST PWRDM_READ_NEXT_PWRST PWRDM_READ_PWRST PWRDM_READ_PREV_PWRST PWRDM_CLEAR_ALL_PREV_PWRST PWRDM_SET_LOGIC_RETST PWRDM_SET_MEM_ONST PWRDSM_SET_MEM_RETST PWRDM_READ_LOGIC_PWRST PWRDM_READ_PREV_LOGIC_PWRST PWRDM_READ_LOGIC_RETST PWRDM_READ_MEM_PWRST PWRDM_READ_PREV_MEM_PWRST PWRDM_READ_MEM_RETST

Note: pwrdm_clkdm_state_switch does not fall either in Group A or Group B. It calls a couple of Group A APIs internally.

Also except for the above mentioned APIs in this slide the remaining APIs will not call into CPU specific registered function pointers.

List of the Function Pointers to be registered per CPU Power domain init: This would take care of the initialization and registration of the power domains

Power domain modify: This would take care of all the APIs which would do the register write into specific registers

Power domain read: This would take care of all the APIs which are meant to read from the specific registers

Power domain transition wait: Ensures appropriate wait time for the power domain to safely transition

Power domain state switch: This would be used to make the power domain transition its state.

Clock Domain Cleanup
TBD