diff options
-rw-r--r-- | drivers/Kconfig | 2 | ||||
-rw-r--r-- | drivers/Makefile | 2 | ||||
-rw-r--r-- | drivers/devfreq/Kconfig | 39 | ||||
-rw-r--r-- | drivers/devfreq/Makefile | 1 | ||||
-rw-r--r-- | drivers/devfreq/devfreq.c | 532 | ||||
-rw-r--r-- | drivers/devfreq/governor.h | 24 | ||||
-rw-r--r-- | include/linux/devfreq.h | 203 |
7 files changed, 803 insertions, 0 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 95b9e7eefadc..a1efd75070aa 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -130,4 +130,6 @@ source "drivers/iommu/Kconfig" | |||
130 | 130 | ||
131 | source "drivers/virt/Kconfig" | 131 | source "drivers/virt/Kconfig" |
132 | 132 | ||
133 | source "drivers/devfreq/Kconfig" | ||
134 | |||
133 | endmenu | 135 | endmenu |
diff --git a/drivers/Makefile b/drivers/Makefile index 7fa433a7030c..97c957b50819 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -127,3 +127,5 @@ obj-$(CONFIG_IOMMU_SUPPORT) += iommu/ | |||
127 | 127 | ||
128 | # Virtualization drivers | 128 | # Virtualization drivers |
129 | obj-$(CONFIG_VIRT_DRIVERS) += virt/ | 129 | obj-$(CONFIG_VIRT_DRIVERS) += virt/ |
130 | |||
131 | obj-$(CONFIG_PM_DEVFREQ) += devfreq/ | ||
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig new file mode 100644 index 000000000000..1fb42de4f420 --- /dev/null +++ b/drivers/devfreq/Kconfig | |||
@@ -0,0 +1,39 @@ | |||
1 | config ARCH_HAS_DEVFREQ | ||
2 | bool | ||
3 | depends on ARCH_HAS_OPP | ||
4 | help | ||
5 | Denotes that the architecture supports DEVFREQ. If the architecture | ||
6 | supports multiple OPP entries per device and the frequency of the | ||
7 | devices with OPPs may be altered dynamically, the architecture | ||
8 | supports DEVFREQ. | ||
9 | |||
10 | menuconfig PM_DEVFREQ | ||
11 | bool "Generic Dynamic Voltage and Frequency Scaling (DVFS) support" | ||
12 | depends on PM_OPP && ARCH_HAS_DEVFREQ | ||
13 | help | ||
14 | With OPP support, a device may have a list of frequencies and | ||
15 | voltages available. DEVFREQ, a generic DVFS framework can be | ||
16 | registered for a device with OPP support in order to let the | ||
17 | governor provided to DEVFREQ choose an operating frequency | ||
18 | based on the OPP's list and the policy given with DEVFREQ. | ||
19 | |||
20 | Each device may have its own governor and policy. DEVFREQ can | ||
21 | reevaluate the device state periodically and/or based on the | ||
22 | OPP list changes (each frequency/voltage pair in OPP may be | ||
23 | disabled or enabled). | ||
24 | |||
25 | Like some CPUs with CPUFREQ, a device may have multiple clocks. | ||
26 | However, because the clock frequencies of a single device are | ||
27 | determined by the single device's state, an instance of DEVFREQ | ||
28 | is attached to a single device and returns a "representative" | ||
29 | clock frequency from the OPP of the device, which is also attached | ||
30 | to a device by 1-to-1. The device registering DEVFREQ takes the | ||
31 | responsiblity to "interpret" the frequency listed in OPP and | ||
32 | to set its every clock accordingly with the "target" callback | ||
33 | given to DEVFREQ. | ||
34 | |||
35 | if PM_DEVFREQ | ||
36 | |||
37 | comment "DEVFREQ Drivers" | ||
38 | |||
39 | endif # PM_DEVFREQ | ||
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile new file mode 100644 index 000000000000..168934a12b38 --- /dev/null +++ b/drivers/devfreq/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_PM_DEVFREQ) += devfreq.o | |||
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c new file mode 100644 index 000000000000..f3100b19f798 --- /dev/null +++ b/drivers/devfreq/devfreq.c | |||
@@ -0,0 +1,532 @@ | |||
1 | /* | ||
2 | * devfreq: Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework | ||
3 | * for Non-CPU Devices. | ||
4 | * | ||
5 | * Copyright (C) 2011 Samsung Electronics | ||
6 | * MyungJoo Ham <myungjoo.ham@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/opp.h> | ||
20 | #include <linux/devfreq.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/printk.h> | ||
25 | #include <linux/hrtimer.h> | ||
26 | #include "governor.h" | ||
27 | |||
28 | struct class *devfreq_class; | ||
29 | |||
30 | /* | ||
31 | * devfreq_work periodically monitors every registered device. | ||
32 | * The minimum polling interval is one jiffy. The polling interval is | ||
33 | * determined by the minimum polling period among all polling devfreq | ||
34 | * devices. The resolution of polling interval is one jiffy. | ||
35 | */ | ||
36 | static bool polling; | ||
37 | static struct workqueue_struct *devfreq_wq; | ||
38 | static struct delayed_work devfreq_work; | ||
39 | |||
40 | /* wait removing if this is to be removed */ | ||
41 | static struct devfreq *wait_remove_device; | ||
42 | |||
43 | /* The list of all device-devfreq */ | ||
44 | static LIST_HEAD(devfreq_list); | ||
45 | static DEFINE_MUTEX(devfreq_list_lock); | ||
46 | |||
47 | /** | ||
48 | * find_device_devfreq() - find devfreq struct using device pointer | ||
49 | * @dev: device pointer used to lookup device devfreq. | ||
50 | * | ||
51 | * Search the list of device devfreqs and return the matched device's | ||
52 | * devfreq info. devfreq_list_lock should be held by the caller. | ||
53 | */ | ||
54 | static struct devfreq *find_device_devfreq(struct device *dev) | ||
55 | { | ||
56 | struct devfreq *tmp_devfreq; | ||
57 | |||
58 | if (unlikely(IS_ERR_OR_NULL(dev))) { | ||
59 | pr_err("DEVFREQ: %s: Invalid parameters\n", __func__); | ||
60 | return ERR_PTR(-EINVAL); | ||
61 | } | ||
62 | WARN(!mutex_is_locked(&devfreq_list_lock), | ||
63 | "devfreq_list_lock must be locked."); | ||
64 | |||
65 | list_for_each_entry(tmp_devfreq, &devfreq_list, node) { | ||
66 | if (tmp_devfreq->dev.parent == dev) | ||
67 | return tmp_devfreq; | ||
68 | } | ||
69 | |||
70 | return ERR_PTR(-ENODEV); | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * update_devfreq() - Reevaluate the device and configure frequency. | ||
75 | * @devfreq: the devfreq instance. | ||
76 | * | ||
77 | * Note: Lock devfreq->lock before calling update_devfreq | ||
78 | * This function is exported for governors. | ||
79 | */ | ||
80 | int update_devfreq(struct devfreq *devfreq) | ||
81 | { | ||
82 | unsigned long freq; | ||
83 | int err = 0; | ||
84 | |||
85 | if (!mutex_is_locked(&devfreq->lock)) { | ||
86 | WARN(true, "devfreq->lock must be locked by the caller.\n"); | ||
87 | return -EINVAL; | ||
88 | } | ||
89 | |||
90 | /* Reevaluate the proper frequency */ | ||
91 | err = devfreq->governor->get_target_freq(devfreq, &freq); | ||
92 | if (err) | ||
93 | return err; | ||
94 | |||
95 | err = devfreq->profile->target(devfreq->dev.parent, &freq); | ||
96 | if (err) | ||
97 | return err; | ||
98 | |||
99 | devfreq->previous_freq = freq; | ||
100 | return err; | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * devfreq_notifier_call() - Notify that the device frequency requirements | ||
105 | * has been changed out of devfreq framework. | ||
106 | * @nb the notifier_block (supposed to be devfreq->nb) | ||
107 | * @type not used | ||
108 | * @devp not used | ||
109 | * | ||
110 | * Called by a notifier that uses devfreq->nb. | ||
111 | */ | ||
112 | static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type, | ||
113 | void *devp) | ||
114 | { | ||
115 | struct devfreq *devfreq = container_of(nb, struct devfreq, nb); | ||
116 | int ret; | ||
117 | |||
118 | mutex_lock(&devfreq->lock); | ||
119 | ret = update_devfreq(devfreq); | ||
120 | mutex_unlock(&devfreq->lock); | ||
121 | |||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * _remove_devfreq() - Remove devfreq from the device. | ||
127 | * @devfreq: the devfreq struct | ||
128 | * @skip: skip calling device_unregister(). | ||
129 | * | ||
130 | * Note that the caller should lock devfreq->lock before calling | ||
131 | * this. _remove_devfreq() will unlock it and free devfreq | ||
132 | * internally. devfreq_list_lock should be locked by the caller | ||
133 | * as well (not relased at return) | ||
134 | * | ||
135 | * Lock usage: | ||
136 | * devfreq->lock: locked before call. | ||
137 | * unlocked at return (and freed) | ||
138 | * devfreq_list_lock: locked before call. | ||
139 | * kept locked at return. | ||
140 | * if devfreq is centrally polled. | ||
141 | * | ||
142 | * Freed memory: | ||
143 | * devfreq | ||
144 | */ | ||
145 | static void _remove_devfreq(struct devfreq *devfreq, bool skip) | ||
146 | { | ||
147 | if (!mutex_is_locked(&devfreq->lock)) { | ||
148 | WARN(true, "devfreq->lock must be locked by the caller.\n"); | ||
149 | return; | ||
150 | } | ||
151 | if (!devfreq->governor->no_central_polling && | ||
152 | !mutex_is_locked(&devfreq_list_lock)) { | ||
153 | WARN(true, "devfreq_list_lock must be locked by the caller.\n"); | ||
154 | return; | ||
155 | } | ||
156 | |||
157 | if (devfreq->being_removed) | ||
158 | return; | ||
159 | |||
160 | devfreq->being_removed = true; | ||
161 | |||
162 | if (devfreq->profile->exit) | ||
163 | devfreq->profile->exit(devfreq->dev.parent); | ||
164 | |||
165 | if (devfreq->governor->exit) | ||
166 | devfreq->governor->exit(devfreq); | ||
167 | |||
168 | if (!skip && get_device(&devfreq->dev)) { | ||
169 | device_unregister(&devfreq->dev); | ||
170 | put_device(&devfreq->dev); | ||
171 | } | ||
172 | |||
173 | if (!devfreq->governor->no_central_polling) | ||
174 | list_del(&devfreq->node); | ||
175 | |||
176 | mutex_unlock(&devfreq->lock); | ||
177 | mutex_destroy(&devfreq->lock); | ||
178 | |||
179 | kfree(devfreq); | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * devfreq_dev_release() - Callback for struct device to release the device. | ||
184 | * @dev: the devfreq device | ||
185 | * | ||
186 | * This calls _remove_devfreq() if _remove_devfreq() is not called. | ||
187 | * Note that devfreq_dev_release() could be called by _remove_devfreq() as | ||
188 | * well as by others unregistering the device. | ||
189 | */ | ||
190 | static void devfreq_dev_release(struct device *dev) | ||
191 | { | ||
192 | struct devfreq *devfreq = to_devfreq(dev); | ||
193 | bool central_polling = !devfreq->governor->no_central_polling; | ||
194 | |||
195 | /* | ||
196 | * If devfreq_dev_release() was called by device_unregister() of | ||
197 | * _remove_devfreq(), we cannot mutex_lock(&devfreq->lock) and | ||
198 | * being_removed is already set. This also partially checks the case | ||
199 | * where devfreq_dev_release() is called from a thread other than | ||
200 | * the one called _remove_devfreq(); however, this case is | ||
201 | * dealt completely with another following being_removed check. | ||
202 | * | ||
203 | * Because being_removed is never being | ||
204 | * unset, we do not need to worry about race conditions on | ||
205 | * being_removed. | ||
206 | */ | ||
207 | if (devfreq->being_removed) | ||
208 | return; | ||
209 | |||
210 | if (central_polling) | ||
211 | mutex_lock(&devfreq_list_lock); | ||
212 | |||
213 | mutex_lock(&devfreq->lock); | ||
214 | |||
215 | /* | ||
216 | * Check being_removed flag again for the case where | ||
217 | * devfreq_dev_release() was called in a thread other than the one | ||
218 | * possibly called _remove_devfreq(). | ||
219 | */ | ||
220 | if (devfreq->being_removed) { | ||
221 | mutex_unlock(&devfreq->lock); | ||
222 | goto out; | ||
223 | } | ||
224 | |||
225 | /* devfreq->lock is unlocked and removed in _removed_devfreq() */ | ||
226 | _remove_devfreq(devfreq, true); | ||
227 | |||
228 | out: | ||
229 | if (central_polling) | ||
230 | mutex_unlock(&devfreq_list_lock); | ||
231 | } | ||
232 | |||
233 | /** | ||
234 | * devfreq_monitor() - Periodically poll devfreq objects. | ||
235 | * @work: the work struct used to run devfreq_monitor periodically. | ||
236 | * | ||
237 | */ | ||
238 | static void devfreq_monitor(struct work_struct *work) | ||
239 | { | ||
240 | static unsigned long last_polled_at; | ||
241 | struct devfreq *devfreq, *tmp; | ||
242 | int error; | ||
243 | unsigned long jiffies_passed; | ||
244 | unsigned long next_jiffies = ULONG_MAX, now = jiffies; | ||
245 | struct device *dev; | ||
246 | |||
247 | /* Initially last_polled_at = 0, polling every device at bootup */ | ||
248 | jiffies_passed = now - last_polled_at; | ||
249 | last_polled_at = now; | ||
250 | if (jiffies_passed == 0) | ||
251 | jiffies_passed = 1; | ||
252 | |||
253 | mutex_lock(&devfreq_list_lock); | ||
254 | list_for_each_entry_safe(devfreq, tmp, &devfreq_list, node) { | ||
255 | mutex_lock(&devfreq->lock); | ||
256 | dev = devfreq->dev.parent; | ||
257 | |||
258 | /* Do not remove tmp for a while */ | ||
259 | wait_remove_device = tmp; | ||
260 | |||
261 | if (devfreq->governor->no_central_polling || | ||
262 | devfreq->next_polling == 0) { | ||
263 | mutex_unlock(&devfreq->lock); | ||
264 | continue; | ||
265 | } | ||
266 | mutex_unlock(&devfreq_list_lock); | ||
267 | |||
268 | /* | ||
269 | * Reduce more next_polling if devfreq_wq took an extra | ||
270 | * delay. (i.e., CPU has been idled.) | ||
271 | */ | ||
272 | if (devfreq->next_polling <= jiffies_passed) { | ||
273 | error = update_devfreq(devfreq); | ||
274 | |||
275 | /* Remove a devfreq with an error. */ | ||
276 | if (error && error != -EAGAIN) { | ||
277 | |||
278 | dev_err(dev, "Due to update_devfreq error(%d), devfreq(%s) is removed from the device\n", | ||
279 | error, devfreq->governor->name); | ||
280 | |||
281 | /* | ||
282 | * Unlock devfreq before locking the list | ||
283 | * in order to avoid deadlock with | ||
284 | * find_device_devfreq or others | ||
285 | */ | ||
286 | mutex_unlock(&devfreq->lock); | ||
287 | mutex_lock(&devfreq_list_lock); | ||
288 | /* Check if devfreq is already removed */ | ||
289 | if (IS_ERR(find_device_devfreq(dev))) | ||
290 | continue; | ||
291 | mutex_lock(&devfreq->lock); | ||
292 | /* This unlocks devfreq->lock and free it */ | ||
293 | _remove_devfreq(devfreq, false); | ||
294 | continue; | ||
295 | } | ||
296 | devfreq->next_polling = devfreq->polling_jiffies; | ||
297 | } else { | ||
298 | devfreq->next_polling -= jiffies_passed; | ||
299 | } | ||
300 | |||
301 | if (devfreq->next_polling) | ||
302 | next_jiffies = (next_jiffies > devfreq->next_polling) ? | ||
303 | devfreq->next_polling : next_jiffies; | ||
304 | |||
305 | mutex_unlock(&devfreq->lock); | ||
306 | mutex_lock(&devfreq_list_lock); | ||
307 | } | ||
308 | wait_remove_device = NULL; | ||
309 | mutex_unlock(&devfreq_list_lock); | ||
310 | |||
311 | if (next_jiffies > 0 && next_jiffies < ULONG_MAX) { | ||
312 | polling = true; | ||
313 | queue_delayed_work(devfreq_wq, &devfreq_work, next_jiffies); | ||
314 | } else { | ||
315 | polling = false; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * devfreq_add_device() - Add devfreq feature to the device | ||
321 | * @dev: the device to add devfreq feature. | ||
322 | * @profile: device-specific profile to run devfreq. | ||
323 | * @governor: the policy to choose frequency. | ||
324 | * @data: private data for the governor. The devfreq framework does not | ||
325 | * touch this value. | ||
326 | */ | ||
327 | struct devfreq *devfreq_add_device(struct device *dev, | ||
328 | struct devfreq_dev_profile *profile, | ||
329 | const struct devfreq_governor *governor, | ||
330 | void *data) | ||
331 | { | ||
332 | struct devfreq *devfreq; | ||
333 | int err = 0; | ||
334 | |||
335 | if (!dev || !profile || !governor) { | ||
336 | dev_err(dev, "%s: Invalid parameters.\n", __func__); | ||
337 | return ERR_PTR(-EINVAL); | ||
338 | } | ||
339 | |||
340 | |||
341 | if (!governor->no_central_polling) { | ||
342 | mutex_lock(&devfreq_list_lock); | ||
343 | devfreq = find_device_devfreq(dev); | ||
344 | mutex_unlock(&devfreq_list_lock); | ||
345 | if (!IS_ERR(devfreq)) { | ||
346 | dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__); | ||
347 | err = -EINVAL; | ||
348 | goto out; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL); | ||
353 | if (!devfreq) { | ||
354 | dev_err(dev, "%s: Unable to create devfreq for the device\n", | ||
355 | __func__); | ||
356 | err = -ENOMEM; | ||
357 | goto out; | ||
358 | } | ||
359 | |||
360 | mutex_init(&devfreq->lock); | ||
361 | mutex_lock(&devfreq->lock); | ||
362 | devfreq->dev.parent = dev; | ||
363 | devfreq->dev.class = devfreq_class; | ||
364 | devfreq->dev.release = devfreq_dev_release; | ||
365 | devfreq->profile = profile; | ||
366 | devfreq->governor = governor; | ||
367 | devfreq->previous_freq = profile->initial_freq; | ||
368 | devfreq->data = data; | ||
369 | devfreq->next_polling = devfreq->polling_jiffies | ||
370 | = msecs_to_jiffies(devfreq->profile->polling_ms); | ||
371 | devfreq->nb.notifier_call = devfreq_notifier_call; | ||
372 | |||
373 | dev_set_name(&devfreq->dev, dev_name(dev)); | ||
374 | err = device_register(&devfreq->dev); | ||
375 | if (err) { | ||
376 | put_device(&devfreq->dev); | ||
377 | goto err_dev; | ||
378 | } | ||
379 | |||
380 | if (governor->init) | ||
381 | err = governor->init(devfreq); | ||
382 | if (err) | ||
383 | goto err_init; | ||
384 | |||
385 | mutex_unlock(&devfreq->lock); | ||
386 | |||
387 | if (governor->no_central_polling) | ||
388 | goto out; | ||
389 | |||
390 | mutex_lock(&devfreq_list_lock); | ||
391 | |||
392 | list_add(&devfreq->node, &devfreq_list); | ||
393 | |||
394 | if (devfreq_wq && devfreq->next_polling && !polling) { | ||
395 | polling = true; | ||
396 | queue_delayed_work(devfreq_wq, &devfreq_work, | ||
397 | devfreq->next_polling); | ||
398 | } | ||
399 | mutex_unlock(&devfreq_list_lock); | ||
400 | goto out; | ||
401 | err_init: | ||
402 | device_unregister(&devfreq->dev); | ||
403 | err_dev: | ||
404 | mutex_unlock(&devfreq->lock); | ||
405 | kfree(devfreq); | ||
406 | out: | ||
407 | if (err) | ||
408 | return ERR_PTR(err); | ||
409 | else | ||
410 | return devfreq; | ||
411 | } | ||
412 | |||
413 | /** | ||
414 | * devfreq_remove_device() - Remove devfreq feature from a device. | ||
415 | * @devfreq the devfreq instance to be removed | ||
416 | */ | ||
417 | int devfreq_remove_device(struct devfreq *devfreq) | ||
418 | { | ||
419 | if (!devfreq) | ||
420 | return -EINVAL; | ||
421 | |||
422 | if (!devfreq->governor->no_central_polling) { | ||
423 | mutex_lock(&devfreq_list_lock); | ||
424 | while (wait_remove_device == devfreq) { | ||
425 | mutex_unlock(&devfreq_list_lock); | ||
426 | schedule(); | ||
427 | mutex_lock(&devfreq_list_lock); | ||
428 | } | ||
429 | } | ||
430 | |||
431 | mutex_lock(&devfreq->lock); | ||
432 | _remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */ | ||
433 | |||
434 | if (!devfreq->governor->no_central_polling) | ||
435 | mutex_unlock(&devfreq_list_lock); | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | /** | ||
441 | * devfreq_start_polling() - Initialize data structure for devfreq framework and | ||
442 | * start polling registered devfreq devices. | ||
443 | */ | ||
444 | static int __init devfreq_start_polling(void) | ||
445 | { | ||
446 | mutex_lock(&devfreq_list_lock); | ||
447 | polling = false; | ||
448 | devfreq_wq = create_freezable_workqueue("devfreq_wq"); | ||
449 | INIT_DELAYED_WORK_DEFERRABLE(&devfreq_work, devfreq_monitor); | ||
450 | mutex_unlock(&devfreq_list_lock); | ||
451 | |||
452 | devfreq_monitor(&devfreq_work.work); | ||
453 | return 0; | ||
454 | } | ||
455 | late_initcall(devfreq_start_polling); | ||
456 | |||
457 | static int __init devfreq_init(void) | ||
458 | { | ||
459 | devfreq_class = class_create(THIS_MODULE, "devfreq"); | ||
460 | if (IS_ERR(devfreq_class)) { | ||
461 | pr_err("%s: couldn't create class\n", __FILE__); | ||
462 | return PTR_ERR(devfreq_class); | ||
463 | } | ||
464 | return 0; | ||
465 | } | ||
466 | subsys_initcall(devfreq_init); | ||
467 | |||
468 | static void __exit devfreq_exit(void) | ||
469 | { | ||
470 | class_destroy(devfreq_class); | ||
471 | } | ||
472 | module_exit(devfreq_exit); | ||
473 | |||
474 | /* | ||
475 | * The followings are helper functions for devfreq user device drivers with | ||
476 | * OPP framework. | ||
477 | */ | ||
478 | |||
479 | /** | ||
480 | * devfreq_recommended_opp() - Helper function to get proper OPP for the | ||
481 | * freq value given to target callback. | ||
482 | * @dev The devfreq user device. (parent of devfreq) | ||
483 | * @freq The frequency given to target function | ||
484 | * | ||
485 | */ | ||
486 | struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq) | ||
487 | { | ||
488 | struct opp *opp = opp_find_freq_ceil(dev, freq); | ||
489 | |||
490 | if (opp == ERR_PTR(-ENODEV)) | ||
491 | opp = opp_find_freq_floor(dev, freq); | ||
492 | return opp; | ||
493 | } | ||
494 | |||
495 | /** | ||
496 | * devfreq_register_opp_notifier() - Helper function to get devfreq notified | ||
497 | * for any changes in the OPP availability | ||
498 | * changes | ||
499 | * @dev The devfreq user device. (parent of devfreq) | ||
500 | * @devfreq The devfreq object. | ||
501 | */ | ||
502 | int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq) | ||
503 | { | ||
504 | struct srcu_notifier_head *nh = opp_get_notifier(dev); | ||
505 | |||
506 | if (IS_ERR(nh)) | ||
507 | return PTR_ERR(nh); | ||
508 | return srcu_notifier_chain_register(nh, &devfreq->nb); | ||
509 | } | ||
510 | |||
511 | /** | ||
512 | * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq | ||
513 | * notified for any changes in the OPP | ||
514 | * availability changes anymore. | ||
515 | * @dev The devfreq user device. (parent of devfreq) | ||
516 | * @devfreq The devfreq object. | ||
517 | * | ||
518 | * At exit() callback of devfreq_dev_profile, this must be included if | ||
519 | * devfreq_recommended_opp is used. | ||
520 | */ | ||
521 | int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq) | ||
522 | { | ||
523 | struct srcu_notifier_head *nh = opp_get_notifier(dev); | ||
524 | |||
525 | if (IS_ERR(nh)) | ||
526 | return PTR_ERR(nh); | ||
527 | return srcu_notifier_chain_unregister(nh, &devfreq->nb); | ||
528 | } | ||
529 | |||
530 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | ||
531 | MODULE_DESCRIPTION("devfreq class support"); | ||
532 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h new file mode 100644 index 000000000000..ea7f13c58ded --- /dev/null +++ b/drivers/devfreq/governor.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * governor.h - internal header for devfreq governors. | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics | ||
5 | * MyungJoo Ham <myungjoo.ham@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This header is for devfreq governors in drivers/devfreq/ | ||
12 | */ | ||
13 | |||
14 | #ifndef _GOVERNOR_H | ||
15 | #define _GOVERNOR_H | ||
16 | |||
17 | #include <linux/devfreq.h> | ||
18 | |||
19 | #define to_devfreq(DEV) container_of((DEV), struct devfreq, dev) | ||
20 | |||
21 | /* Caution: devfreq->lock must be locked before calling update_devfreq */ | ||
22 | extern int update_devfreq(struct devfreq *devfreq); | ||
23 | |||
24 | #endif /* _GOVERNOR_H */ | ||
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h new file mode 100644 index 000000000000..b3be3d3cbaa7 --- /dev/null +++ b/include/linux/devfreq.h | |||
@@ -0,0 +1,203 @@ | |||
1 | /* | ||
2 | * devfreq: Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework | ||
3 | * for Non-CPU Devices. | ||
4 | * | ||
5 | * Copyright (C) 2011 Samsung Electronics | ||
6 | * MyungJoo Ham <myungjoo.ham@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __LINUX_DEVFREQ_H__ | ||
14 | #define __LINUX_DEVFREQ_H__ | ||
15 | |||
16 | #include <linux/device.h> | ||
17 | #include <linux/notifier.h> | ||
18 | #include <linux/opp.h> | ||
19 | |||
20 | #define DEVFREQ_NAME_LEN 16 | ||
21 | |||
22 | struct devfreq; | ||
23 | |||
24 | /** | ||
25 | * struct devfreq_dev_status - Data given from devfreq user device to | ||
26 | * governors. Represents the performance | ||
27 | * statistics. | ||
28 | * @total_time The total time represented by this instance of | ||
29 | * devfreq_dev_status | ||
30 | * @busy_time The time that the device was working among the | ||
31 | * total_time. | ||
32 | * @current_frequency The operating frequency. | ||
33 | * @private_data An entry not specified by the devfreq framework. | ||
34 | * A device and a specific governor may have their | ||
35 | * own protocol with private_data. However, because | ||
36 | * this is governor-specific, a governor using this | ||
37 | * will be only compatible with devices aware of it. | ||
38 | */ | ||
39 | struct devfreq_dev_status { | ||
40 | /* both since the last measure */ | ||
41 | unsigned long total_time; | ||
42 | unsigned long busy_time; | ||
43 | unsigned long current_frequency; | ||
44 | void *private_date; | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * struct devfreq_dev_profile - Devfreq's user device profile | ||
49 | * @initial_freq The operating frequency when devfreq_add_device() is | ||
50 | * called. | ||
51 | * @polling_ms The polling interval in ms. 0 disables polling. | ||
52 | * @target The device should set its operating frequency at | ||
53 | * freq or lowest-upper-than-freq value. If freq is | ||
54 | * higher than any operable frequency, set maximum. | ||
55 | * Before returning, target function should set | ||
56 | * freq at the current frequency. | ||
57 | * @get_dev_status The device should provide the current performance | ||
58 | * status to devfreq, which is used by governors. | ||
59 | * @exit An optional callback that is called when devfreq | ||
60 | * is removing the devfreq object due to error or | ||
61 | * from devfreq_remove_device() call. If the user | ||
62 | * has registered devfreq->nb at a notifier-head, | ||
63 | * this is the time to unregister it. | ||
64 | */ | ||
65 | struct devfreq_dev_profile { | ||
66 | unsigned long initial_freq; | ||
67 | unsigned int polling_ms; | ||
68 | |||
69 | int (*target)(struct device *dev, unsigned long *freq); | ||
70 | int (*get_dev_status)(struct device *dev, | ||
71 | struct devfreq_dev_status *stat); | ||
72 | void (*exit)(struct device *dev); | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * struct devfreq_governor - Devfreq policy governor | ||
77 | * @name Governor's name | ||
78 | * @get_target_freq Returns desired operating frequency for the device. | ||
79 | * Basically, get_target_freq will run | ||
80 | * devfreq_dev_profile.get_dev_status() to get the | ||
81 | * status of the device (load = busy_time / total_time). | ||
82 | * If no_central_polling is set, this callback is called | ||
83 | * only with update_devfreq() notified by OPP. | ||
84 | * @init Called when the devfreq is being attached to a device | ||
85 | * @exit Called when the devfreq is being removed from a | ||
86 | * device. Governor should stop any internal routines | ||
87 | * before return because related data may be | ||
88 | * freed after exit(). | ||
89 | * @no_central_polling Do not use devfreq's central polling mechanism. | ||
90 | * When this is set, devfreq will not call | ||
91 | * get_target_freq with devfreq_monitor(). However, | ||
92 | * devfreq will call get_target_freq with | ||
93 | * devfreq_update() notified by OPP framework. | ||
94 | * | ||
95 | * Note that the callbacks are called with devfreq->lock locked by devfreq. | ||
96 | */ | ||
97 | struct devfreq_governor { | ||
98 | const char name[DEVFREQ_NAME_LEN]; | ||
99 | int (*get_target_freq)(struct devfreq *this, unsigned long *freq); | ||
100 | int (*init)(struct devfreq *this); | ||
101 | void (*exit)(struct devfreq *this); | ||
102 | const bool no_central_polling; | ||
103 | }; | ||
104 | |||
105 | /** | ||
106 | * struct devfreq - Device devfreq structure | ||
107 | * @node list node - contains the devices with devfreq that have been | ||
108 | * registered. | ||
109 | * @lock a mutex to protect accessing devfreq. | ||
110 | * @dev device registered by devfreq class. dev.parent is the device | ||
111 | * using devfreq. | ||
112 | * @profile device-specific devfreq profile | ||
113 | * @governor method how to choose frequency based on the usage. | ||
114 | * @nb notifier block used to notify devfreq object that it should | ||
115 | * reevaluate operable frequencies. Devfreq users may use | ||
116 | * devfreq.nb to the corresponding register notifier call chain. | ||
117 | * @polling_jiffies interval in jiffies. | ||
118 | * @previous_freq previously configured frequency value. | ||
119 | * @next_polling the number of remaining jiffies to poll with | ||
120 | * "devfreq_monitor" executions to reevaluate | ||
121 | * frequency/voltage of the device. Set by | ||
122 | * profile's polling_ms interval. | ||
123 | * @data Private data of the governor. The devfreq framework does not | ||
124 | * touch this. | ||
125 | * @being_removed a flag to mark that this object is being removed in | ||
126 | * order to prevent trying to remove the object multiple times. | ||
127 | * | ||
128 | * This structure stores the devfreq information for a give device. | ||
129 | * | ||
130 | * Note that when a governor accesses entries in struct devfreq in its | ||
131 | * functions except for the context of callbacks defined in struct | ||
132 | * devfreq_governor, the governor should protect its access with the | ||
133 | * struct mutex lock in struct devfreq. A governor may use this mutex | ||
134 | * to protect its own private data in void *data as well. | ||
135 | */ | ||
136 | struct devfreq { | ||
137 | struct list_head node; | ||
138 | |||
139 | struct mutex lock; | ||
140 | struct device dev; | ||
141 | struct devfreq_dev_profile *profile; | ||
142 | const struct devfreq_governor *governor; | ||
143 | struct notifier_block nb; | ||
144 | |||
145 | unsigned long polling_jiffies; | ||
146 | unsigned long previous_freq; | ||
147 | unsigned int next_polling; | ||
148 | |||
149 | void *data; /* private data for governors */ | ||
150 | |||
151 | bool being_removed; | ||
152 | }; | ||
153 | |||
154 | #if defined(CONFIG_PM_DEVFREQ) | ||
155 | extern struct devfreq *devfreq_add_device(struct device *dev, | ||
156 | struct devfreq_dev_profile *profile, | ||
157 | const struct devfreq_governor *governor, | ||
158 | void *data); | ||
159 | extern int devfreq_remove_device(struct devfreq *devfreq); | ||
160 | |||
161 | /* Helper functions for devfreq user device driver with OPP. */ | ||
162 | extern struct opp *devfreq_recommended_opp(struct device *dev, | ||
163 | unsigned long *freq); | ||
164 | extern int devfreq_register_opp_notifier(struct device *dev, | ||
165 | struct devfreq *devfreq); | ||
166 | extern int devfreq_unregister_opp_notifier(struct device *dev, | ||
167 | struct devfreq *devfreq); | ||
168 | |||
169 | #else /* !CONFIG_PM_DEVFREQ */ | ||
170 | static struct devfreq *devfreq_add_device(struct device *dev, | ||
171 | struct devfreq_dev_profile *profile, | ||
172 | struct devfreq_governor *governor, | ||
173 | void *data); | ||
174 | { | ||
175 | return NULL; | ||
176 | } | ||
177 | |||
178 | static int devfreq_remove_device(struct devfreq *devfreq); | ||
179 | { | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static struct opp *devfreq_recommended_opp(struct device *dev, | ||
184 | unsigned long *freq) | ||
185 | { | ||
186 | return -EINVAL; | ||
187 | } | ||
188 | |||
189 | static int devfreq_register_opp_notifier(struct device *dev, | ||
190 | struct devfreq *devfreq) | ||
191 | { | ||
192 | return -EINVAL; | ||
193 | } | ||
194 | |||
195 | static int devfreq_unregister_opp_notifier(struct device *dev, | ||
196 | struct devfreq *devfreq) | ||
197 | { | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | |||
201 | #endif /* CONFIG_PM_DEVFREQ */ | ||
202 | |||
203 | #endif /* __LINUX_DEVFREQ_H__ */ | ||