/** * omap4_hotplug_cpu: OMAP4 CPU hotplug entry * @cpu : CPU ID * @power_state: CPU low power state. */ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) { unsigned int cpu_state = 0; if (omap_rev() == OMAP4430_REV_ES1_0) return -ENXIO; if (power_state == PWRDM_POWER_OFF) cpu_state = 1; clear_cpu_prev_pwrst(cpu); set_cpu_next_pwrst(cpu, power_state); set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup)); scu_pwrst_prepare(cpu, power_state); /* * CPU never retuns back if targetted power state is OFF mode. * CPU ONLINE follows normal CPU ONLINE ptah via * omap_secondary_startup(). */ omap4_finish_suspend(cpu_state); set_cpu_next_pwrst(cpu, PWRDM_POWER_ON); return 0; }
/** * omap4_hotplug_cpu: OMAP4 CPU hotplug entry * @cpu : CPU ID * @power_state: CPU low power state. */ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) { struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu); unsigned int cpu_state = 0; if (omap_rev() == OMAP4430_REV_ES1_0) return -ENXIO; /* Use the achievable power state for the domain */ power_state = pwrdm_get_valid_lp_state(pm_info->pwrdm, false, power_state); if (power_state == PWRDM_POWER_OFF) cpu_state = 1; pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.hotplug_restart)); omap_pm_ops.scu_prepare(cpu, power_state); /* * CPU never retuns back if targeted power state is OFF mode. * CPU ONLINE follows normal CPU ONLINE ptah via * omap4_secondary_startup(). */ omap_pm_ops.finish_suspend(cpu_state); pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); return 0; }
/** * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function * The purpose of this function is to manage low power programming * of OMAP4 MPUSS subsystem * @cpu : CPU ID * @power_state: Low power state. * * MPUSS states for the context save: * save_state = * 0 - Nothing lost and no need to save: MPUSS INACTIVE * 1 - CPUx L1 and logic lost: MPUSS CSWR * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR * 3 - CPUx L1 and logic lost + GIC + L2 lost: DEVICE OFF */ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) { unsigned int save_state = 0; unsigned int wakeup_cpu; if (omap_rev() == OMAP4430_REV_ES1_0) return -ENXIO; switch (power_state) { case PWRDM_POWER_ON: case PWRDM_POWER_INACTIVE: save_state = 0; break; case PWRDM_POWER_OFF: save_state = 1; break; case PWRDM_POWER_RET: default: /* * CPUx CSWR is invalid hardware state. Also CPUx OSWR * doesn't make much scense, since logic is lost and $L1 * needs to be cleaned because of coherency. This makes * CPUx OSWR equivalent to CPUX OFF and hence not supported */ WARN_ON(1); return -ENXIO; } pwrdm_pre_transition(NULL); /* * Check MPUSS next state and save interrupt controller if needed. * In MPUSS OSWR or device OFF, interrupt controller contest is lost. */ mpuss_clear_prev_logic_pwrst(); if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) && (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF)) save_state = 2; cpu_clear_prev_logic_pwrst(cpu); set_cpu_next_pwrst(cpu, power_state); set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume)); scu_pwrst_prepare(cpu, power_state); l2x0_pwrst_prepare(cpu, save_state); /* * Call low level function with targeted low power state. */ cpu_suspend(save_state, omap4_finish_suspend); /* * Restore the CPUx power state to ON otherwise CPUx * power domain can transitions to programmed low power * state while doing WFI outside the low powe code. On * secure devices, CPUx does WFI which can result in * domain transition */ wakeup_cpu = smp_processor_id(); set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON); pwrdm_post_transition(NULL); return 0; }