Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f0cc168 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-devfreq'

* pm-devfreq:
  PM / devfreq: add relation of recommended frequency.
parents 62dc7c02 ab5f299f
Loading
Loading
Loading
Loading
+38 −4
Original line number Original line Diff line number Diff line
@@ -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 (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) {
		/* The freq is an upper bound. opp should be lower */
		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))
		if (opp == ERR_PTR(-ENODEV))
			opp = opp_find_freq_floor(dev, freq);
			opp = opp_find_freq_floor(dev, freq);
	}

	return opp;
	return opp;
}
}


+10 −4
Original line number Original line Diff line number Diff line
@@ -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;
+13 −3
Original line number Original line Diff line number Diff line
@@ -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;
}
}