mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-13 09:20:17 +00:00
Merge branch 'pm-devfreq'
* pm-devfreq: PM / devfreq: add relation of recommended frequency.
This commit is contained in:
commit
0f0cc1687d
@ -83,6 +83,7 @@ int update_devfreq(struct devfreq *devfreq)
|
|||||||
{
|
{
|
||||||
unsigned long freq;
|
unsigned long freq;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
u32 flags = 0;
|
||||||
|
|
||||||
if (!mutex_is_locked(&devfreq->lock)) {
|
if (!mutex_is_locked(&devfreq->lock)) {
|
||||||
WARN(true, "devfreq->lock must be locked by the caller.\n");
|
WARN(true, "devfreq->lock must be locked by the caller.\n");
|
||||||
@ -94,7 +95,24 @@ int update_devfreq(struct devfreq *devfreq)
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = devfreq->profile->target(devfreq->dev.parent, &freq);
|
/*
|
||||||
|
* Adjust the freuqency with user freq and QoS.
|
||||||
|
*
|
||||||
|
* List from the highest proiority
|
||||||
|
* max_freq (probably called by thermal when it's too hot)
|
||||||
|
* min_freq
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (devfreq->min_freq && freq < devfreq->min_freq) {
|
||||||
|
freq = devfreq->min_freq;
|
||||||
|
flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */
|
||||||
|
}
|
||||||
|
if (devfreq->max_freq && freq > devfreq->max_freq) {
|
||||||
|
freq = devfreq->max_freq;
|
||||||
|
flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */
|
||||||
|
}
|
||||||
|
|
||||||
|
err = devfreq->profile->target(devfreq->dev.parent, &freq, flags);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -625,14 +643,30 @@ module_exit(devfreq_exit);
|
|||||||
* freq value given to target callback.
|
* freq value given to target callback.
|
||||||
* @dev The devfreq user device. (parent of devfreq)
|
* @dev The devfreq user device. (parent of devfreq)
|
||||||
* @freq The frequency given to target function
|
* @freq The frequency given to target function
|
||||||
|
* @flags Flags handed from devfreq framework.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq)
|
struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
|
||||||
|
u32 flags)
|
||||||
{
|
{
|
||||||
struct opp *opp = opp_find_freq_ceil(dev, freq);
|
struct opp *opp;
|
||||||
|
|
||||||
if (opp == ERR_PTR(-ENODEV))
|
if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) {
|
||||||
|
/* The freq is an upper bound. opp should be lower */
|
||||||
opp = opp_find_freq_floor(dev, freq);
|
opp = opp_find_freq_floor(dev, freq);
|
||||||
|
|
||||||
|
/* If not available, use the closest opp */
|
||||||
|
if (opp == ERR_PTR(-ENODEV))
|
||||||
|
opp = opp_find_freq_ceil(dev, freq);
|
||||||
|
} else {
|
||||||
|
/* The freq is an lower bound. opp should be higher */
|
||||||
|
opp = opp_find_freq_ceil(dev, freq);
|
||||||
|
|
||||||
|
/* If not available, use the closest opp */
|
||||||
|
if (opp == ERR_PTR(-ENODEV))
|
||||||
|
opp = opp_find_freq_floor(dev, freq);
|
||||||
|
}
|
||||||
|
|
||||||
return opp;
|
return opp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,13 +619,19 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int exynos4_bus_target(struct device *dev, unsigned long *_freq)
|
static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
|
||||||
|
u32 flags)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
struct busfreq_data *data = dev_get_drvdata(dev);
|
struct platform_device *pdev = container_of(dev, struct platform_device,
|
||||||
struct opp *opp = devfreq_recommended_opp(dev, _freq);
|
dev);
|
||||||
unsigned long old_freq = opp_get_freq(data->curr_opp);
|
struct busfreq_data *data = platform_get_drvdata(pdev);
|
||||||
|
struct opp *opp = devfreq_recommended_opp(dev, _freq, flags);
|
||||||
unsigned long freq = opp_get_freq(opp);
|
unsigned long freq = opp_get_freq(opp);
|
||||||
|
unsigned long old_freq = opp_get_freq(data->curr_opp);
|
||||||
|
|
||||||
|
if (IS_ERR(opp))
|
||||||
|
return PTR_ERR(opp);
|
||||||
|
|
||||||
if (old_freq == freq)
|
if (old_freq == freq)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -44,6 +44,14 @@ struct devfreq_dev_status {
|
|||||||
void *private_data;
|
void *private_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The resulting frequency should be at most this. (this bound is the
|
||||||
|
* least upper bound; thus, the resulting freq should be lower or same)
|
||||||
|
* If the flag is not set, the resulting frequency should be at most the
|
||||||
|
* bound (greatest lower bound)
|
||||||
|
*/
|
||||||
|
#define DEVFREQ_FLAG_LEAST_UPPER_BOUND 0x1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct devfreq_dev_profile - Devfreq's user device profile
|
* 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
|
||||||
@ -54,6 +62,8 @@ struct devfreq_dev_status {
|
|||||||
* higher than any operable frequency, set maximum.
|
* higher than any operable frequency, set maximum.
|
||||||
* Before returning, target function should set
|
* Before returning, target function should set
|
||||||
* freq at the current frequency.
|
* 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.
|
* status to devfreq, which is used by governors.
|
||||||
* @exit An optional callback that is called when devfreq
|
* @exit An optional callback that is called when devfreq
|
||||||
@ -66,7 +76,7 @@ struct devfreq_dev_profile {
|
|||||||
unsigned long initial_freq;
|
unsigned long initial_freq;
|
||||||
unsigned int polling_ms;
|
unsigned int polling_ms;
|
||||||
|
|
||||||
int (*target)(struct device *dev, unsigned long *freq);
|
int (*target)(struct device *dev, unsigned long *freq, u32 flags);
|
||||||
int (*get_dev_status)(struct device *dev,
|
int (*get_dev_status)(struct device *dev,
|
||||||
struct devfreq_dev_status *stat);
|
struct devfreq_dev_status *stat);
|
||||||
void (*exit)(struct device *dev);
|
void (*exit)(struct device *dev);
|
||||||
@ -165,7 +175,7 @@ extern int devfreq_remove_device(struct devfreq *devfreq);
|
|||||||
|
|
||||||
/* Helper functions for devfreq user device driver with OPP. */
|
/* Helper functions for devfreq user device driver with OPP. */
|
||||||
extern struct opp *devfreq_recommended_opp(struct device *dev,
|
extern struct opp *devfreq_recommended_opp(struct device *dev,
|
||||||
unsigned long *freq);
|
unsigned long *freq, u32 flags);
|
||||||
extern int devfreq_register_opp_notifier(struct device *dev,
|
extern int devfreq_register_opp_notifier(struct device *dev,
|
||||||
struct devfreq *devfreq);
|
struct devfreq *devfreq);
|
||||||
extern int devfreq_unregister_opp_notifier(struct device *dev,
|
extern int devfreq_unregister_opp_notifier(struct device *dev,
|
||||||
@ -216,7 +226,7 @@ static int devfreq_remove_device(struct devfreq *devfreq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct opp *devfreq_recommended_opp(struct device *dev,
|
static struct opp *devfreq_recommended_opp(struct device *dev,
|
||||||
unsigned long *freq)
|
unsigned long *freq, u32 flags)
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user