0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/cpuidle.h>
0013 #include <linux/cpu_pm.h>
0014 #include <linux/init.h>
0015 #include <linux/mm.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/psci.h>
0018
0019 #include <asm/cpuidle.h>
0020 #include <asm/suspend.h>
0021
0022 #include <uapi/linux/psci.h>
0023
0024 #define CALXEDA_IDLE_PARAM \
0025 ((0 << PSCI_0_2_POWER_STATE_ID_SHIFT) | \
0026 (0 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) | \
0027 (PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT))
0028
0029 static int calxeda_idle_finish(unsigned long val)
0030 {
0031 return psci_ops.cpu_suspend(CALXEDA_IDLE_PARAM, __pa(cpu_resume));
0032 }
0033
0034 static int calxeda_pwrdown_idle(struct cpuidle_device *dev,
0035 struct cpuidle_driver *drv,
0036 int index)
0037 {
0038 cpu_pm_enter();
0039 cpu_suspend(0, calxeda_idle_finish);
0040 cpu_pm_exit();
0041
0042 return index;
0043 }
0044
0045 static struct cpuidle_driver calxeda_idle_driver = {
0046 .name = "calxeda_idle",
0047 .states = {
0048 ARM_CPUIDLE_WFI_STATE,
0049 {
0050 .name = "PG",
0051 .desc = "Power Gate",
0052 .exit_latency = 30,
0053 .power_usage = 50,
0054 .target_residency = 200,
0055 .enter = calxeda_pwrdown_idle,
0056 },
0057 },
0058 .state_count = 2,
0059 };
0060
0061 static int calxeda_cpuidle_probe(struct platform_device *pdev)
0062 {
0063 return cpuidle_register(&calxeda_idle_driver, NULL);
0064 }
0065
0066 static struct platform_driver calxeda_cpuidle_plat_driver = {
0067 .driver = {
0068 .name = "cpuidle-calxeda",
0069 },
0070 .probe = calxeda_cpuidle_probe,
0071 };
0072 builtin_platform_driver(calxeda_cpuidle_plat_driver);