/** Function to handle a GPU state change for the demand power policy * * This function is called whenever the GPU has transitioned to another state. It first checks that the transition is * complete and then moves the state machine to the next state. */ static void demand_state_changed(kbase_device *kbdev) { kbasep_pm_policy_demand *data = &kbdev->pm.policy_data.demand; switch(data->state) { case KBASEP_PM_DEMAND_STATE_CHANGING_POLICY: case KBASEP_PM_DEMAND_STATE_POWERING_UP: case KBASEP_PM_DEMAND_STATE_POWERING_DOWN: if (kbase_pm_get_pwr_active(kbdev)) { /* Cores are still transitioning - ignore the event */ return; } break; default: /* Must not call kbase_pm_get_pwr_active here as the clock may be turned off */ break; } switch(data->state) { case KBASEP_PM_DEMAND_STATE_CHANGING_POLICY: /* Signal power events before switching the policy */ kbase_pm_power_up_done(kbdev); kbase_pm_power_down_done(kbdev); kbase_pm_change_policy(kbdev); break; case KBASEP_PM_DEMAND_STATE_POWERING_UP: data->state = KBASEP_PM_DEMAND_STATE_POWERED_UP; kbase_pm_power_up_done(kbdev); /* State changed, try to run jobs */ kbase_js_try_run_jobs(kbdev); break; case KBASEP_PM_DEMAND_STATE_POWERING_DOWN: data->state = KBASEP_PM_DEMAND_STATE_POWERED_DOWN; /* Disable interrupts and turn the clock off */ kbase_pm_disable_interrupts(kbdev); kbase_pm_clock_off(kbdev); kbase_pm_power_down_done(kbdev); break; case KBASEP_PM_DEMAND_STATE_POWERED_UP: /* Core states may have been changed, try to run jobs */ kbase_js_try_run_jobs(kbdev); break; default: break; } }
/** Function to handle a GPU state change for the coarse_demand power policy. * * This function is called whenever the GPU has transitioned to another state. It first checks that the transition is * complete and then moves the state machine to the next state. * * @param kbdev The kbase device structure for the device */ static void coarse_demand_state_changed(kbase_device *kbdev) { kbasep_pm_policy_coarse_demand *data = &kbdev->pm.policy_data.coarse_demand; /* No need to early-out if cores transitioning during the POWERING_UP state */ if (data->state != KBASEP_PM_COARSE_DEMAND_STATE_POWERING_UP && kbase_pm_get_pwr_active(kbdev)) { /* Cores are still transitioning - ignore the event */ return; } switch(data->state) { case KBASEP_PM_COARSE_DEMAND_STATE_POWERING_UP: /* All cores are ready, inform the OS */ data->state = KBASEP_PM_COARSE_DEMAND_STATE_POWERED_UP; kbase_pm_power_up_done(kbdev); /* * No need to submit jobs: * - All cores will be powered on * - Cores are made available even while they're transitioning to 'powered on' * - We signal power_up_done after calling kbase_pm_check_transitions(), which makes the cores available. * Hence, the submission of jobs will already be handled by the call-path that invoked kbase_pm_context_active() */ break; case KBASEP_PM_COARSE_DEMAND_STATE_POWERING_DOWN: data->state = KBASEP_PM_COARSE_DEMAND_STATE_POWERED_DOWN; /* All cores have transitioned, turn the clock and interrupts off */ kbase_pm_clock_off(kbdev); /* Inform the OS */ kbase_pm_power_down_done(kbdev); break; case KBASEP_PM_COARSE_DEMAND_STATE_CHANGING_POLICY: /* Signal power events before switching the policy */ kbase_pm_power_up_done(kbdev); kbase_pm_power_down_done(kbdev); kbase_pm_change_policy(kbdev); break; default: break; } }
/** Function to handle a GPU state change for the always_on power policy. * * This function is called whenever the GPU has transitioned to another state. It first checks that the transition is * complete and then moves the state machine to the next state. * * @param kbdev The kbase device structure for the device */ static void always_on_state_changed(kbase_device *kbdev) { kbasep_pm_policy_always_on *data = &kbdev->pm.policy_data.always_on; switch(data->state) { case KBASEP_PM_ALWAYS_ON_STATE_POWERING_UP: if (kbase_pm_get_pwr_active(kbdev)) { /* Cores still transitioning */ return; } /* All cores have transitioned, inform the OS */ kbase_pm_power_up_done(kbdev); data->state = KBASEP_PM_ALWAYS_ON_STATE_POWERED_UP; break; case KBASEP_PM_ALWAYS_ON_STATE_POWERING_DOWN: if (kbase_pm_get_pwr_active(kbdev)) { /* Cores still transitioning */ return; } /* All cores have transitioned, turn the clock and interrupts off */ kbase_pm_disable_interrupts(kbdev); kbase_pm_clock_off(kbdev); /* Inform the OS */ kbase_pm_power_down_done(kbdev); data->state = KBASEP_PM_ALWAYS_ON_STATE_POWERED_DOWN; break; case KBASEP_PM_ALWAYS_ON_STATE_CHANGING_POLICY: if (kbase_pm_get_pwr_active(kbdev)) { /* Cores still transitioning */ return; } /* All cores have transitioned, inform the system we can change policy*/ kbase_pm_change_policy(kbdev); break; default: break; } }
/** The event callback function for the demand power policy. * * This function is called to handle the events for the power policy. It calls the relevant handler function depending * on the type of the event. * * @param kbdev The kbase device structure for the device * @param event The event that should be processed */ static void demand_event(kbase_device *kbdev, kbase_pm_event event) { kbasep_pm_policy_demand *data = &kbdev->pm.policy_data.demand; switch(event) { case KBASE_PM_EVENT_POLICY_INIT: demand_power_up(kbdev); break; case KBASE_PM_EVENT_POLICY_CHANGE: if (data->state == KBASEP_PM_DEMAND_STATE_POWERED_UP || data->state == KBASEP_PM_DEMAND_STATE_POWERED_DOWN) { kbase_pm_change_policy(kbdev); } else { data->state = KBASEP_PM_DEMAND_STATE_CHANGING_POLICY; } break; case KBASE_PM_EVENT_SYSTEM_RESUME: case KBASE_PM_EVENT_GPU_ACTIVE: switch (data->state) { case KBASEP_PM_DEMAND_STATE_POWERING_UP: break; case KBASEP_PM_DEMAND_STATE_POWERED_UP: kbase_pm_power_up_done(kbdev); break; default: demand_power_up(kbdev); } break; case KBASE_PM_EVENT_SYSTEM_SUSPEND: case KBASE_PM_EVENT_GPU_IDLE: switch (data->state) { case KBASEP_PM_DEMAND_STATE_POWERING_DOWN: break; case KBASEP_PM_DEMAND_STATE_POWERED_DOWN: kbase_pm_power_down_done(kbdev); break; default: demand_power_down(kbdev); } break; case KBASE_PM_EVENT_CHANGE_GPU_STATE: if (data->state != KBASEP_PM_DEMAND_STATE_POWERED_DOWN && data->state != KBASEP_PM_DEMAND_STATE_POWERING_DOWN) { demand_change_gpu_state(kbdev); } break; case KBASE_PM_EVENT_GPU_STATE_CHANGED: demand_state_changed(kbdev); break; default: /* unrecognized event, should never happen */ OSK_ASSERT(0); } }
/** The event callback function for the coarse_demand power policy. * * This function is called to handle the events for the power policy. It calls the relevant handler function depending * on the type of the event. * * @param kbdev The kbase device structure for the device * @param event The event that should be processed */ static void coarse_demand_event(kbase_device *kbdev, kbase_pm_event event) { kbasep_pm_policy_coarse_demand *data = &kbdev->pm.policy_data.coarse_demand; switch(event) { case KBASE_PM_EVENT_POLICY_INIT: coarse_demand_power_up(kbdev); break; case KBASE_PM_EVENT_SYSTEM_SUSPEND: switch (data->state) { case KBASEP_PM_COARSE_DEMAND_STATE_POWERING_DOWN: break; case KBASEP_PM_COARSE_DEMAND_STATE_POWERED_DOWN: kbase_pm_power_down_done(kbdev); break; default: coarse_demand_suspend(kbdev); } break; case KBASE_PM_EVENT_GPU_IDLE: switch (data->state) { case KBASEP_PM_COARSE_DEMAND_STATE_POWERING_DOWN: break; case KBASEP_PM_COARSE_DEMAND_STATE_POWERED_DOWN: kbase_pm_power_down_done(kbdev); break; default: coarse_demand_power_down(kbdev); } break; case KBASE_PM_EVENT_GPU_ACTIVE: case KBASE_PM_EVENT_SYSTEM_RESUME: switch (data->state) { case KBASEP_PM_COARSE_DEMAND_STATE_POWERING_UP: break; case KBASEP_PM_COARSE_DEMAND_STATE_POWERED_UP: kbase_pm_power_up_done(kbdev); break; default: coarse_demand_power_up(kbdev); } break; case KBASE_PM_EVENT_GPU_STATE_CHANGED: coarse_demand_state_changed(kbdev); break; case KBASE_PM_EVENT_POLICY_CHANGE: if (data->state == KBASEP_PM_COARSE_DEMAND_STATE_POWERED_UP || data->state == KBASEP_PM_COARSE_DEMAND_STATE_POWERED_DOWN) { kbase_pm_change_policy(kbdev); } else { data->state = KBASEP_PM_COARSE_DEMAND_STATE_CHANGING_POLICY; } break; case KBASE_PM_EVENT_CHANGE_GPU_STATE: if (data->state != KBASEP_PM_COARSE_DEMAND_STATE_POWERED_DOWN && data->state != KBASEP_PM_COARSE_DEMAND_STATE_POWERING_DOWN) { /* * Update anyone waiting for power up events. */ kbase_pm_check_transitions(kbdev); } break; default: /* Unrecognised event - this should never happen */ OSK_ASSERT(0); } }