Merge remote-tracking branch 'korg_arm-soc/timer/cleanup' into cleanup
[linux-3.10.git] / arch / arm / mach-imx / cpuidle.c
1 /*
2  * Copyright 2012 Freescale Semiconductor, Inc.
3  * Copyright 2012 Linaro Ltd.
4  *
5  * The code contained herein is licensed under the GNU General Public
6  * License. You may obtain a copy of the GNU General Public License
7  * Version 2 or later at the following locations:
8  *
9  * http://www.opensource.org/licenses/gpl-license.html
10  * http://www.gnu.org/copyleft/gpl.html
11  */
12
13 #include <linux/cpuidle.h>
14 #include <linux/err.h>
15 #include <linux/hrtimer.h>
16 #include <linux/io.h>
17 #include <linux/kernel.h>
18 #include <linux/slab.h>
19
20 static struct cpuidle_device __percpu * imx_cpuidle_devices;
21
22 static void __init imx_cpuidle_devices_uninit(void)
23 {
24         int cpu_id;
25         struct cpuidle_device *dev;
26
27         for_each_possible_cpu(cpu_id) {
28                 dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
29                 cpuidle_unregister_device(dev);
30         }
31
32         free_percpu(imx_cpuidle_devices);
33 }
34
35 int __init imx_cpuidle_init(struct cpuidle_driver *drv)
36 {
37         struct cpuidle_device *dev;
38         int cpu_id, ret;
39
40         if (drv->state_count > CPUIDLE_STATE_MAX) {
41                 pr_err("%s: state_count exceeds maximum\n", __func__);
42                 return -EINVAL;
43         }
44
45         ret = cpuidle_register_driver(drv);
46         if (ret) {
47                 pr_err("%s: Failed to register cpuidle driver with error: %d\n",
48                          __func__, ret);
49                 return ret;
50         }
51
52         imx_cpuidle_devices = alloc_percpu(struct cpuidle_device);
53         if (imx_cpuidle_devices == NULL) {
54                 ret = -ENOMEM;
55                 goto unregister_drv;
56         }
57
58         /* initialize state data for each cpuidle_device */
59         for_each_possible_cpu(cpu_id) {
60                 dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
61                 dev->cpu = cpu_id;
62                 dev->state_count = drv->state_count;
63
64                 ret = cpuidle_register_device(dev);
65                 if (ret) {
66                         pr_err("%s: Failed to register cpu %u, error: %d\n",
67                                 __func__, cpu_id, ret);
68                         goto uninit;
69                 }
70         }
71
72         return 0;
73
74 uninit:
75         imx_cpuidle_devices_uninit();
76
77 unregister_drv:
78         cpuidle_unregister_driver(drv);
79         return ret;
80 }