2 * Copyright (C) 2012 ROCKCHIP, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #define pr_fmt(fmt) "cpuidle: %s: " fmt, __func__
12 #include <linux/cpuidle.h>
13 #include <linux/suspend.h>
14 #include <linux/err.h>
16 #include <asm/hardware/gic.h>
19 static bool rk30_gic_interrupt_pending(void)
21 return (readl_relaxed(RK30_GICC_BASE + GIC_CPU_HIGHPRI) != 0x3FF);
24 static void rk30_wfi_until_interrupt(void)
29 if (!rk30_gic_interrupt_pending())
33 static int rk30_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
35 ktime_t preidle, postidle;
39 preidle = ktime_get();
41 rk30_wfi_until_interrupt();
43 postidle = ktime_get();
48 return ktime_to_us(ktime_sub(postidle, preidle));
51 static DEFINE_PER_CPU(struct cpuidle_device, rk30_cpuidle_device);
53 static __initdata struct cpuidle_state rk30_cpuidle_states[] = {
57 .flags = CPUIDLE_FLAG_TIME_VALID,
59 .target_residency = 0,
64 static struct cpuidle_driver rk30_cpuidle_driver = {
65 .name = "rk30_cpuidle",
69 static int __init rk30_cpuidle_init(void)
71 struct cpuidle_device *dev;
75 ret = cpuidle_register_driver(&rk30_cpuidle_driver);
77 pr_err("failed to register cpuidle driver: %d\n", ret);
81 for_each_possible_cpu(cpu) {
82 dev = &per_cpu(rk30_cpuidle_device, cpu);
84 dev->state_count = ARRAY_SIZE(rk30_cpuidle_states);
85 memcpy(dev->states, rk30_cpuidle_states, sizeof(rk30_cpuidle_states));
86 dev->safe_state = &dev->states[0];
88 ret = cpuidle_register_device(dev);
90 pr_err("failed to register cpuidle device for cpu %u: %d\n", cpu, ret);
97 late_initcall(rk30_cpuidle_init);