xref: /linux-6.15/include/linux/cpuidle.h (revision 615c36f5)
1 /*
2  * cpuidle.h - a generic framework for CPU idle power management
3  *
4  * (C) 2007 Venkatesh Pallipadi <[email protected]>
5  *          Shaohua Li <[email protected]>
6  *          Adam Belay <[email protected]>
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  */
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
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  */
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 
134 extern int cpuidle_register_driver(struct cpuidle_driver *drv);
135 struct cpuidle_driver *cpuidle_get_driver(void);
136 extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
137 extern int cpuidle_register_device(struct cpuidle_device *dev);
138 extern void cpuidle_unregister_device(struct cpuidle_device *dev);
139 
140 extern void cpuidle_pause_and_lock(void);
141 extern void cpuidle_resume_and_unlock(void);
142 extern int cpuidle_enable_device(struct cpuidle_device *dev);
143 extern void cpuidle_disable_device(struct cpuidle_device *dev);
144 
145 #else
146 static inline void disable_cpuidle(void) { }
147 static inline int cpuidle_idle_call(void) { return -ENODEV; }
148 
149 static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
150 {return -ENODEV; }
151 static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
152 static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
153 static inline int cpuidle_register_device(struct cpuidle_device *dev)
154 {return -ENODEV; }
155 static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { }
156 
157 static inline void cpuidle_pause_and_lock(void) { }
158 static inline void cpuidle_resume_and_unlock(void) { }
159 static inline int cpuidle_enable_device(struct cpuidle_device *dev)
160 {return -ENODEV; }
161 static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
162 
163 #endif
164 
165 /******************************
166  * CPUIDLE GOVERNOR INTERFACE *
167  ******************************/
168 
169 struct cpuidle_governor {
170 	char			name[CPUIDLE_NAME_LEN];
171 	struct list_head 	governor_list;
172 	unsigned int		rating;
173 
174 	int  (*enable)		(struct cpuidle_driver *drv,
175 					struct cpuidle_device *dev);
176 	void (*disable)		(struct cpuidle_driver *drv,
177 					struct cpuidle_device *dev);
178 
179 	int  (*select)		(struct cpuidle_driver *drv,
180 					struct cpuidle_device *dev);
181 	void (*reflect)		(struct cpuidle_device *dev, int index);
182 
183 	struct module 		*owner;
184 };
185 
186 #ifdef CONFIG_CPU_IDLE
187 
188 extern int cpuidle_register_governor(struct cpuidle_governor *gov);
189 extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
190 
191 #else
192 
193 static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
194 {return 0;}
195 static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { }
196 
197 #endif
198 
199 #ifdef CONFIG_ARCH_HAS_CPU_RELAX
200 #define CPUIDLE_DRIVER_STATE_START	1
201 #else
202 #define CPUIDLE_DRIVER_STATE_START	0
203 #endif
204 
205 #endif /* _LINUX_CPUIDLE_H */
206