aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-class-devfreq52
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/base/power/opp.c30
-rw-r--r--drivers/devfreq/Kconfig75
-rw-r--r--drivers/devfreq/Makefile5
-rw-r--r--drivers/devfreq/devfreq.c601
-rw-r--r--drivers/devfreq/governor.h24
-rw-r--r--drivers/devfreq/governor_performance.c29
-rw-r--r--drivers/devfreq/governor_powersave.c29
-rw-r--r--drivers/devfreq/governor_simpleondemand.c88
-rw-r--r--drivers/devfreq/governor_userspace.c116
-rw-r--r--include/linux/devfreq.h238
-rw-r--r--include/linux/opp.h12
14 files changed, 1303 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq
new file mode 100644
index 000000000000..23d78b5aab11
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-devfreq
@@ -0,0 +1,52 @@
1What: /sys/class/devfreq/.../
2Date: September 2011
3Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
4Description:
5 Provide a place in sysfs for the devfreq objects.
6 This allows accessing various devfreq specific variables.
7 The name of devfreq object denoted as ... is same as the
8 name of device using devfreq.
9
10What: /sys/class/devfreq/.../governor
11Date: September 2011
12Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
13Description:
14 The /sys/class/devfreq/.../governor shows the name of the
15 governor used by the corresponding devfreq object.
16
17What: /sys/class/devfreq/.../cur_freq
18Date: September 2011
19Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
20Description:
21 The /sys/class/devfreq/.../cur_freq shows the current
22 frequency of the corresponding devfreq object.
23
24What: /sys/class/devfreq/.../central_polling
25Date: September 2011
26Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
27Description:
28 The /sys/class/devfreq/.../central_polling shows whether
29 the devfreq ojbect is using devfreq-provided central
30 polling mechanism or not.
31
32What: /sys/class/devfreq/.../polling_interval
33Date: September 2011
34Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
35Description:
36 The /sys/class/devfreq/.../polling_interval shows and sets
37 the requested polling interval of the corresponding devfreq
38 object. The values are represented in ms. If the value is
39 less than 1 jiffy, it is considered to be 0, which means
40 no polling. This value is meaningless if the governor is
41 not polling; thus. If the governor is not using
42 devfreq-provided central polling
43 (/sys/class/devfreq/.../central_polling is 0), this value
44 may be useless.
45
46What: /sys/class/devfreq/.../userspace/set_freq
47Date: September 2011
48Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
49Description:
50 The /sys/class/devfreq/.../userspace/set_freq shows and
51 sets the requested frequency for the devfreq object if
52 userspace governor is in effect.
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
131source "drivers/virt/Kconfig" 131source "drivers/virt/Kconfig"
132 132
133source "drivers/devfreq/Kconfig"
134
133endmenu 135endmenu
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
129obj-$(CONFIG_VIRT_DRIVERS) += virt/ 129obj-$(CONFIG_VIRT_DRIVERS) += virt/
130
131obj-$(CONFIG_PM_DEVFREQ) += devfreq/
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index b23de185cb04..434a6c011675 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -73,6 +73,7 @@ struct opp {
73 * RCU usage: nodes are not modified in the list of device_opp, 73 * RCU usage: nodes are not modified in the list of device_opp,
74 * however addition is possible and is secured by dev_opp_list_lock 74 * however addition is possible and is secured by dev_opp_list_lock
75 * @dev: device pointer 75 * @dev: device pointer
76 * @head: notifier head to notify the OPP availability changes.
76 * @opp_list: list of opps 77 * @opp_list: list of opps
77 * 78 *
78 * This is an internal data structure maintaining the link to opps attached to 79 * This is an internal data structure maintaining the link to opps attached to
@@ -83,6 +84,7 @@ struct device_opp {
83 struct list_head node; 84 struct list_head node;
84 85
85 struct device *dev; 86 struct device *dev;
87 struct srcu_notifier_head head;
86 struct list_head opp_list; 88 struct list_head opp_list;
87}; 89};
88 90
@@ -404,6 +406,7 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
404 } 406 }
405 407
406 dev_opp->dev = dev; 408 dev_opp->dev = dev;
409 srcu_init_notifier_head(&dev_opp->head);
407 INIT_LIST_HEAD(&dev_opp->opp_list); 410 INIT_LIST_HEAD(&dev_opp->opp_list);
408 411
409 /* Secure the device list modification */ 412 /* Secure the device list modification */
@@ -428,6 +431,11 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
428 list_add_rcu(&new_opp->node, head); 431 list_add_rcu(&new_opp->node, head);
429 mutex_unlock(&dev_opp_list_lock); 432 mutex_unlock(&dev_opp_list_lock);
430 433
434 /*
435 * Notify the changes in the availability of the operable
436 * frequency/voltage list.
437 */
438 srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp);
431 return 0; 439 return 0;
432} 440}
433 441
@@ -504,6 +512,14 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
504 mutex_unlock(&dev_opp_list_lock); 512 mutex_unlock(&dev_opp_list_lock);
505 synchronize_rcu(); 513 synchronize_rcu();
506 514
515 /* Notify the change of the OPP availability */
516 if (availability_req)
517 srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ENABLE,
518 new_opp);
519 else
520 srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_DISABLE,
521 new_opp);
522
507 /* clean up old opp */ 523 /* clean up old opp */
508 new_opp = opp; 524 new_opp = opp;
509 goto out; 525 goto out;
@@ -643,3 +659,17 @@ void opp_free_cpufreq_table(struct device *dev,
643 *table = NULL; 659 *table = NULL;
644} 660}
645#endif /* CONFIG_CPU_FREQ */ 661#endif /* CONFIG_CPU_FREQ */
662
663/**
664 * opp_get_notifier() - find notifier_head of the device with opp
665 * @dev: device pointer used to lookup device OPPs.
666 */
667struct srcu_notifier_head *opp_get_notifier(struct device *dev)
668{
669 struct device_opp *dev_opp = find_device_opp(dev);
670
671 if (IS_ERR(dev_opp))
672 return ERR_PTR(PTR_ERR(dev_opp)); /* matching type */
673
674 return &dev_opp->head;
675}
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
new file mode 100644
index 000000000000..643b055ed3cd
--- /dev/null
+++ b/drivers/devfreq/Kconfig
@@ -0,0 +1,75 @@
1config 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
10menuconfig 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
35if PM_DEVFREQ
36
37comment "DEVFREQ Governors"
38
39config DEVFREQ_GOV_SIMPLE_ONDEMAND
40 bool "Simple Ondemand"
41 help
42 Chooses frequency based on the recent load on the device. Works
43 similar as ONDEMAND governor of CPUFREQ does. A device with
44 Simple-Ondemand should be able to provide busy/total counter
45 values that imply the usage rate. A device may provide tuned
46 values to the governor with data field at devfreq_add_device().
47
48config DEVFREQ_GOV_PERFORMANCE
49 bool "Performance"
50 help
51 Sets the frequency at the maximum available frequency.
52 This governor always returns UINT_MAX as frequency so that
53 the DEVFREQ framework returns the highest frequency available
54 at any time.
55
56config DEVFREQ_GOV_POWERSAVE
57 bool "Powersave"
58 help
59 Sets the frequency at the minimum available frequency.
60 This governor always returns 0 as frequency so that
61 the DEVFREQ framework returns the lowest frequency available
62 at any time.
63
64config DEVFREQ_GOV_USERSPACE
65 bool "Userspace"
66 help
67 Sets the frequency at the user specified one.
68 This governor returns the user configured frequency if there
69 has been an input to /sys/devices/.../power/devfreq_set_freq.
70 Otherwise, the governor does not change the frequnecy
71 given at the initialization.
72
73comment "DEVFREQ Drivers"
74
75endif # PM_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
new file mode 100644
index 000000000000..4564a89e970a
--- /dev/null
+++ b/drivers/devfreq/Makefile
@@ -0,0 +1,5 @@
1obj-$(CONFIG_PM_DEVFREQ) += devfreq.o
2obj-$(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) += governor_simpleondemand.o
3obj-$(CONFIG_DEVFREQ_GOV_PERFORMANCE) += governor_performance.o
4obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o
5obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
new file mode 100644
index 000000000000..5d15b812377b
--- /dev/null
+++ b/drivers/devfreq/devfreq.c
@@ -0,0 +1,601 @@
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
28struct 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 */
36static bool polling;
37static struct workqueue_struct *devfreq_wq;
38static struct delayed_work devfreq_work;
39
40/* wait removing if this is to be removed */
41static struct devfreq *wait_remove_device;
42
43/* The list of all device-devfreq */
44static LIST_HEAD(devfreq_list);
45static 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 */
54static 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 */
80int 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 */
112static 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 */
145static 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 */
190static 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
228out:
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 */
238static 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 */
327struct 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;
401err_init:
402 device_unregister(&devfreq->dev);
403err_dev:
404 mutex_unlock(&devfreq->lock);
405 kfree(devfreq);
406out:
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 */
417int 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
440static ssize_t show_governor(struct device *dev,
441 struct device_attribute *attr, char *buf)
442{
443 return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
444}
445
446static ssize_t show_freq(struct device *dev,
447 struct device_attribute *attr, char *buf)
448{
449 return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq);
450}
451
452static ssize_t show_polling_interval(struct device *dev,
453 struct device_attribute *attr, char *buf)
454{
455 return sprintf(buf, "%d\n", to_devfreq(dev)->profile->polling_ms);
456}
457
458static ssize_t store_polling_interval(struct device *dev,
459 struct device_attribute *attr,
460 const char *buf, size_t count)
461{
462 struct devfreq *df = to_devfreq(dev);
463 unsigned int value;
464 int ret;
465
466 ret = sscanf(buf, "%u", &value);
467 if (ret != 1)
468 goto out;
469
470 mutex_lock(&df->lock);
471 df->profile->polling_ms = value;
472 df->next_polling = df->polling_jiffies
473 = msecs_to_jiffies(value);
474 mutex_unlock(&df->lock);
475
476 ret = count;
477
478 if (df->governor->no_central_polling)
479 goto out;
480
481 mutex_lock(&devfreq_list_lock);
482 if (df->next_polling > 0 && !polling) {
483 polling = true;
484 queue_delayed_work(devfreq_wq, &devfreq_work,
485 df->next_polling);
486 }
487 mutex_unlock(&devfreq_list_lock);
488out:
489 return ret;
490}
491
492static ssize_t show_central_polling(struct device *dev,
493 struct device_attribute *attr, char *buf)
494{
495 return sprintf(buf, "%d\n",
496 !to_devfreq(dev)->governor->no_central_polling);
497}
498
499static struct device_attribute devfreq_attrs[] = {
500 __ATTR(governor, S_IRUGO, show_governor, NULL),
501 __ATTR(cur_freq, S_IRUGO, show_freq, NULL),
502 __ATTR(central_polling, S_IRUGO, show_central_polling, NULL),
503 __ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
504 store_polling_interval),
505 { },
506};
507
508/**
509 * devfreq_start_polling() - Initialize data structure for devfreq framework and
510 * start polling registered devfreq devices.
511 */
512static int __init devfreq_start_polling(void)
513{
514 mutex_lock(&devfreq_list_lock);
515 polling = false;
516 devfreq_wq = create_freezable_workqueue("devfreq_wq");
517 INIT_DELAYED_WORK_DEFERRABLE(&devfreq_work, devfreq_monitor);
518 mutex_unlock(&devfreq_list_lock);
519
520 devfreq_monitor(&devfreq_work.work);
521 return 0;
522}
523late_initcall(devfreq_start_polling);
524
525static int __init devfreq_init(void)
526{
527 devfreq_class = class_create(THIS_MODULE, "devfreq");
528 if (IS_ERR(devfreq_class)) {
529 pr_err("%s: couldn't create class\n", __FILE__);
530 return PTR_ERR(devfreq_class);
531 }
532 devfreq_class->dev_attrs = devfreq_attrs;
533 return 0;
534}
535subsys_initcall(devfreq_init);
536
537static void __exit devfreq_exit(void)
538{
539 class_destroy(devfreq_class);
540}
541module_exit(devfreq_exit);
542
543/*
544 * The followings are helper functions for devfreq user device drivers with
545 * OPP framework.
546 */
547
548/**
549 * devfreq_recommended_opp() - Helper function to get proper OPP for the
550 * freq value given to target callback.
551 * @dev The devfreq user device. (parent of devfreq)
552 * @freq The frequency given to target function
553 *
554 */
555struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq)
556{
557 struct opp *opp = opp_find_freq_ceil(dev, freq);
558
559 if (opp == ERR_PTR(-ENODEV))
560 opp = opp_find_freq_floor(dev, freq);
561 return opp;
562}
563
564/**
565 * devfreq_register_opp_notifier() - Helper function to get devfreq notified
566 * for any changes in the OPP availability
567 * changes
568 * @dev The devfreq user device. (parent of devfreq)
569 * @devfreq The devfreq object.
570 */
571int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
572{
573 struct srcu_notifier_head *nh = opp_get_notifier(dev);
574
575 if (IS_ERR(nh))
576 return PTR_ERR(nh);
577 return srcu_notifier_chain_register(nh, &devfreq->nb);
578}
579
580/**
581 * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq
582 * notified for any changes in the OPP
583 * availability changes anymore.
584 * @dev The devfreq user device. (parent of devfreq)
585 * @devfreq The devfreq object.
586 *
587 * At exit() callback of devfreq_dev_profile, this must be included if
588 * devfreq_recommended_opp is used.
589 */
590int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
591{
592 struct srcu_notifier_head *nh = opp_get_notifier(dev);
593
594 if (IS_ERR(nh))
595 return PTR_ERR(nh);
596 return srcu_notifier_chain_unregister(nh, &devfreq->nb);
597}
598
599MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
600MODULE_DESCRIPTION("devfreq class support");
601MODULE_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 */
22extern int update_devfreq(struct devfreq *devfreq);
23
24#endif /* _GOVERNOR_H */
diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
new file mode 100644
index 000000000000..c0596b291761
--- /dev/null
+++ b/drivers/devfreq/governor_performance.c
@@ -0,0 +1,29 @@
1/*
2 * linux/drivers/devfreq/governor_performance.c
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
12#include <linux/devfreq.h>
13
14static int devfreq_performance_func(struct devfreq *df,
15 unsigned long *freq)
16{
17 /*
18 * target callback should be able to get floor value as
19 * said in devfreq.h
20 */
21 *freq = UINT_MAX;
22 return 0;
23}
24
25const struct devfreq_governor devfreq_performance = {
26 .name = "performance",
27 .get_target_freq = devfreq_performance_func,
28 .no_central_polling = true,
29};
diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c
new file mode 100644
index 000000000000..2483a85a266f
--- /dev/null
+++ b/drivers/devfreq/governor_powersave.c
@@ -0,0 +1,29 @@
1/*
2 * linux/drivers/devfreq/governor_powersave.c
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
12#include <linux/devfreq.h>
13
14static int devfreq_powersave_func(struct devfreq *df,
15 unsigned long *freq)
16{
17 /*
18 * target callback should be able to get ceiling value as
19 * said in devfreq.h
20 */
21 *freq = 0;
22 return 0;
23}
24
25const struct devfreq_governor devfreq_powersave = {
26 .name = "powersave",
27 .get_target_freq = devfreq_powersave_func,
28 .no_central_polling = true,
29};
diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
new file mode 100644
index 000000000000..efad8dcf9028
--- /dev/null
+++ b/drivers/devfreq/governor_simpleondemand.c
@@ -0,0 +1,88 @@
1/*
2 * linux/drivers/devfreq/governor_simpleondemand.c
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
12#include <linux/errno.h>
13#include <linux/devfreq.h>
14#include <linux/math64.h>
15
16/* Default constants for DevFreq-Simple-Ondemand (DFSO) */
17#define DFSO_UPTHRESHOLD (90)
18#define DFSO_DOWNDIFFERENCTIAL (5)
19static int devfreq_simple_ondemand_func(struct devfreq *df,
20 unsigned long *freq)
21{
22 struct devfreq_dev_status stat;
23 int err = df->profile->get_dev_status(df->dev.parent, &stat);
24 unsigned long long a, b;
25 unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
26 unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
27 struct devfreq_simple_ondemand_data *data = df->data;
28
29 if (err)
30 return err;
31
32 if (data) {
33 if (data->upthreshold)
34 dfso_upthreshold = data->upthreshold;
35 if (data->downdifferential)
36 dfso_downdifferential = data->downdifferential;
37 }
38 if (dfso_upthreshold > 100 ||
39 dfso_upthreshold < dfso_downdifferential)
40 return -EINVAL;
41
42 /* Assume MAX if it is going to be divided by zero */
43 if (stat.total_time == 0) {
44 *freq = UINT_MAX;
45 return 0;
46 }
47
48 /* Prevent overflow */
49 if (stat.busy_time >= (1 << 24) || stat.total_time >= (1 << 24)) {
50 stat.busy_time >>= 7;
51 stat.total_time >>= 7;
52 }
53
54 /* Set MAX if it's busy enough */
55 if (stat.busy_time * 100 >
56 stat.total_time * dfso_upthreshold) {
57 *freq = UINT_MAX;
58 return 0;
59 }
60
61 /* Set MAX if we do not know the initial frequency */
62 if (stat.current_frequency == 0) {
63 *freq = UINT_MAX;
64 return 0;
65 }
66
67 /* Keep the current frequency */
68 if (stat.busy_time * 100 >
69 stat.total_time * (dfso_upthreshold - dfso_downdifferential)) {
70 *freq = stat.current_frequency;
71 return 0;
72 }
73
74 /* Set the desired frequency based on the load */
75 a = stat.busy_time;
76 a *= stat.current_frequency;
77 b = div_u64(a, stat.total_time);
78 b *= 100;
79 b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
80 *freq = (unsigned long) b;
81
82 return 0;
83}
84
85const struct devfreq_governor devfreq_simple_ondemand = {
86 .name = "simple_ondemand",
87 .get_target_freq = devfreq_simple_ondemand_func,
88};
diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c
new file mode 100644
index 000000000000..4f8b563da782
--- /dev/null
+++ b/drivers/devfreq/governor_userspace.c
@@ -0,0 +1,116 @@
1/*
2 * linux/drivers/devfreq/governor_simpleondemand.c
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
12#include <linux/slab.h>
13#include <linux/device.h>
14#include <linux/devfreq.h>
15#include <linux/pm.h>
16#include <linux/mutex.h>
17#include "governor.h"
18
19struct userspace_data {
20 unsigned long user_frequency;
21 bool valid;
22};
23
24static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq)
25{
26 struct userspace_data *data = df->data;
27
28 if (!data->valid)
29 *freq = df->previous_freq; /* No user freq specified yet */
30 else
31 *freq = data->user_frequency;
32 return 0;
33}
34
35static ssize_t store_freq(struct device *dev, struct device_attribute *attr,
36 const char *buf, size_t count)
37{
38 struct devfreq *devfreq = to_devfreq(dev);
39 struct userspace_data *data;
40 unsigned long wanted;
41 int err = 0;
42
43
44 mutex_lock(&devfreq->lock);
45 data = devfreq->data;
46
47 sscanf(buf, "%lu", &wanted);
48 data->user_frequency = wanted;
49 data->valid = true;
50 err = update_devfreq(devfreq);
51 if (err == 0)
52 err = count;
53 mutex_unlock(&devfreq->lock);
54 return err;
55}
56
57static ssize_t show_freq(struct device *dev, struct device_attribute *attr,
58 char *buf)
59{
60 struct devfreq *devfreq = to_devfreq(dev);
61 struct userspace_data *data;
62 int err = 0;
63
64 mutex_lock(&devfreq->lock);
65 data = devfreq->data;
66
67 if (data->valid)
68 err = sprintf(buf, "%lu\n", data->user_frequency);
69 else
70 err = sprintf(buf, "undefined\n");
71 mutex_unlock(&devfreq->lock);
72 return err;
73}
74
75static DEVICE_ATTR(set_freq, 0644, show_freq, store_freq);
76static struct attribute *dev_entries[] = {
77 &dev_attr_set_freq.attr,
78 NULL,
79};
80static struct attribute_group dev_attr_group = {
81 .name = "userspace",
82 .attrs = dev_entries,
83};
84
85static int userspace_init(struct devfreq *devfreq)
86{
87 int err = 0;
88 struct userspace_data *data = kzalloc(sizeof(struct userspace_data),
89 GFP_KERNEL);
90
91 if (!data) {
92 err = -ENOMEM;
93 goto out;
94 }
95 data->valid = false;
96 devfreq->data = data;
97
98 err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group);
99out:
100 return err;
101}
102
103static void userspace_exit(struct devfreq *devfreq)
104{
105 sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group);
106 kfree(devfreq->data);
107 devfreq->data = NULL;
108}
109
110const struct devfreq_governor devfreq_userspace = {
111 .name = "userspace",
112 .get_target_freq = devfreq_userspace_func,
113 .init = userspace_init,
114 .exit = userspace_exit,
115 .no_central_polling = true,
116};
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
new file mode 100644
index 000000000000..afb94583960c
--- /dev/null
+++ b/include/linux/devfreq.h
@@ -0,0 +1,238 @@
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
22struct 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 */
39struct 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 */
65struct 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 */
97struct 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 */
136struct 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)
155extern struct devfreq *devfreq_add_device(struct device *dev,
156 struct devfreq_dev_profile *profile,
157 const struct devfreq_governor *governor,
158 void *data);
159extern int devfreq_remove_device(struct devfreq *devfreq);
160
161/* Helper functions for devfreq user device driver with OPP. */
162extern struct opp *devfreq_recommended_opp(struct device *dev,
163 unsigned long *freq);
164extern int devfreq_register_opp_notifier(struct device *dev,
165 struct devfreq *devfreq);
166extern int devfreq_unregister_opp_notifier(struct device *dev,
167 struct devfreq *devfreq);
168
169#ifdef CONFIG_DEVFREQ_GOV_POWERSAVE
170extern const struct devfreq_governor devfreq_powersave;
171#endif
172#ifdef CONFIG_DEVFREQ_GOV_PERFORMANCE
173extern const struct devfreq_governor devfreq_performance;
174#endif
175#ifdef CONFIG_DEVFREQ_GOV_USERSPACE
176extern const struct devfreq_governor devfreq_userspace;
177#endif
178#ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND
179extern const struct devfreq_governor devfreq_simple_ondemand;
180/**
181 * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
182 * and devfreq_add_device
183 * @ upthreshold If the load is over this value, the frequency jumps.
184 * Specify 0 to use the default. Valid value = 0 to 100.
185 * @ downdifferential If the load is under upthreshold - downdifferential,
186 * the governor may consider slowing the frequency down.
187 * Specify 0 to use the default. Valid value = 0 to 100.
188 * downdifferential < upthreshold must hold.
189 *
190 * If the fed devfreq_simple_ondemand_data pointer is NULL to the governor,
191 * the governor uses the default values.
192 */
193struct devfreq_simple_ondemand_data {
194 unsigned int upthreshold;
195 unsigned int downdifferential;
196};
197#endif
198
199#else /* !CONFIG_PM_DEVFREQ */
200static struct devfreq *devfreq_add_device(struct device *dev,
201 struct devfreq_dev_profile *profile,
202 struct devfreq_governor *governor,
203 void *data);
204{
205 return NULL;
206}
207
208static int devfreq_remove_device(struct devfreq *devfreq);
209{
210 return 0;
211}
212
213static struct opp *devfreq_recommended_opp(struct device *dev,
214 unsigned long *freq)
215{
216 return -EINVAL;
217}
218
219static int devfreq_register_opp_notifier(struct device *dev,
220 struct devfreq *devfreq)
221{
222 return -EINVAL;
223}
224
225static int devfreq_unregister_opp_notifier(struct device *dev,
226 struct devfreq *devfreq)
227{
228 return -EINVAL;
229}
230
231#define devfreq_powersave NULL
232#define devfreq_performance NULL
233#define devfreq_userspace NULL
234#define devfreq_simple_ondemand NULL
235
236#endif /* CONFIG_PM_DEVFREQ */
237
238#endif /* __LINUX_DEVFREQ_H__ */
diff --git a/include/linux/opp.h b/include/linux/opp.h
index 7020e9736fc5..87a9208f8aec 100644
--- a/include/linux/opp.h
+++ b/include/linux/opp.h
@@ -16,9 +16,14 @@
16 16
17#include <linux/err.h> 17#include <linux/err.h>
18#include <linux/cpufreq.h> 18#include <linux/cpufreq.h>
19#include <linux/notifier.h>
19 20
20struct opp; 21struct opp;
21 22
23enum opp_event {
24 OPP_EVENT_ADD, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE,
25};
26
22#if defined(CONFIG_PM_OPP) 27#if defined(CONFIG_PM_OPP)
23 28
24unsigned long opp_get_voltage(struct opp *opp); 29unsigned long opp_get_voltage(struct opp *opp);
@@ -40,6 +45,8 @@ int opp_enable(struct device *dev, unsigned long freq);
40 45
41int opp_disable(struct device *dev, unsigned long freq); 46int opp_disable(struct device *dev, unsigned long freq);
42 47
48struct srcu_notifier_head *opp_get_notifier(struct device *dev);
49
43#else 50#else
44static inline unsigned long opp_get_voltage(struct opp *opp) 51static inline unsigned long opp_get_voltage(struct opp *opp)
45{ 52{
@@ -89,6 +96,11 @@ static inline int opp_disable(struct device *dev, unsigned long freq)
89{ 96{
90 return 0; 97 return 0;
91} 98}
99
100struct srcu_notifier_head *opp_get_notifier(struct device *dev)
101{
102 return ERR_PTR(-EINVAL);
103}
92#endif /* CONFIG_PM */ 104#endif /* CONFIG_PM */
93 105
94#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP) 106#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)