Merge branch 'pm-devfreq'
* pm-devfreq: (23 commits) PM / devfreq: remove compiler error with module governors (2) PM / devfreq: Fix return value in devfreq_remove_governor() PM / devfreq: Fix incorrect argument in error message PM / devfreq: missing rcu_read_lock() added for find_device_opp() PM / devfreq: remove compiler error when a governor is module PM / devfreq: exynos4_bus.c: Fixed an alignment of the func call args. PM / devfreq: Add sysfs node to expose available governors PM / devfreq: allow sysfs governor node to switch governor PM / devfreq: governors: add GPL module license and allow module build PM / devfreq: map devfreq drivers to governor using name PM / devfreq: register governors with devfreq framework PM / devfreq: provide hooks for governors to be registered PM / devfreq: export update_devfreq PM / devfreq: Add sysfs node for representing frequency transition information. PM / devfreq: Add sysfs node to expose available frequencies PM / devfreq: documentation cleanups for devfreq header PM / devfreq: Use devm_* functions in exynos4_bus.c PM / devfreq: make devfreq_class static PM / devfreq: fix sscanf handling for writable sysfs entries PM / devfreq: kernel-doc typo corrections ...
This commit is contained in:
commit
bf58cdffac
|
@ -11,7 +11,7 @@ What: /sys/class/devfreq/.../governor
|
|||
Date: September 2011
|
||||
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||
Description:
|
||||
The /sys/class/devfreq/.../governor shows the name of the
|
||||
The /sys/class/devfreq/.../governor show or set the name of the
|
||||
governor used by the corresponding devfreq object.
|
||||
|
||||
What: /sys/class/devfreq/.../cur_freq
|
||||
|
@ -19,15 +19,16 @@ Date: September 2011
|
|||
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||
Description:
|
||||
The /sys/class/devfreq/.../cur_freq shows the current
|
||||
frequency of the corresponding devfreq object.
|
||||
frequency of the corresponding devfreq object. Same as
|
||||
target_freq when get_cur_freq() is not implemented by
|
||||
devfreq driver.
|
||||
|
||||
What: /sys/class/devfreq/.../central_polling
|
||||
Date: September 2011
|
||||
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||
What: /sys/class/devfreq/.../target_freq
|
||||
Date: September 2012
|
||||
Contact: Rajagopal Venkat <rajagopal.venkat@linaro.org>
|
||||
Description:
|
||||
The /sys/class/devfreq/.../central_polling shows whether
|
||||
the devfreq ojbect is using devfreq-provided central
|
||||
polling mechanism or not.
|
||||
The /sys/class/devfreq/.../target_freq shows the next governor
|
||||
predicted target frequency of the corresponding devfreq object.
|
||||
|
||||
What: /sys/class/devfreq/.../polling_interval
|
||||
Date: September 2011
|
||||
|
@ -43,6 +44,17 @@ Description:
|
|||
(/sys/class/devfreq/.../central_polling is 0), this value
|
||||
may be useless.
|
||||
|
||||
What: /sys/class/devfreq/.../trans_stat
|
||||
Date: October 2012
|
||||
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||
Descrtiption:
|
||||
This ABI shows the statistics of devfreq behavior on a
|
||||
specific device. It shows the time spent in each state and
|
||||
the number of transitions between states.
|
||||
In order to activate this ABI, the devfreq target device
|
||||
driver should provide the list of available frequencies
|
||||
with its profile.
|
||||
|
||||
What: /sys/class/devfreq/.../userspace/set_freq
|
||||
Date: September 2011
|
||||
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||
|
@ -50,3 +62,19 @@ Description:
|
|||
The /sys/class/devfreq/.../userspace/set_freq shows and
|
||||
sets the requested frequency for the devfreq object if
|
||||
userspace governor is in effect.
|
||||
|
||||
What: /sys/class/devfreq/.../available_frequencies
|
||||
Date: October 2012
|
||||
Contact: Nishanth Menon <nm@ti.com>
|
||||
Description:
|
||||
The /sys/class/devfreq/.../available_frequencies shows
|
||||
the available frequencies of the corresponding devfreq object.
|
||||
This is a snapshot of available frequencies and not limited
|
||||
by the min/max frequency restrictions.
|
||||
|
||||
What: /sys/class/devfreq/.../available_governors
|
||||
Date: October 2012
|
||||
Contact: Nishanth Menon <nm@ti.com>
|
||||
Description:
|
||||
The /sys/class/devfreq/.../available_governors shows
|
||||
currently available governors in the system.
|
||||
|
|
|
@ -30,7 +30,7 @@ if PM_DEVFREQ
|
|||
comment "DEVFREQ Governors"
|
||||
|
||||
config DEVFREQ_GOV_SIMPLE_ONDEMAND
|
||||
bool "Simple Ondemand"
|
||||
tristate "Simple Ondemand"
|
||||
help
|
||||
Chooses frequency based on the recent load on the device. Works
|
||||
similar as ONDEMAND governor of CPUFREQ does. A device with
|
||||
|
@ -39,7 +39,7 @@ config DEVFREQ_GOV_SIMPLE_ONDEMAND
|
|||
values to the governor with data field at devfreq_add_device().
|
||||
|
||||
config DEVFREQ_GOV_PERFORMANCE
|
||||
bool "Performance"
|
||||
tristate "Performance"
|
||||
help
|
||||
Sets the frequency at the maximum available frequency.
|
||||
This governor always returns UINT_MAX as frequency so that
|
||||
|
@ -47,7 +47,7 @@ config DEVFREQ_GOV_PERFORMANCE
|
|||
at any time.
|
||||
|
||||
config DEVFREQ_GOV_POWERSAVE
|
||||
bool "Powersave"
|
||||
tristate "Powersave"
|
||||
help
|
||||
Sets the frequency at the minimum available frequency.
|
||||
This governor always returns 0 as frequency so that
|
||||
|
@ -55,7 +55,7 @@ config DEVFREQ_GOV_POWERSAVE
|
|||
at any time.
|
||||
|
||||
config DEVFREQ_GOV_USERSPACE
|
||||
bool "Userspace"
|
||||
tristate "Userspace"
|
||||
help
|
||||
Sets the frequency at the user specified one.
|
||||
This governor returns the user configured frequency if there
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -987,7 +987,7 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
|
|||
struct device *dev = &pdev->dev;
|
||||
int err = 0;
|
||||
|
||||
data = kzalloc(sizeof(struct busfreq_data), GFP_KERNEL);
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data), GFP_KERNEL);
|
||||
if (data == NULL) {
|
||||
dev_err(dev, "Cannot allocate memory.\n");
|
||||
return -ENOMEM;
|
||||
|
@ -1012,31 +1012,26 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
|
|||
err = -EINVAL;
|
||||
}
|
||||
if (err)
|
||||
goto err_regulator;
|
||||
return err;
|
||||
|
||||
data->vdd_int = regulator_get(dev, "vdd_int");
|
||||
data->vdd_int = devm_regulator_get(dev, "vdd_int");
|
||||
if (IS_ERR(data->vdd_int)) {
|
||||
dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
|
||||
err = PTR_ERR(data->vdd_int);
|
||||
goto err_regulator;
|
||||
return PTR_ERR(data->vdd_int);
|
||||
}
|
||||
if (data->type == TYPE_BUSF_EXYNOS4x12) {
|
||||
data->vdd_mif = regulator_get(dev, "vdd_mif");
|
||||
data->vdd_mif = devm_regulator_get(dev, "vdd_mif");
|
||||
if (IS_ERR(data->vdd_mif)) {
|
||||
dev_err(dev, "Cannot get the regulator \"vdd_mif\"\n");
|
||||
err = PTR_ERR(data->vdd_mif);
|
||||
regulator_put(data->vdd_int);
|
||||
goto err_regulator;
|
||||
|
||||
return PTR_ERR(data->vdd_mif);
|
||||
}
|
||||
}
|
||||
|
||||
opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq);
|
||||
if (IS_ERR(opp)) {
|
||||
dev_err(dev, "Invalid initial frequency %lu kHz.\n",
|
||||
exynos4_devfreq_profile.initial_freq);
|
||||
err = PTR_ERR(opp);
|
||||
goto err_opp_add;
|
||||
exynos4_devfreq_profile.initial_freq);
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
data->curr_opp = opp;
|
||||
|
||||
|
@ -1045,30 +1040,20 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
|
|||
busfreq_mon_reset(data);
|
||||
|
||||
data->devfreq = devfreq_add_device(dev, &exynos4_devfreq_profile,
|
||||
&devfreq_simple_ondemand, NULL);
|
||||
if (IS_ERR(data->devfreq)) {
|
||||
err = PTR_ERR(data->devfreq);
|
||||
goto err_opp_add;
|
||||
}
|
||||
"simple_ondemand", NULL);
|
||||
if (IS_ERR(data->devfreq))
|
||||
return PTR_ERR(data->devfreq);
|
||||
|
||||
devfreq_register_opp_notifier(dev, data->devfreq);
|
||||
|
||||
err = register_pm_notifier(&data->pm_notifier);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to setup pm notifier\n");
|
||||
goto err_devfreq_add;
|
||||
devfreq_remove_device(data->devfreq);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_devfreq_add:
|
||||
devfreq_remove_device(data->devfreq);
|
||||
err_opp_add:
|
||||
if (data->vdd_mif)
|
||||
regulator_put(data->vdd_mif);
|
||||
regulator_put(data->vdd_int);
|
||||
err_regulator:
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
static __devexit int exynos4_busfreq_remove(struct platform_device *pdev)
|
||||
|
@ -1077,10 +1062,6 @@ static __devexit int exynos4_busfreq_remove(struct platform_device *pdev)
|
|||
|
||||
unregister_pm_notifier(&data->pm_notifier);
|
||||
devfreq_remove_device(data->devfreq);
|
||||
regulator_put(data->vdd_int);
|
||||
if (data->vdd_mif)
|
||||
regulator_put(data->vdd_mif);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,24 @@
|
|||
|
||||
#define to_devfreq(DEV) container_of((DEV), struct devfreq, dev)
|
||||
|
||||
/* Devfreq events */
|
||||
#define DEVFREQ_GOV_START 0x1
|
||||
#define DEVFREQ_GOV_STOP 0x2
|
||||
#define DEVFREQ_GOV_INTERVAL 0x3
|
||||
#define DEVFREQ_GOV_SUSPEND 0x4
|
||||
#define DEVFREQ_GOV_RESUME 0x5
|
||||
|
||||
/* Caution: devfreq->lock must be locked before calling update_devfreq */
|
||||
extern int update_devfreq(struct devfreq *devfreq);
|
||||
|
||||
extern void devfreq_monitor_start(struct devfreq *devfreq);
|
||||
extern void devfreq_monitor_stop(struct devfreq *devfreq);
|
||||
extern void devfreq_monitor_suspend(struct devfreq *devfreq);
|
||||
extern void devfreq_monitor_resume(struct devfreq *devfreq);
|
||||
extern void devfreq_interval_update(struct devfreq *devfreq,
|
||||
unsigned int *delay);
|
||||
|
||||
extern int devfreq_add_governor(struct devfreq_governor *governor);
|
||||
extern int devfreq_remove_governor(struct devfreq_governor *governor);
|
||||
|
||||
#endif /* _GOVERNOR_H */
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/module.h>
|
||||
#include "governor.h"
|
||||
|
||||
static int devfreq_performance_func(struct devfreq *df,
|
||||
|
@ -26,14 +27,41 @@ static int devfreq_performance_func(struct devfreq *df,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int performance_init(struct devfreq *devfreq)
|
||||
static int devfreq_performance_handler(struct devfreq *devfreq,
|
||||
unsigned int event, void *data)
|
||||
{
|
||||
return update_devfreq(devfreq);
|
||||
int ret = 0;
|
||||
|
||||
if (event == DEVFREQ_GOV_START) {
|
||||
mutex_lock(&devfreq->lock);
|
||||
ret = update_devfreq(devfreq);
|
||||
mutex_unlock(&devfreq->lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct devfreq_governor devfreq_performance = {
|
||||
static struct devfreq_governor devfreq_performance = {
|
||||
.name = "performance",
|
||||
.init = performance_init,
|
||||
.get_target_freq = devfreq_performance_func,
|
||||
.no_central_polling = true,
|
||||
.event_handler = devfreq_performance_handler,
|
||||
};
|
||||
|
||||
static int __init devfreq_performance_init(void)
|
||||
{
|
||||
return devfreq_add_governor(&devfreq_performance);
|
||||
}
|
||||
subsys_initcall(devfreq_performance_init);
|
||||
|
||||
static void __exit devfreq_performance_exit(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = devfreq_remove_governor(&devfreq_performance);
|
||||
if (ret)
|
||||
pr_err("%s: failed remove governor %d\n", __func__, ret);
|
||||
|
||||
return;
|
||||
}
|
||||
module_exit(devfreq_performance_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/module.h>
|
||||
#include "governor.h"
|
||||
|
||||
static int devfreq_powersave_func(struct devfreq *df,
|
||||
|
@ -23,14 +24,41 @@ static int devfreq_powersave_func(struct devfreq *df,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int powersave_init(struct devfreq *devfreq)
|
||||
static int devfreq_powersave_handler(struct devfreq *devfreq,
|
||||
unsigned int event, void *data)
|
||||
{
|
||||
return update_devfreq(devfreq);
|
||||
int ret = 0;
|
||||
|
||||
if (event == DEVFREQ_GOV_START) {
|
||||
mutex_lock(&devfreq->lock);
|
||||
ret = update_devfreq(devfreq);
|
||||
mutex_unlock(&devfreq->lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct devfreq_governor devfreq_powersave = {
|
||||
static struct devfreq_governor devfreq_powersave = {
|
||||
.name = "powersave",
|
||||
.init = powersave_init,
|
||||
.get_target_freq = devfreq_powersave_func,
|
||||
.no_central_polling = true,
|
||||
.event_handler = devfreq_powersave_handler,
|
||||
};
|
||||
|
||||
static int __init devfreq_powersave_init(void)
|
||||
{
|
||||
return devfreq_add_governor(&devfreq_powersave);
|
||||
}
|
||||
subsys_initcall(devfreq_powersave_init);
|
||||
|
||||
static void __exit devfreq_powersave_exit(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = devfreq_remove_governor(&devfreq_powersave);
|
||||
if (ret)
|
||||
pr_err("%s: failed remove governor %d\n", __func__, ret);
|
||||
|
||||
return;
|
||||
}
|
||||
module_exit(devfreq_powersave_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -10,8 +10,10 @@
|
|||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/math64.h>
|
||||
#include "governor.h"
|
||||
|
||||
/* Default constants for DevFreq-Simple-Ondemand (DFSO) */
|
||||
#define DFSO_UPTHRESHOLD (90)
|
||||
|
@ -88,7 +90,58 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
|
|||
return 0;
|
||||
}
|
||||
|
||||
const struct devfreq_governor devfreq_simple_ondemand = {
|
||||
static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
|
||||
unsigned int event, void *data)
|
||||
{
|
||||
switch (event) {
|
||||
case DEVFREQ_GOV_START:
|
||||
devfreq_monitor_start(devfreq);
|
||||
break;
|
||||
|
||||
case DEVFREQ_GOV_STOP:
|
||||
devfreq_monitor_stop(devfreq);
|
||||
break;
|
||||
|
||||
case DEVFREQ_GOV_INTERVAL:
|
||||
devfreq_interval_update(devfreq, (unsigned int *)data);
|
||||
break;
|
||||
|
||||
case DEVFREQ_GOV_SUSPEND:
|
||||
devfreq_monitor_suspend(devfreq);
|
||||
break;
|
||||
|
||||
case DEVFREQ_GOV_RESUME:
|
||||
devfreq_monitor_resume(devfreq);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct devfreq_governor devfreq_simple_ondemand = {
|
||||
.name = "simple_ondemand",
|
||||
.get_target_freq = devfreq_simple_ondemand_func,
|
||||
.event_handler = devfreq_simple_ondemand_handler,
|
||||
};
|
||||
|
||||
static int __init devfreq_simple_ondemand_init(void)
|
||||
{
|
||||
return devfreq_add_governor(&devfreq_simple_ondemand);
|
||||
}
|
||||
subsys_initcall(devfreq_simple_ondemand_init);
|
||||
|
||||
static void __exit devfreq_simple_ondemand_exit(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = devfreq_remove_governor(&devfreq_simple_ondemand);
|
||||
if (ret)
|
||||
pr_err("%s: failed remove governor %d\n", __func__, ret);
|
||||
|
||||
return;
|
||||
}
|
||||
module_exit(devfreq_simple_ondemand_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/devfreq.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/module.h>
|
||||
#include "governor.h"
|
||||
|
||||
struct userspace_data {
|
||||
|
@ -116,10 +117,46 @@ static void userspace_exit(struct devfreq *devfreq)
|
|||
devfreq->data = NULL;
|
||||
}
|
||||
|
||||
const struct devfreq_governor devfreq_userspace = {
|
||||
static int devfreq_userspace_handler(struct devfreq *devfreq,
|
||||
unsigned int event, void *data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (event) {
|
||||
case DEVFREQ_GOV_START:
|
||||
ret = userspace_init(devfreq);
|
||||
break;
|
||||
case DEVFREQ_GOV_STOP:
|
||||
userspace_exit(devfreq);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct devfreq_governor devfreq_userspace = {
|
||||
.name = "userspace",
|
||||
.get_target_freq = devfreq_userspace_func,
|
||||
.init = userspace_init,
|
||||
.exit = userspace_exit,
|
||||
.no_central_polling = true,
|
||||
.event_handler = devfreq_userspace_handler,
|
||||
};
|
||||
|
||||
static int __init devfreq_userspace_init(void)
|
||||
{
|
||||
return devfreq_add_governor(&devfreq_userspace);
|
||||
}
|
||||
subsys_initcall(devfreq_userspace_init);
|
||||
|
||||
static void __exit devfreq_userspace_exit(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = devfreq_remove_governor(&devfreq_userspace);
|
||||
if (ret)
|
||||
pr_err("%s: failed remove governor %d\n", __func__, ret);
|
||||
|
||||
return;
|
||||
}
|
||||
module_exit(devfreq_userspace_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -25,12 +25,12 @@ struct devfreq;
|
|||
* struct devfreq_dev_status - Data given from devfreq user device to
|
||||
* governors. Represents the performance
|
||||
* statistics.
|
||||
* @total_time The total time represented by this instance of
|
||||
* @total_time: The total time represented by this instance of
|
||||
* devfreq_dev_status
|
||||
* @busy_time The time that the device was working among the
|
||||
* @busy_time: The time that the device was working among the
|
||||
* total_time.
|
||||
* @current_frequency The operating frequency.
|
||||
* @private_data An entry not specified by the devfreq framework.
|
||||
* @current_frequency: The operating frequency.
|
||||
* @private_data: An entry not specified by the devfreq framework.
|
||||
* A device and a specific governor may have their
|
||||
* own protocol with private_data. However, because
|
||||
* this is governor-specific, a governor using this
|
||||
|
@ -54,23 +54,27 @@ struct devfreq_dev_status {
|
|||
|
||||
/**
|
||||
* struct devfreq_dev_profile - Devfreq's user device profile
|
||||
* @initial_freq The operating frequency when devfreq_add_device() is
|
||||
* @initial_freq: The operating frequency when devfreq_add_device() is
|
||||
* called.
|
||||
* @polling_ms The polling interval in ms. 0 disables polling.
|
||||
* @target The device should set its operating frequency at
|
||||
* @polling_ms: The polling interval in ms. 0 disables polling.
|
||||
* @target: The device should set its operating frequency at
|
||||
* freq or lowest-upper-than-freq value. If freq is
|
||||
* higher than any operable frequency, set maximum.
|
||||
* Before returning, target function should set
|
||||
* freq at the current frequency.
|
||||
* The "flags" parameter's possible values are
|
||||
* explained above with "DEVFREQ_FLAG_*" macros.
|
||||
* @get_dev_status The device should provide the current performance
|
||||
* @get_dev_status: The device should provide the current performance
|
||||
* status to devfreq, which is used by governors.
|
||||
* @exit An optional callback that is called when devfreq
|
||||
* @get_cur_freq: The device should provide the current frequency
|
||||
* at which it is operating.
|
||||
* @exit: An optional callback that is called when devfreq
|
||||
* is removing the devfreq object due to error or
|
||||
* from devfreq_remove_device() call. If the user
|
||||
* has registered devfreq->nb at a notifier-head,
|
||||
* this is the time to unregister it.
|
||||
* @freq_table: Optional list of frequencies to support statistics.
|
||||
* @max_state: The size of freq_table.
|
||||
*/
|
||||
struct devfreq_dev_profile {
|
||||
unsigned long initial_freq;
|
||||
|
@ -79,63 +83,63 @@ struct devfreq_dev_profile {
|
|||
int (*target)(struct device *dev, unsigned long *freq, u32 flags);
|
||||
int (*get_dev_status)(struct device *dev,
|
||||
struct devfreq_dev_status *stat);
|
||||
int (*get_cur_freq)(struct device *dev, unsigned long *freq);
|
||||
void (*exit)(struct device *dev);
|
||||
|
||||
unsigned int *freq_table;
|
||||
unsigned int max_state;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct devfreq_governor - Devfreq policy governor
|
||||
* @name Governor's name
|
||||
* @get_target_freq Returns desired operating frequency for the device.
|
||||
* @node: list node - contains registered devfreq governors
|
||||
* @name: Governor's name
|
||||
* @get_target_freq: Returns desired operating frequency for the device.
|
||||
* Basically, get_target_freq will run
|
||||
* devfreq_dev_profile.get_dev_status() to get the
|
||||
* status of the device (load = busy_time / total_time).
|
||||
* If no_central_polling is set, this callback is called
|
||||
* only with update_devfreq() notified by OPP.
|
||||
* @init Called when the devfreq is being attached to a device
|
||||
* @exit Called when the devfreq is being removed from a
|
||||
* device. Governor should stop any internal routines
|
||||
* before return because related data may be
|
||||
* freed after exit().
|
||||
* @no_central_polling Do not use devfreq's central polling mechanism.
|
||||
* When this is set, devfreq will not call
|
||||
* get_target_freq with devfreq_monitor(). However,
|
||||
* devfreq will call get_target_freq with
|
||||
* devfreq_update() notified by OPP framework.
|
||||
* @event_handler: Callback for devfreq core framework to notify events
|
||||
* to governors. Events include per device governor
|
||||
* init and exit, opp changes out of devfreq, suspend
|
||||
* and resume of per device devfreq during device idle.
|
||||
*
|
||||
* Note that the callbacks are called with devfreq->lock locked by devfreq.
|
||||
*/
|
||||
struct devfreq_governor {
|
||||
struct list_head node;
|
||||
|
||||
const char name[DEVFREQ_NAME_LEN];
|
||||
int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
|
||||
int (*init)(struct devfreq *this);
|
||||
void (*exit)(struct devfreq *this);
|
||||
const bool no_central_polling;
|
||||
int (*event_handler)(struct devfreq *devfreq,
|
||||
unsigned int event, void *data);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct devfreq - Device devfreq structure
|
||||
* @node list node - contains the devices with devfreq that have been
|
||||
* @node: list node - contains the devices with devfreq that have been
|
||||
* registered.
|
||||
* @lock a mutex to protect accessing devfreq.
|
||||
* @dev device registered by devfreq class. dev.parent is the device
|
||||
* @lock: a mutex to protect accessing devfreq.
|
||||
* @dev: device registered by devfreq class. dev.parent is the device
|
||||
* using devfreq.
|
||||
* @profile device-specific devfreq profile
|
||||
* @governor method how to choose frequency based on the usage.
|
||||
* @nb notifier block used to notify devfreq object that it should
|
||||
* @profile: device-specific devfreq profile
|
||||
* @governor: method how to choose frequency based on the usage.
|
||||
* @governor_name: devfreq governor name for use with this devfreq
|
||||
* @nb: notifier block used to notify devfreq object that it should
|
||||
* reevaluate operable frequencies. Devfreq users may use
|
||||
* devfreq.nb to the corresponding register notifier call chain.
|
||||
* @polling_jiffies interval in jiffies.
|
||||
* @previous_freq previously configured frequency value.
|
||||
* @next_polling the number of remaining jiffies to poll with
|
||||
* "devfreq_monitor" executions to reevaluate
|
||||
* frequency/voltage of the device. Set by
|
||||
* profile's polling_ms interval.
|
||||
* @data Private data of the governor. The devfreq framework does not
|
||||
* @work: delayed work for load monitoring.
|
||||
* @previous_freq: previously configured frequency value.
|
||||
* @data: Private data of the governor. The devfreq framework does not
|
||||
* touch this.
|
||||
* @being_removed a flag to mark that this object is being removed in
|
||||
* order to prevent trying to remove the object multiple times.
|
||||
* @min_freq Limit minimum frequency requested by user (0: none)
|
||||
* @max_freq Limit maximum frequency requested by user (0: none)
|
||||
* @min_freq: Limit minimum frequency requested by user (0: none)
|
||||
* @max_freq: Limit maximum frequency requested by user (0: none)
|
||||
* @stop_polling: devfreq polling status of a device.
|
||||
* @total_trans: Number of devfreq transitions
|
||||
* @trans_table: Statistics of devfreq transitions
|
||||
* @time_in_state: Statistics of devfreq states
|
||||
* @last_stat_updated: The last time stat updated
|
||||
*
|
||||
* This structure stores the devfreq information for a give device.
|
||||
*
|
||||
|
@ -152,26 +156,33 @@ struct devfreq {
|
|||
struct device dev;
|
||||
struct devfreq_dev_profile *profile;
|
||||
const struct devfreq_governor *governor;
|
||||
char governor_name[DEVFREQ_NAME_LEN];
|
||||
struct notifier_block nb;
|
||||
struct delayed_work work;
|
||||
|
||||
unsigned long polling_jiffies;
|
||||
unsigned long previous_freq;
|
||||
unsigned int next_polling;
|
||||
|
||||
void *data; /* private data for governors */
|
||||
|
||||
bool being_removed;
|
||||
|
||||
unsigned long min_freq;
|
||||
unsigned long max_freq;
|
||||
bool stop_polling;
|
||||
|
||||
/* information for device freqeuncy transition */
|
||||
unsigned int total_trans;
|
||||
unsigned int *trans_table;
|
||||
unsigned long *time_in_state;
|
||||
unsigned long last_stat_updated;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_PM_DEVFREQ)
|
||||
extern struct devfreq *devfreq_add_device(struct device *dev,
|
||||
struct devfreq_dev_profile *profile,
|
||||
const struct devfreq_governor *governor,
|
||||
const char *governor_name,
|
||||
void *data);
|
||||
extern int devfreq_remove_device(struct devfreq *devfreq);
|
||||
extern int devfreq_suspend_device(struct devfreq *devfreq);
|
||||
extern int devfreq_resume_device(struct devfreq *devfreq);
|
||||
|
||||
/* Helper functions for devfreq user device driver with OPP. */
|
||||
extern struct opp *devfreq_recommended_opp(struct device *dev,
|
||||
|
@ -181,23 +192,13 @@ extern int devfreq_register_opp_notifier(struct device *dev,
|
|||
extern int devfreq_unregister_opp_notifier(struct device *dev,
|
||||
struct devfreq *devfreq);
|
||||
|
||||
#ifdef CONFIG_DEVFREQ_GOV_POWERSAVE
|
||||
extern const struct devfreq_governor devfreq_powersave;
|
||||
#endif
|
||||
#ifdef CONFIG_DEVFREQ_GOV_PERFORMANCE
|
||||
extern const struct devfreq_governor devfreq_performance;
|
||||
#endif
|
||||
#ifdef CONFIG_DEVFREQ_GOV_USERSPACE
|
||||
extern const struct devfreq_governor devfreq_userspace;
|
||||
#endif
|
||||
#ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND
|
||||
extern const struct devfreq_governor devfreq_simple_ondemand;
|
||||
#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
|
||||
/**
|
||||
* struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
|
||||
* and devfreq_add_device
|
||||
* @ upthreshold If the load is over this value, the frequency jumps.
|
||||
* @upthreshold: If the load is over this value, the frequency jumps.
|
||||
* Specify 0 to use the default. Valid value = 0 to 100.
|
||||
* @ downdifferential If the load is under upthreshold - downdifferential,
|
||||
* @downdifferential: If the load is under upthreshold - downdifferential,
|
||||
* the governor may consider slowing the frequency down.
|
||||
* Specify 0 to use the default. Valid value = 0 to 100.
|
||||
* downdifferential < upthreshold must hold.
|
||||
|
@ -214,7 +215,7 @@ struct devfreq_simple_ondemand_data {
|
|||
#else /* !CONFIG_PM_DEVFREQ */
|
||||
static struct devfreq *devfreq_add_device(struct device *dev,
|
||||
struct devfreq_dev_profile *profile,
|
||||
struct devfreq_governor *governor,
|
||||
const char *governor_name,
|
||||
void *data)
|
||||
{
|
||||
return NULL;
|
||||
|
@ -225,6 +226,16 @@ static int devfreq_remove_device(struct devfreq *devfreq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int devfreq_suspend_device(struct devfreq *devfreq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int devfreq_resume_device(struct devfreq *devfreq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct opp *devfreq_recommended_opp(struct device *dev,
|
||||
unsigned long *freq, u32 flags)
|
||||
{
|
||||
|
@ -243,11 +254,6 @@ static int devfreq_unregister_opp_notifier(struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
#define devfreq_powersave NULL
|
||||
#define devfreq_performance NULL
|
||||
#define devfreq_userspace NULL
|
||||
#define devfreq_simple_ondemand NULL
|
||||
|
||||
#endif /* CONFIG_PM_DEVFREQ */
|
||||
|
||||
#endif /* __LINUX_DEVFREQ_H__ */
|
||||
|
|
Loading…
Reference in a new issue