1 /*
2  * cpuidle.h - a generic framework for CPU idle power management
3  *
4  * (C) 2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
5  *          Shaohua Li <shaohua.li@intel.com>
6  *          Adam Belay <abelay@novell.com>
7  *
8  * This code is licenced under the GPL.
9  */
10 
11 #ifndef _LINUX_CPUIDLE_H
12 #define _LINUX_CPUIDLE_H
13 
14 #include <linux/percpu.h>
15 #include <linux/list.h>
16 #include <linux/kobject.h>
17 #include <linux/completion.h>
18 
19 #define CPUIDLE_STATE_MAX	8
20 #define CPUIDLE_NAME_LEN	16
21 #define CPUIDLE_DESC_LEN	32
22 
23 struct module;
24 
25 struct cpuidle_device;
26 struct cpuidle_driver;
27 
28 
29 /****************************
30  * CPUIDLE DEVICE INTERFACE *
31  ****************************/
32 
33 struct cpuidle_state_usage {
34 	void		*driver_data;
35 
36 	unsigned long long	usage;
37 	unsigned long long	time; /* in US */
38 };
39 
40 struct cpuidle_state {
41 	char		name[CPUIDLE_NAME_LEN];
42 	char		desc[CPUIDLE_DESC_LEN];
43 
44 	unsigned int	flags;
45 	unsigned int	exit_latency; /* in US */
46 	unsigned int	power_usage; /* in mW */
47 	unsigned int	target_residency; /* in US */
48 
49 	int (*enter)	(struct cpuidle_device *dev,
50 			struct cpuidle_driver *drv,
51 			int index);
52 };
53 
54 /* Idle State Flags */
55 #define CPUIDLE_FLAG_TIME_VALID	(0x01) /* is residency time measurable? */
56 
57 #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
58 
59 /**
60  * cpuidle_get_statedata - retrieves private driver state data
61  * @st_usage: the state usage statistics
62  */
cpuidle_get_statedata(struct cpuidle_state_usage * st_usage)63 static inline void *cpuidle_get_statedata(struct cpuidle_state_usage *st_usage)
64 {
65 	return st_usage->driver_data;
66 }
67 
68 /**
69  * cpuidle_set_statedata - stores private driver state data
70  * @st_usage: the state usage statistics
71  * @data: the private data
72  */
73 static inline void
cpuidle_set_statedata(struct cpuidle_state_usage * st_usage,void * data)74 cpuidle_set_statedata(struct cpuidle_state_usage *st_usage, void *data)
75 {
76 	st_usage->driver_data = data;
77 }
78 
79 struct cpuidle_state_kobj {
80 	struct cpuidle_state *state;
81 	struct cpuidle_state_usage *state_usage;
82 	struct completion kobj_unregister;
83 	struct kobject kobj;
84 };
85 
86 struct cpuidle_device {
87 	unsigned int		registered:1;
88 	unsigned int		enabled:1;
89 	unsigned int		cpu;
90 
91 	int			last_residency;
92 	int			state_count;
93 	struct cpuidle_state_usage	states_usage[CPUIDLE_STATE_MAX];
94 	struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
95 
96 	struct list_head 	device_list;
97 	struct kobject		kobj;
98 	struct completion	kobj_unregister;
99 	void			*governor_data;
100 };
101 
102 DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
103 
104 /**
105  * cpuidle_get_last_residency - retrieves the last state's residency time
106  * @dev: the target CPU
107  *
108  * NOTE: this value is invalid if CPUIDLE_FLAG_TIME_VALID isn't set
109  */
cpuidle_get_last_residency(struct cpuidle_device * dev)110 static inline int cpuidle_get_last_residency(struct cpuidle_device *dev)
111 {
112 	return dev->last_residency;
113 }
114 
115 
116 /****************************
117  * CPUIDLE DRIVER INTERFACE *
118  ****************************/
119 
120 struct cpuidle_driver {
121 	char			name[CPUIDLE_NAME_LEN];
122 	struct module 		*owner;
123 
124 	unsigned int		power_specified:1;
125 	struct cpuidle_state	states[CPUIDLE_STATE_MAX];
126 	int			state_count;
127 	int			safe_state_index;
128 };
129 
130 #ifdef CONFIG_CPU_IDLE
131 extern void disable_cpuidle(void);
132 extern int cpuidle_idle_call(void);
133 extern int cpuidle_register_driver(struct cpuidle_driver *drv);
134 struct cpuidle_driver *cpuidle_get_driver(void);
135 extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
136 extern int cpuidle_register_device(struct cpuidle_device *dev);
137 extern void cpuidle_unregister_device(struct cpuidle_device *dev);
138 
139 extern void cpuidle_pause_and_lock(void);
140 extern void cpuidle_resume_and_unlock(void);
141 extern int cpuidle_enable_device(struct cpuidle_device *dev);
142 extern void cpuidle_disable_device(struct cpuidle_device *dev);
143 
144 #else
disable_cpuidle(void)145 static inline void disable_cpuidle(void) { }
cpuidle_idle_call(void)146 static inline int cpuidle_idle_call(void) { return -ENODEV; }
cpuidle_register_driver(struct cpuidle_driver * drv)147 static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
148 {return -ENODEV; }
cpuidle_get_driver(void)149 static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
cpuidle_unregister_driver(struct cpuidle_driver * drv)150 static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
cpuidle_register_device(struct cpuidle_device * dev)151 static inline int cpuidle_register_device(struct cpuidle_device *dev)
152 {return -ENODEV; }
cpuidle_unregister_device(struct cpuidle_device * dev)153 static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { }
154 
cpuidle_pause_and_lock(void)155 static inline void cpuidle_pause_and_lock(void) { }
cpuidle_resume_and_unlock(void)156 static inline void cpuidle_resume_and_unlock(void) { }
cpuidle_enable_device(struct cpuidle_device * dev)157 static inline int cpuidle_enable_device(struct cpuidle_device *dev)
158 {return -ENODEV; }
cpuidle_disable_device(struct cpuidle_device * dev)159 static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
160 
161 #endif
162 
163 /******************************
164  * CPUIDLE GOVERNOR INTERFACE *
165  ******************************/
166 
167 struct cpuidle_governor {
168 	char			name[CPUIDLE_NAME_LEN];
169 	struct list_head 	governor_list;
170 	unsigned int		rating;
171 
172 	int  (*enable)		(struct cpuidle_driver *drv,
173 					struct cpuidle_device *dev);
174 	void (*disable)		(struct cpuidle_driver *drv,
175 					struct cpuidle_device *dev);
176 
177 	int  (*select)		(struct cpuidle_driver *drv,
178 					struct cpuidle_device *dev);
179 	void (*reflect)		(struct cpuidle_device *dev, int index);
180 
181 	struct module 		*owner;
182 };
183 
184 #ifdef CONFIG_CPU_IDLE
185 
186 extern int cpuidle_register_governor(struct cpuidle_governor *gov);
187 extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
188 
189 #ifdef CONFIG_INTEL_IDLE
190 extern int intel_idle_cpu_init(int cpu);
191 #else
intel_idle_cpu_init(int cpu)192 static inline int intel_idle_cpu_init(int cpu) { return -1; }
193 #endif
194 
195 #else
intel_idle_cpu_init(int cpu)196 static inline int intel_idle_cpu_init(int cpu) { return -1; }
197 
cpuidle_register_governor(struct cpuidle_governor * gov)198 static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
199 {return 0;}
cpuidle_unregister_governor(struct cpuidle_governor * gov)200 static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { }
201 
202 #endif
203 
204 #ifdef CONFIG_ARCH_HAS_CPU_RELAX
205 #define CPUIDLE_DRIVER_STATE_START	1
206 #else
207 #define CPUIDLE_DRIVER_STATE_START	0
208 #endif
209 
210 #endif /* _LINUX_CPUIDLE_H */
211