2019-06-04 16:11:33 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
/*
|
|
|
|
* devfreq: Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework
|
|
|
|
* for Non-CPU Devices.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2011 Samsung Electronics
|
|
|
|
* MyungJoo Ham <myungjoo.ham@samsung.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
2018-07-04 16:45:50 +08:00
|
|
|
#include <linux/kmod.h>
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
#include <linux/sched.h>
|
2019-12-26 13:23:49 +08:00
|
|
|
#include <linux/debugfs.h>
|
2021-03-08 21:30:37 +08:00
|
|
|
#include <linux/devfreq_cooling.h>
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/err.h>
|
|
|
|
#include <linux/init.h>
|
2016-06-26 02:43:47 +08:00
|
|
|
#include <linux/export.h>
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
#include <linux/slab.h>
|
2011-11-10 17:16:23 +08:00
|
|
|
#include <linux/stat.h>
|
2013-09-20 05:03:52 +08:00
|
|
|
#include <linux/pm_opp.h>
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
#include <linux/devfreq.h>
|
|
|
|
#include <linux/workqueue.h>
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <linux/list.h>
|
|
|
|
#include <linux/printk.h>
|
|
|
|
#include <linux/hrtimer.h>
|
2015-11-10 19:31:07 +08:00
|
|
|
#include <linux/of.h>
|
2019-12-05 18:05:06 +08:00
|
|
|
#include <linux/pm_qos.h>
|
2021-09-08 10:57:54 +08:00
|
|
|
#include <linux/units.h>
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
#include "governor.h"
|
|
|
|
|
2019-02-19 02:21:09 +08:00
|
|
|
#define CREATE_TRACE_POINTS
|
|
|
|
#include <trace/events/devfreq.h>
|
|
|
|
|
2020-10-05 13:48:01 +08:00
|
|
|
#define IS_SUPPORTED_FLAG(f, name) ((f & DEVFREQ_GOV_FLAG_##name) ? true : false)
|
2020-07-03 16:20:27 +08:00
|
|
|
#define IS_SUPPORTED_ATTR(f, name) ((f & DEVFREQ_GOV_ATTR_##name) ? true : false)
|
2019-12-05 18:05:06 +08:00
|
|
|
|
2012-10-26 07:50:53 +08:00
|
|
|
static struct class *devfreq_class;
|
2019-12-26 13:23:49 +08:00
|
|
|
static struct dentry *devfreq_debugfs;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
|
|
|
/*
|
2012-10-26 07:50:09 +08:00
|
|
|
* devfreq core provides delayed work based load monitoring helper
|
|
|
|
* functions. Governors can use these or can implement their own
|
|
|
|
* monitoring mechanism.
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
*/
|
|
|
|
static struct workqueue_struct *devfreq_wq;
|
|
|
|
|
2012-10-30 04:01:43 +08:00
|
|
|
/* The list of all device-devfreq governors */
|
|
|
|
static LIST_HEAD(devfreq_governor_list);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
/* The list of all device-devfreq */
|
|
|
|
static LIST_HEAD(devfreq_list);
|
|
|
|
static DEFINE_MUTEX(devfreq_list_lock);
|
|
|
|
|
2020-07-02 19:41:28 +08:00
|
|
|
static const char timer_name[][DEVFREQ_NAME_LEN] = {
|
|
|
|
[DEVFREQ_TIMER_DEFERRABLE] = { "deferrable" },
|
|
|
|
[DEVFREQ_TIMER_DELAYED] = { "delayed" },
|
|
|
|
};
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
/**
|
|
|
|
* find_device_devfreq() - find devfreq struct using device pointer
|
|
|
|
* @dev: device pointer used to lookup device devfreq.
|
|
|
|
*
|
|
|
|
* Search the list of device devfreqs and return the matched device's
|
|
|
|
* devfreq info. devfreq_list_lock should be held by the caller.
|
|
|
|
*/
|
|
|
|
static struct devfreq *find_device_devfreq(struct device *dev)
|
|
|
|
{
|
|
|
|
struct devfreq *tmp_devfreq;
|
|
|
|
|
2020-05-12 14:41:58 +08:00
|
|
|
lockdep_assert_held(&devfreq_list_lock);
|
|
|
|
|
2015-08-10 14:12:25 +08:00
|
|
|
if (IS_ERR_OR_NULL(dev)) {
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
|
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(tmp_devfreq, &devfreq_list, node) {
|
|
|
|
if (tmp_devfreq->dev.parent == dev)
|
|
|
|
return tmp_devfreq;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
}
|
|
|
|
|
2017-10-23 09:32:06 +08:00
|
|
|
static unsigned long find_available_min_freq(struct devfreq *devfreq)
|
|
|
|
{
|
|
|
|
struct dev_pm_opp *opp;
|
|
|
|
unsigned long min_freq = 0;
|
|
|
|
|
|
|
|
opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &min_freq);
|
|
|
|
if (IS_ERR(opp))
|
|
|
|
min_freq = 0;
|
|
|
|
else
|
|
|
|
dev_pm_opp_put(opp);
|
|
|
|
|
|
|
|
return min_freq;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned long find_available_max_freq(struct devfreq *devfreq)
|
|
|
|
{
|
|
|
|
struct dev_pm_opp *opp;
|
|
|
|
unsigned long max_freq = ULONG_MAX;
|
|
|
|
|
|
|
|
opp = dev_pm_opp_find_freq_floor(devfreq->dev.parent, &max_freq);
|
|
|
|
if (IS_ERR(opp))
|
|
|
|
max_freq = 0;
|
|
|
|
else
|
|
|
|
dev_pm_opp_put(opp);
|
|
|
|
|
|
|
|
return max_freq;
|
|
|
|
}
|
|
|
|
|
2019-11-01 05:34:26 +08:00
|
|
|
/**
|
|
|
|
* get_freq_range() - Get the current freq range
|
|
|
|
* @devfreq: the devfreq instance
|
|
|
|
* @min_freq: the min frequency
|
|
|
|
* @max_freq: the max frequency
|
|
|
|
*
|
|
|
|
* This takes into consideration all constraints.
|
|
|
|
*/
|
|
|
|
static void get_freq_range(struct devfreq *devfreq,
|
|
|
|
unsigned long *min_freq,
|
|
|
|
unsigned long *max_freq)
|
|
|
|
{
|
|
|
|
unsigned long *freq_table = devfreq->profile->freq_table;
|
2019-12-05 18:05:06 +08:00
|
|
|
s32 qos_min_freq, qos_max_freq;
|
2019-11-01 05:34:26 +08:00
|
|
|
|
|
|
|
lockdep_assert_held(&devfreq->lock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize minimum/maximum frequency from freq table.
|
|
|
|
* The devfreq drivers can initialize this in either ascending or
|
|
|
|
* descending order and devfreq core supports both.
|
|
|
|
*/
|
|
|
|
if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) {
|
|
|
|
*min_freq = freq_table[0];
|
|
|
|
*max_freq = freq_table[devfreq->profile->max_state - 1];
|
|
|
|
} else {
|
|
|
|
*min_freq = freq_table[devfreq->profile->max_state - 1];
|
|
|
|
*max_freq = freq_table[0];
|
|
|
|
}
|
|
|
|
|
2019-12-05 18:05:06 +08:00
|
|
|
/* Apply constraints from PM QoS */
|
|
|
|
qos_min_freq = dev_pm_qos_read_value(devfreq->dev.parent,
|
|
|
|
DEV_PM_QOS_MIN_FREQUENCY);
|
|
|
|
qos_max_freq = dev_pm_qos_read_value(devfreq->dev.parent,
|
|
|
|
DEV_PM_QOS_MAX_FREQUENCY);
|
|
|
|
*min_freq = max(*min_freq, (unsigned long)HZ_PER_KHZ * qos_min_freq);
|
|
|
|
if (qos_max_freq != PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE)
|
|
|
|
*max_freq = min(*max_freq,
|
|
|
|
(unsigned long)HZ_PER_KHZ * qos_max_freq);
|
|
|
|
|
2019-11-01 05:34:26 +08:00
|
|
|
/* Apply constraints from OPP interface */
|
|
|
|
*min_freq = max(*min_freq, devfreq->scaling_min_freq);
|
|
|
|
*max_freq = min(*max_freq, devfreq->scaling_max_freq);
|
|
|
|
|
|
|
|
if (*min_freq > *max_freq)
|
|
|
|
*min_freq = *max_freq;
|
|
|
|
}
|
|
|
|
|
2012-08-23 19:00:46 +08:00
|
|
|
/**
|
|
|
|
* devfreq_get_freq_level() - Lookup freq_table for the frequency
|
|
|
|
* @devfreq: the devfreq instance
|
|
|
|
* @freq: the target frequency
|
|
|
|
*/
|
|
|
|
static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
|
|
|
|
{
|
|
|
|
int lev;
|
|
|
|
|
|
|
|
for (lev = 0; lev < devfreq->profile->max_state; lev++)
|
|
|
|
if (freq == devfreq->profile->freq_table[lev])
|
|
|
|
return lev;
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2017-10-23 09:32:09 +08:00
|
|
|
static int set_freq_table(struct devfreq *devfreq)
|
2015-11-18 13:49:02 +08:00
|
|
|
{
|
|
|
|
struct devfreq_dev_profile *profile = devfreq->profile;
|
|
|
|
struct dev_pm_opp *opp;
|
|
|
|
unsigned long freq;
|
|
|
|
int i, count;
|
|
|
|
|
|
|
|
/* Initialize the freq_table from OPP table */
|
|
|
|
count = dev_pm_opp_get_opp_count(devfreq->dev.parent);
|
|
|
|
if (count <= 0)
|
2017-10-23 09:32:09 +08:00
|
|
|
return -EINVAL;
|
2015-11-18 13:49:02 +08:00
|
|
|
|
|
|
|
profile->max_state = count;
|
|
|
|
profile->freq_table = devm_kcalloc(devfreq->dev.parent,
|
|
|
|
profile->max_state,
|
|
|
|
sizeof(*profile->freq_table),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!profile->freq_table) {
|
|
|
|
profile->max_state = 0;
|
2017-10-23 09:32:09 +08:00
|
|
|
return -ENOMEM;
|
2015-11-18 13:49:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0, freq = 0; i < profile->max_state; i++, freq++) {
|
|
|
|
opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
|
|
|
|
if (IS_ERR(opp)) {
|
|
|
|
devm_kfree(devfreq->dev.parent, profile->freq_table);
|
|
|
|
profile->max_state = 0;
|
2017-10-23 09:32:09 +08:00
|
|
|
return PTR_ERR(opp);
|
2015-11-18 13:49:02 +08:00
|
|
|
}
|
2017-01-23 12:41:47 +08:00
|
|
|
dev_pm_opp_put(opp);
|
2015-11-18 13:49:02 +08:00
|
|
|
profile->freq_table[i] = freq;
|
|
|
|
}
|
2017-10-23 09:32:09 +08:00
|
|
|
|
|
|
|
return 0;
|
2015-11-18 13:49:02 +08:00
|
|
|
}
|
|
|
|
|
2012-08-23 19:00:46 +08:00
|
|
|
/**
|
|
|
|
* devfreq_update_status() - Update statistics of devfreq behavior
|
|
|
|
* @devfreq: the devfreq instance
|
|
|
|
* @freq: the update target frequency
|
|
|
|
*/
|
2017-01-31 14:38:17 +08:00
|
|
|
int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
|
2012-08-23 19:00:46 +08:00
|
|
|
{
|
2014-02-28 11:38:57 +08:00
|
|
|
int lev, prev_lev, ret = 0;
|
2019-12-05 22:55:25 +08:00
|
|
|
u64 cur_time;
|
2012-08-23 19:00:46 +08:00
|
|
|
|
2019-09-24 15:52:23 +08:00
|
|
|
lockdep_assert_held(&devfreq->lock);
|
2019-12-05 22:55:25 +08:00
|
|
|
cur_time = get_jiffies_64();
|
2014-02-28 11:38:57 +08:00
|
|
|
|
2016-09-29 20:36:36 +08:00
|
|
|
/* Immediately exit if previous_freq is not initialized yet. */
|
|
|
|
if (!devfreq->previous_freq)
|
|
|
|
goto out;
|
|
|
|
|
2014-02-28 11:38:57 +08:00
|
|
|
prev_lev = devfreq_get_freq_level(devfreq, devfreq->previous_freq);
|
|
|
|
if (prev_lev < 0) {
|
|
|
|
ret = prev_lev;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2019-12-06 12:46:39 +08:00
|
|
|
devfreq->stats.time_in_state[prev_lev] +=
|
|
|
|
cur_time - devfreq->stats.last_update;
|
2014-02-28 11:38:57 +08:00
|
|
|
|
|
|
|
lev = devfreq_get_freq_level(devfreq, freq);
|
|
|
|
if (lev < 0) {
|
|
|
|
ret = lev;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lev != prev_lev) {
|
2019-12-06 12:46:39 +08:00
|
|
|
devfreq->stats.trans_table[
|
|
|
|
(prev_lev * devfreq->profile->max_state) + lev]++;
|
|
|
|
devfreq->stats.total_trans++;
|
2012-08-23 19:00:46 +08:00
|
|
|
}
|
|
|
|
|
2014-02-28 11:38:57 +08:00
|
|
|
out:
|
2019-12-06 12:46:39 +08:00
|
|
|
devfreq->stats.last_update = cur_time;
|
2014-02-28 11:38:57 +08:00
|
|
|
return ret;
|
2012-08-23 19:00:46 +08:00
|
|
|
}
|
2017-01-31 14:38:17 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_update_status);
|
2012-08-23 19:00:46 +08:00
|
|
|
|
2012-10-30 04:01:43 +08:00
|
|
|
/**
|
|
|
|
* find_devfreq_governor() - find devfreq governor from name
|
|
|
|
* @name: name of the governor
|
|
|
|
*
|
|
|
|
* Search the list of devfreq governors and return the matched
|
|
|
|
* governor's pointer. devfreq_list_lock should be held by the caller.
|
|
|
|
*/
|
|
|
|
static struct devfreq_governor *find_devfreq_governor(const char *name)
|
|
|
|
{
|
|
|
|
struct devfreq_governor *tmp_governor;
|
|
|
|
|
2020-05-12 14:41:58 +08:00
|
|
|
lockdep_assert_held(&devfreq_list_lock);
|
|
|
|
|
2015-08-10 14:12:25 +08:00
|
|
|
if (IS_ERR_OR_NULL(name)) {
|
2012-10-30 04:01:43 +08:00
|
|
|
pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
|
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(tmp_governor, &devfreq_governor_list, node) {
|
|
|
|
if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
|
|
|
|
return tmp_governor;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:45:50 +08:00
|
|
|
/**
|
|
|
|
* try_then_request_governor() - Try to find the governor and request the
|
|
|
|
* module if is not found.
|
|
|
|
* @name: name of the governor
|
|
|
|
*
|
|
|
|
* Search the list of devfreq governors and request the module and try again
|
|
|
|
* if is not found. This can happen when both drivers (the governor driver
|
|
|
|
* and the driver that call devfreq_add_device) are built as modules.
|
|
|
|
* devfreq_list_lock should be held by the caller. Returns the matched
|
2019-03-13 20:22:53 +08:00
|
|
|
* governor's pointer or an error pointer.
|
2018-07-04 16:45:50 +08:00
|
|
|
*/
|
|
|
|
static struct devfreq_governor *try_then_request_governor(const char *name)
|
|
|
|
{
|
|
|
|
struct devfreq_governor *governor;
|
|
|
|
int err = 0;
|
|
|
|
|
2020-05-12 14:41:58 +08:00
|
|
|
lockdep_assert_held(&devfreq_list_lock);
|
|
|
|
|
2018-07-04 16:45:50 +08:00
|
|
|
if (IS_ERR_OR_NULL(name)) {
|
|
|
|
pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
|
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
governor = find_devfreq_governor(name);
|
|
|
|
if (IS_ERR(governor)) {
|
|
|
|
mutex_unlock(&devfreq_list_lock);
|
|
|
|
|
|
|
|
if (!strncmp(name, DEVFREQ_GOV_SIMPLE_ONDEMAND,
|
|
|
|
DEVFREQ_NAME_LEN))
|
|
|
|
err = request_module("governor_%s", "simpleondemand");
|
|
|
|
else
|
|
|
|
err = request_module("governor_%s", name);
|
|
|
|
/* Restore previous state before return */
|
|
|
|
mutex_lock(&devfreq_list_lock);
|
|
|
|
if (err)
|
2019-06-22 05:39:49 +08:00
|
|
|
return (err < 0) ? ERR_PTR(err) : ERR_PTR(-EINVAL);
|
2018-07-04 16:45:50 +08:00
|
|
|
|
|
|
|
governor = find_devfreq_governor(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return governor;
|
|
|
|
}
|
|
|
|
|
2016-01-26 12:21:26 +08:00
|
|
|
static int devfreq_notify_transition(struct devfreq *devfreq,
|
|
|
|
struct devfreq_freqs *freqs, unsigned int state)
|
|
|
|
{
|
|
|
|
if (!devfreq)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case DEVFREQ_PRECHANGE:
|
|
|
|
srcu_notifier_call_chain(&devfreq->transition_notifier_list,
|
|
|
|
DEVFREQ_PRECHANGE, freqs);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DEVFREQ_POSTCHANGE:
|
|
|
|
srcu_notifier_call_chain(&devfreq->transition_notifier_list,
|
|
|
|
DEVFREQ_POSTCHANGE, freqs);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-12-05 19:05:52 +08:00
|
|
|
static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq,
|
|
|
|
u32 flags)
|
|
|
|
{
|
|
|
|
struct devfreq_freqs freqs;
|
|
|
|
unsigned long cur_freq;
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
if (devfreq->profile->get_cur_freq)
|
|
|
|
devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
|
|
|
|
else
|
|
|
|
cur_freq = devfreq->previous_freq;
|
|
|
|
|
|
|
|
freqs.old = cur_freq;
|
|
|
|
freqs.new = new_freq;
|
|
|
|
devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);
|
|
|
|
|
|
|
|
err = devfreq->profile->target(devfreq->dev.parent, &new_freq, flags);
|
|
|
|
if (err) {
|
|
|
|
freqs.new = cur_freq;
|
|
|
|
devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-10-07 21:03:59 +08:00
|
|
|
/*
|
|
|
|
* Print devfreq_frequency trace information between DEVFREQ_PRECHANGE
|
|
|
|
* and DEVFREQ_POSTCHANGE because for showing the correct frequency
|
|
|
|
* change order of between devfreq device and passive devfreq device.
|
|
|
|
*/
|
|
|
|
if (trace_devfreq_frequency_enabled() && new_freq != cur_freq)
|
|
|
|
trace_devfreq_frequency(devfreq, new_freq, cur_freq);
|
|
|
|
|
2018-12-05 19:05:52 +08:00
|
|
|
freqs.new = new_freq;
|
|
|
|
devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
|
|
|
|
|
|
|
|
if (devfreq_update_status(devfreq, new_freq))
|
|
|
|
dev_err(&devfreq->dev,
|
|
|
|
"Couldn't update frequency transition information.\n");
|
|
|
|
|
|
|
|
devfreq->previous_freq = new_freq;
|
2018-12-05 19:05:53 +08:00
|
|
|
|
|
|
|
if (devfreq->suspend_freq)
|
2021-03-23 15:20:08 +08:00
|
|
|
devfreq->resume_freq = new_freq;
|
2018-12-05 19:05:53 +08:00
|
|
|
|
2018-12-05 19:05:52 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
/**
|
2020-10-07 21:02:39 +08:00
|
|
|
* devfreq_update_target() - Reevaluate the device and configure frequency
|
|
|
|
* on the final stage.
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
* @devfreq: the devfreq instance.
|
2020-10-07 21:02:39 +08:00
|
|
|
* @freq: the new frequency of parent device. This argument
|
|
|
|
* is only used for devfreq device using passive governor.
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
*
|
2020-10-07 21:02:39 +08:00
|
|
|
* Note: Lock devfreq->lock before calling devfreq_update_target. This function
|
|
|
|
* should be only used by both update_devfreq() and devfreq governors.
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
*/
|
2020-10-07 21:02:39 +08:00
|
|
|
int devfreq_update_target(struct devfreq *devfreq, unsigned long freq)
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
{
|
2020-10-07 21:02:39 +08:00
|
|
|
unsigned long min_freq, max_freq;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
int err = 0;
|
2012-03-17 04:54:53 +08:00
|
|
|
u32 flags = 0;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
2020-05-12 14:41:58 +08:00
|
|
|
lockdep_assert_held(&devfreq->lock);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
2012-10-30 04:01:45 +08:00
|
|
|
if (!devfreq->governor)
|
|
|
|
return -EINVAL;
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
/* Reevaluate the proper frequency */
|
|
|
|
err = devfreq->governor->get_target_freq(devfreq, &freq);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2019-11-01 05:34:26 +08:00
|
|
|
get_freq_range(devfreq, &min_freq, &max_freq);
|
2012-03-17 04:54:53 +08:00
|
|
|
|
2018-08-04 04:05:09 +08:00
|
|
|
if (freq < min_freq) {
|
2017-10-23 09:32:08 +08:00
|
|
|
freq = min_freq;
|
2012-03-17 04:54:53 +08:00
|
|
|
flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */
|
|
|
|
}
|
2018-08-04 04:05:09 +08:00
|
|
|
if (freq > max_freq) {
|
2017-10-23 09:32:08 +08:00
|
|
|
freq = max_freq;
|
2012-03-17 04:54:53 +08:00
|
|
|
flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */
|
|
|
|
}
|
|
|
|
|
2018-12-05 19:05:52 +08:00
|
|
|
return devfreq_set_target(devfreq, freq, flags);
|
2020-10-07 21:02:39 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devfreq_update_target);
|
|
|
|
|
|
|
|
/* Load monitoring helper functions for governors use */
|
2016-01-26 12:21:26 +08:00
|
|
|
|
2020-10-07 21:02:39 +08:00
|
|
|
/**
|
|
|
|
* update_devfreq() - Reevaluate the device and configure frequency.
|
|
|
|
* @devfreq: the devfreq instance.
|
|
|
|
*
|
|
|
|
* Note: Lock devfreq->lock before calling update_devfreq
|
|
|
|
* This function is exported for governors.
|
|
|
|
*/
|
|
|
|
int update_devfreq(struct devfreq *devfreq)
|
|
|
|
{
|
|
|
|
return devfreq_update_target(devfreq, 0L);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
}
|
2012-10-30 04:01:42 +08:00
|
|
|
EXPORT_SYMBOL(update_devfreq);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
2012-10-26 07:50:09 +08:00
|
|
|
/**
|
|
|
|
* devfreq_monitor() - Periodically poll devfreq objects.
|
|
|
|
* @work: the work struct used to run devfreq_monitor periodically.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void devfreq_monitor(struct work_struct *work)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
struct devfreq *devfreq = container_of(work,
|
|
|
|
struct devfreq, work.work);
|
|
|
|
|
|
|
|
mutex_lock(&devfreq->lock);
|
|
|
|
err = update_devfreq(devfreq);
|
|
|
|
if (err)
|
|
|
|
dev_err(&devfreq->dev, "dvfs failed with (%d) error\n", err);
|
|
|
|
|
|
|
|
queue_delayed_work(devfreq_wq, &devfreq->work,
|
|
|
|
msecs_to_jiffies(devfreq->profile->polling_ms));
|
|
|
|
mutex_unlock(&devfreq->lock);
|
2019-02-19 02:21:09 +08:00
|
|
|
|
|
|
|
trace_devfreq_monitor(devfreq);
|
2012-10-26 07:50:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* devfreq_monitor_start() - Start load monitoring of devfreq instance
|
|
|
|
* @devfreq: the devfreq instance.
|
|
|
|
*
|
2019-05-03 02:27:36 +08:00
|
|
|
* Helper function for starting devfreq device load monitoring. By
|
2012-10-26 07:50:09 +08:00
|
|
|
* default delayed work based monitoring is supported. Function
|
|
|
|
* to be called from governor in response to DEVFREQ_GOV_START
|
|
|
|
* event when device is added to devfreq framework.
|
|
|
|
*/
|
|
|
|
void devfreq_monitor_start(struct devfreq *devfreq)
|
|
|
|
{
|
2020-10-05 13:48:01 +08:00
|
|
|
if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
|
2019-11-05 05:56:14 +08:00
|
|
|
return;
|
|
|
|
|
2020-07-02 19:41:28 +08:00
|
|
|
switch (devfreq->profile->timer) {
|
|
|
|
case DEVFREQ_TIMER_DEFERRABLE:
|
|
|
|
INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
|
|
|
|
break;
|
|
|
|
case DEVFREQ_TIMER_DELAYED:
|
|
|
|
INIT_DELAYED_WORK(&devfreq->work, devfreq_monitor);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-26 07:50:09 +08:00
|
|
|
if (devfreq->profile->polling_ms)
|
|
|
|
queue_delayed_work(devfreq_wq, &devfreq->work,
|
|
|
|
msecs_to_jiffies(devfreq->profile->polling_ms));
|
|
|
|
}
|
2012-11-29 03:29:17 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_monitor_start);
|
2012-10-26 07:50:09 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* devfreq_monitor_stop() - Stop load monitoring of a devfreq instance
|
|
|
|
* @devfreq: the devfreq instance.
|
|
|
|
*
|
2019-05-03 02:27:36 +08:00
|
|
|
* Helper function to stop devfreq device load monitoring. Function
|
2012-10-26 07:50:09 +08:00
|
|
|
* to be called from governor in response to DEVFREQ_GOV_STOP
|
|
|
|
* event when device is removed from devfreq framework.
|
|
|
|
*/
|
|
|
|
void devfreq_monitor_stop(struct devfreq *devfreq)
|
|
|
|
{
|
2020-10-05 13:48:01 +08:00
|
|
|
if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
|
2019-11-05 05:56:14 +08:00
|
|
|
return;
|
|
|
|
|
2012-10-26 07:50:09 +08:00
|
|
|
cancel_delayed_work_sync(&devfreq->work);
|
|
|
|
}
|
2012-11-29 03:29:17 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_monitor_stop);
|
2012-10-26 07:50:09 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* devfreq_monitor_suspend() - Suspend load monitoring of a devfreq instance
|
|
|
|
* @devfreq: the devfreq instance.
|
|
|
|
*
|
2019-05-03 02:27:36 +08:00
|
|
|
* Helper function to suspend devfreq device load monitoring. Function
|
2012-10-26 07:50:09 +08:00
|
|
|
* to be called from governor in response to DEVFREQ_GOV_SUSPEND
|
|
|
|
* event or when polling interval is set to zero.
|
|
|
|
*
|
|
|
|
* Note: Though this function is same as devfreq_monitor_stop(),
|
|
|
|
* intentionally kept separate to provide hooks for collecting
|
|
|
|
* transition statistics.
|
|
|
|
*/
|
|
|
|
void devfreq_monitor_suspend(struct devfreq *devfreq)
|
|
|
|
{
|
|
|
|
mutex_lock(&devfreq->lock);
|
|
|
|
if (devfreq->stop_polling) {
|
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-01-08 13:50:39 +08:00
|
|
|
devfreq_update_status(devfreq, devfreq->previous_freq);
|
2012-10-26 07:50:09 +08:00
|
|
|
devfreq->stop_polling = true;
|
|
|
|
mutex_unlock(&devfreq->lock);
|
2019-11-05 05:56:14 +08:00
|
|
|
|
2020-10-05 13:48:01 +08:00
|
|
|
if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
|
2019-11-05 05:56:14 +08:00
|
|
|
return;
|
|
|
|
|
2012-10-26 07:50:09 +08:00
|
|
|
cancel_delayed_work_sync(&devfreq->work);
|
|
|
|
}
|
2012-11-29 03:29:17 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_monitor_suspend);
|
2012-10-26 07:50:09 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* devfreq_monitor_resume() - Resume load monitoring of a devfreq instance
|
|
|
|
* @devfreq: the devfreq instance.
|
|
|
|
*
|
2019-05-03 02:27:36 +08:00
|
|
|
* Helper function to resume devfreq device load monitoring. Function
|
2012-10-26 07:50:09 +08:00
|
|
|
* to be called from governor in response to DEVFREQ_GOV_RESUME
|
|
|
|
* event or when polling interval is set to non-zero.
|
|
|
|
*/
|
|
|
|
void devfreq_monitor_resume(struct devfreq *devfreq)
|
|
|
|
{
|
2013-01-08 13:50:39 +08:00
|
|
|
unsigned long freq;
|
|
|
|
|
2012-10-26 07:50:09 +08:00
|
|
|
mutex_lock(&devfreq->lock);
|
|
|
|
|
2020-10-05 13:48:01 +08:00
|
|
|
if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
|
2019-11-05 05:56:14 +08:00
|
|
|
goto out_update;
|
|
|
|
|
2020-10-05 13:48:01 +08:00
|
|
|
if (!devfreq->stop_polling)
|
|
|
|
goto out;
|
|
|
|
|
2012-10-26 07:50:09 +08:00
|
|
|
if (!delayed_work_pending(&devfreq->work) &&
|
|
|
|
devfreq->profile->polling_ms)
|
|
|
|
queue_delayed_work(devfreq_wq, &devfreq->work,
|
|
|
|
msecs_to_jiffies(devfreq->profile->polling_ms));
|
2013-01-08 13:50:39 +08:00
|
|
|
|
2019-11-05 05:56:14 +08:00
|
|
|
out_update:
|
2019-12-06 12:46:39 +08:00
|
|
|
devfreq->stats.last_update = get_jiffies_64();
|
2012-10-26 07:50:09 +08:00
|
|
|
devfreq->stop_polling = false;
|
|
|
|
|
2013-01-08 13:50:39 +08:00
|
|
|
if (devfreq->profile->get_cur_freq &&
|
|
|
|
!devfreq->profile->get_cur_freq(devfreq->dev.parent, &freq))
|
|
|
|
devfreq->previous_freq = freq;
|
|
|
|
|
2012-10-26 07:50:09 +08:00
|
|
|
out:
|
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
}
|
2012-11-29 03:29:17 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_monitor_resume);
|
2012-10-26 07:50:09 +08:00
|
|
|
|
|
|
|
/**
|
2020-01-29 12:24:18 +08:00
|
|
|
* devfreq_update_interval() - Update device devfreq monitoring interval
|
2012-10-26 07:50:09 +08:00
|
|
|
* @devfreq: the devfreq instance.
|
|
|
|
* @delay: new polling interval to be set.
|
|
|
|
*
|
|
|
|
* Helper function to set new load monitoring polling interval. Function
|
2020-01-29 12:24:18 +08:00
|
|
|
* to be called from governor in response to DEVFREQ_GOV_UPDATE_INTERVAL event.
|
2012-10-26 07:50:09 +08:00
|
|
|
*/
|
2020-01-29 12:24:18 +08:00
|
|
|
void devfreq_update_interval(struct devfreq *devfreq, unsigned int *delay)
|
2012-10-26 07:50:09 +08:00
|
|
|
{
|
|
|
|
unsigned int cur_delay = devfreq->profile->polling_ms;
|
|
|
|
unsigned int new_delay = *delay;
|
|
|
|
|
|
|
|
mutex_lock(&devfreq->lock);
|
|
|
|
devfreq->profile->polling_ms = new_delay;
|
|
|
|
|
2020-10-05 13:48:01 +08:00
|
|
|
if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
|
2012-10-26 07:50:09 +08:00
|
|
|
goto out;
|
|
|
|
|
2020-10-05 13:48:01 +08:00
|
|
|
if (devfreq->stop_polling)
|
2019-11-05 05:56:14 +08:00
|
|
|
goto out;
|
|
|
|
|
2012-10-26 07:50:09 +08:00
|
|
|
/* if new delay is zero, stop polling */
|
|
|
|
if (!new_delay) {
|
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
cancel_delayed_work_sync(&devfreq->work);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if current delay is zero, start polling with new delay */
|
|
|
|
if (!cur_delay) {
|
|
|
|
queue_delayed_work(devfreq_wq, &devfreq->work,
|
|
|
|
msecs_to_jiffies(devfreq->profile->polling_ms));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if current delay is greater than new delay, restart polling */
|
|
|
|
if (cur_delay > new_delay) {
|
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
cancel_delayed_work_sync(&devfreq->work);
|
|
|
|
mutex_lock(&devfreq->lock);
|
|
|
|
if (!devfreq->stop_polling)
|
|
|
|
queue_delayed_work(devfreq_wq, &devfreq->work,
|
2019-01-21 10:11:07 +08:00
|
|
|
msecs_to_jiffies(devfreq->profile->polling_ms));
|
2012-10-26 07:50:09 +08:00
|
|
|
}
|
|
|
|
out:
|
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
}
|
2020-01-29 12:24:18 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_update_interval);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* devfreq_notifier_call() - Notify that the device frequency requirements
|
2019-01-21 10:11:07 +08:00
|
|
|
* has been changed out of devfreq framework.
|
2012-10-26 07:50:35 +08:00
|
|
|
* @nb: the notifier_block (supposed to be devfreq->nb)
|
|
|
|
* @type: not used
|
|
|
|
* @devp: not used
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
*
|
|
|
|
* Called by a notifier that uses devfreq->nb.
|
|
|
|
*/
|
|
|
|
static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
|
|
|
|
void *devp)
|
|
|
|
{
|
|
|
|
struct devfreq *devfreq = container_of(nb, struct devfreq, nb);
|
2019-11-01 05:34:18 +08:00
|
|
|
int err = -EINVAL;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
|
|
|
mutex_lock(&devfreq->lock);
|
2017-10-23 09:32:08 +08:00
|
|
|
|
|
|
|
devfreq->scaling_min_freq = find_available_min_freq(devfreq);
|
2019-11-01 05:34:18 +08:00
|
|
|
if (!devfreq->scaling_min_freq)
|
|
|
|
goto out;
|
2017-10-23 09:32:08 +08:00
|
|
|
|
|
|
|
devfreq->scaling_max_freq = find_available_max_freq(devfreq);
|
2019-11-01 05:34:19 +08:00
|
|
|
if (!devfreq->scaling_max_freq) {
|
|
|
|
devfreq->scaling_max_freq = ULONG_MAX;
|
2019-11-01 05:34:18 +08:00
|
|
|
goto out;
|
2019-11-01 05:34:19 +08:00
|
|
|
}
|
2019-11-01 05:34:18 +08:00
|
|
|
|
|
|
|
err = update_devfreq(devfreq);
|
2017-10-23 09:32:08 +08:00
|
|
|
|
2019-11-01 05:34:18 +08:00
|
|
|
out:
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
mutex_unlock(&devfreq->lock);
|
2019-11-01 05:34:18 +08:00
|
|
|
if (err)
|
|
|
|
dev_err(devfreq->dev.parent,
|
|
|
|
"failed to update frequency from OPP notifier (%d)\n",
|
|
|
|
err);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
2019-11-01 05:34:18 +08:00
|
|
|
return NOTIFY_OK;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
}
|
|
|
|
|
2019-12-05 18:05:06 +08:00
|
|
|
/**
|
|
|
|
* qos_notifier_call() - Common handler for QoS constraints.
|
|
|
|
* @devfreq: the devfreq instance.
|
|
|
|
*/
|
|
|
|
static int qos_notifier_call(struct devfreq *devfreq)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
mutex_lock(&devfreq->lock);
|
|
|
|
err = update_devfreq(devfreq);
|
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
if (err)
|
|
|
|
dev_err(devfreq->dev.parent,
|
|
|
|
"failed to update frequency from PM QoS (%d)\n",
|
|
|
|
err);
|
|
|
|
|
|
|
|
return NOTIFY_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qos_min_notifier_call() - Callback for QoS min_freq changes.
|
|
|
|
* @nb: Should be devfreq->nb_min
|
|
|
|
*/
|
|
|
|
static int qos_min_notifier_call(struct notifier_block *nb,
|
|
|
|
unsigned long val, void *ptr)
|
|
|
|
{
|
|
|
|
return qos_notifier_call(container_of(nb, struct devfreq, nb_min));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qos_max_notifier_call() - Callback for QoS max_freq changes.
|
|
|
|
* @nb: Should be devfreq->nb_max
|
|
|
|
*/
|
|
|
|
static int qos_max_notifier_call(struct notifier_block *nb,
|
|
|
|
unsigned long val, void *ptr)
|
|
|
|
{
|
|
|
|
return qos_notifier_call(container_of(nb, struct devfreq, nb_max));
|
|
|
|
}
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
/**
|
2017-01-31 14:38:18 +08:00
|
|
|
* devfreq_dev_release() - Callback for struct device to release the device.
|
|
|
|
* @dev: the devfreq device
|
|
|
|
*
|
|
|
|
* Remove devfreq from the list and release its resources.
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
*/
|
2017-01-31 14:38:18 +08:00
|
|
|
static void devfreq_dev_release(struct device *dev)
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
{
|
2017-01-31 14:38:18 +08:00
|
|
|
struct devfreq *devfreq = to_devfreq(dev);
|
2019-12-05 18:05:06 +08:00
|
|
|
int err;
|
2017-01-31 14:38:18 +08:00
|
|
|
|
2012-10-26 07:50:09 +08:00
|
|
|
mutex_lock(&devfreq_list_lock);
|
|
|
|
list_del(&devfreq->node);
|
|
|
|
mutex_unlock(&devfreq_list_lock);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
2019-12-05 18:05:06 +08:00
|
|
|
err = dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_max,
|
|
|
|
DEV_PM_QOS_MAX_FREQUENCY);
|
|
|
|
if (err && err != -ENOENT)
|
|
|
|
dev_warn(dev->parent,
|
|
|
|
"Failed to remove max_freq notifier: %d\n", err);
|
|
|
|
err = dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_min,
|
|
|
|
DEV_PM_QOS_MIN_FREQUENCY);
|
|
|
|
if (err && err != -ENOENT)
|
|
|
|
dev_warn(dev->parent,
|
|
|
|
"Failed to remove min_freq notifier: %d\n", err);
|
|
|
|
|
2019-12-05 18:05:07 +08:00
|
|
|
if (dev_pm_qos_request_active(&devfreq->user_max_freq_req)) {
|
|
|
|
err = dev_pm_qos_remove_request(&devfreq->user_max_freq_req);
|
2020-03-12 23:36:06 +08:00
|
|
|
if (err < 0)
|
2019-12-05 18:05:07 +08:00
|
|
|
dev_warn(dev->parent,
|
|
|
|
"Failed to remove max_freq request: %d\n", err);
|
|
|
|
}
|
|
|
|
if (dev_pm_qos_request_active(&devfreq->user_min_freq_req)) {
|
|
|
|
err = dev_pm_qos_remove_request(&devfreq->user_min_freq_req);
|
2020-03-12 23:36:06 +08:00
|
|
|
if (err < 0)
|
2019-12-05 18:05:07 +08:00
|
|
|
dev_warn(dev->parent,
|
|
|
|
"Failed to remove min_freq request: %d\n", err);
|
|
|
|
}
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
if (devfreq->profile->exit)
|
|
|
|
devfreq->profile->exit(devfreq->dev.parent);
|
|
|
|
|
2021-02-04 16:14:23 +08:00
|
|
|
if (devfreq->opp_table)
|
|
|
|
dev_pm_opp_put_opp_table(devfreq->opp_table);
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
mutex_destroy(&devfreq->lock);
|
|
|
|
kfree(devfreq);
|
|
|
|
}
|
|
|
|
|
2020-07-03 16:20:27 +08:00
|
|
|
static void create_sysfs_files(struct devfreq *devfreq,
|
|
|
|
const struct devfreq_governor *gov);
|
|
|
|
static void remove_sysfs_files(struct devfreq *devfreq,
|
|
|
|
const struct devfreq_governor *gov);
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
/**
|
|
|
|
* devfreq_add_device() - Add devfreq feature to the device
|
|
|
|
* @dev: the device to add devfreq feature.
|
|
|
|
* @profile: device-specific profile to run devfreq.
|
2012-10-30 04:01:45 +08:00
|
|
|
* @governor_name: name of the policy to choose frequency.
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
* @data: private data for the governor. The devfreq framework does not
|
|
|
|
* touch this value.
|
|
|
|
*/
|
|
|
|
struct devfreq *devfreq_add_device(struct device *dev,
|
|
|
|
struct devfreq_dev_profile *profile,
|
2012-10-30 04:01:45 +08:00
|
|
|
const char *governor_name,
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
struct devfreq *devfreq;
|
2012-10-30 04:01:45 +08:00
|
|
|
struct devfreq_governor *governor;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
int err = 0;
|
|
|
|
|
2012-10-30 04:01:45 +08:00
|
|
|
if (!dev || !profile || !governor_name) {
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
dev_err(dev, "%s: Invalid parameters.\n", __func__);
|
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
}
|
|
|
|
|
2012-10-26 07:50:09 +08:00
|
|
|
mutex_lock(&devfreq_list_lock);
|
|
|
|
devfreq = find_device_devfreq(dev);
|
|
|
|
mutex_unlock(&devfreq_list_lock);
|
|
|
|
if (!IS_ERR(devfreq)) {
|
2019-09-19 08:09:46 +08:00
|
|
|
dev_err(dev, "%s: devfreq device already exists!\n",
|
2016-11-19 21:47:36 +08:00
|
|
|
__func__);
|
2012-10-26 07:50:09 +08:00
|
|
|
err = -EINVAL;
|
|
|
|
goto err_out;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL);
|
|
|
|
if (!devfreq) {
|
|
|
|
err = -ENOMEM;
|
2011-11-16 04:59:09 +08:00
|
|
|
goto err_out;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
mutex_init(&devfreq->lock);
|
|
|
|
mutex_lock(&devfreq->lock);
|
|
|
|
devfreq->dev.parent = dev;
|
|
|
|
devfreq->dev.class = devfreq_class;
|
|
|
|
devfreq->dev.release = devfreq_dev_release;
|
2019-11-14 07:21:31 +08:00
|
|
|
INIT_LIST_HEAD(&devfreq->node);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
devfreq->profile = profile;
|
|
|
|
devfreq->previous_freq = profile->initial_freq;
|
2016-05-31 18:25:09 +08:00
|
|
|
devfreq->last_status.current_frequency = profile->initial_freq;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
devfreq->data = data;
|
|
|
|
devfreq->nb.notifier_call = devfreq_notifier_call;
|
|
|
|
|
2020-07-02 19:41:28 +08:00
|
|
|
if (devfreq->profile->timer < 0
|
|
|
|
|| devfreq->profile->timer >= DEVFREQ_TIMER_NUM) {
|
2021-03-15 17:31:23 +08:00
|
|
|
mutex_unlock(&devfreq->lock);
|
2021-05-14 14:48:43 +08:00
|
|
|
err = -EINVAL;
|
2021-03-15 17:31:23 +08:00
|
|
|
goto err_dev;
|
2020-07-02 19:41:28 +08:00
|
|
|
}
|
|
|
|
|
2015-11-18 13:49:02 +08:00
|
|
|
if (!devfreq->profile->max_state && !devfreq->profile->freq_table) {
|
|
|
|
mutex_unlock(&devfreq->lock);
|
2017-10-23 09:32:09 +08:00
|
|
|
err = set_freq_table(devfreq);
|
|
|
|
if (err < 0)
|
2019-01-20 00:04:54 +08:00
|
|
|
goto err_dev;
|
2015-11-18 13:49:02 +08:00
|
|
|
mutex_lock(&devfreq->lock);
|
|
|
|
}
|
|
|
|
|
2018-05-26 04:30:33 +08:00
|
|
|
devfreq->scaling_min_freq = find_available_min_freq(devfreq);
|
|
|
|
if (!devfreq->scaling_min_freq) {
|
2017-10-23 09:32:06 +08:00
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
err = -EINVAL;
|
|
|
|
goto err_dev;
|
|
|
|
}
|
|
|
|
|
2018-05-26 04:30:33 +08:00
|
|
|
devfreq->scaling_max_freq = find_available_max_freq(devfreq);
|
|
|
|
if (!devfreq->scaling_max_freq) {
|
2017-10-23 09:32:06 +08:00
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
err = -EINVAL;
|
|
|
|
goto err_dev;
|
|
|
|
}
|
|
|
|
|
2018-12-05 19:05:53 +08:00
|
|
|
devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
|
2021-02-04 16:14:23 +08:00
|
|
|
devfreq->opp_table = dev_pm_opp_get_opp_table(dev);
|
|
|
|
if (IS_ERR(devfreq->opp_table))
|
|
|
|
devfreq->opp_table = NULL;
|
|
|
|
|
2018-12-05 19:05:53 +08:00
|
|
|
atomic_set(&devfreq->suspend_count, 0);
|
|
|
|
|
2020-02-21 01:37:04 +08:00
|
|
|
dev_set_name(&devfreq->dev, "%s", dev_name(dev));
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
err = device_register(&devfreq->dev);
|
|
|
|
if (err) {
|
2012-10-26 07:50:09 +08:00
|
|
|
mutex_unlock(&devfreq->lock);
|
2018-03-30 19:44:03 +08:00
|
|
|
put_device(&devfreq->dev);
|
|
|
|
goto err_out;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
}
|
|
|
|
|
2019-12-06 12:46:39 +08:00
|
|
|
devfreq->stats.trans_table = devm_kzalloc(&devfreq->dev,
|
2019-01-21 10:11:07 +08:00
|
|
|
array3_size(sizeof(unsigned int),
|
|
|
|
devfreq->profile->max_state,
|
|
|
|
devfreq->profile->max_state),
|
|
|
|
GFP_KERNEL);
|
2019-12-06 12:46:39 +08:00
|
|
|
if (!devfreq->stats.trans_table) {
|
2019-01-20 00:04:53 +08:00
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
err = -ENOMEM;
|
|
|
|
goto err_devfreq;
|
|
|
|
}
|
|
|
|
|
2019-12-06 12:46:39 +08:00
|
|
|
devfreq->stats.time_in_state = devm_kcalloc(&devfreq->dev,
|
2019-01-21 10:11:07 +08:00
|
|
|
devfreq->profile->max_state,
|
2019-12-06 12:46:39 +08:00
|
|
|
sizeof(*devfreq->stats.time_in_state),
|
2019-01-21 10:11:07 +08:00
|
|
|
GFP_KERNEL);
|
2019-12-06 12:46:39 +08:00
|
|
|
if (!devfreq->stats.time_in_state) {
|
2019-01-20 00:04:53 +08:00
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
err = -ENOMEM;
|
|
|
|
goto err_devfreq;
|
|
|
|
}
|
|
|
|
|
2019-12-06 12:46:39 +08:00
|
|
|
devfreq->stats.total_trans = 0;
|
|
|
|
devfreq->stats.last_update = get_jiffies_64();
|
2015-10-02 11:39:23 +08:00
|
|
|
|
2016-01-26 12:21:26 +08:00
|
|
|
srcu_init_notifier_head(&devfreq->transition_notifier_list);
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
|
2019-12-05 18:05:07 +08:00
|
|
|
err = dev_pm_qos_add_request(dev, &devfreq->user_min_freq_req,
|
|
|
|
DEV_PM_QOS_MIN_FREQUENCY, 0);
|
|
|
|
if (err < 0)
|
|
|
|
goto err_devfreq;
|
|
|
|
err = dev_pm_qos_add_request(dev, &devfreq->user_max_freq_req,
|
|
|
|
DEV_PM_QOS_MAX_FREQUENCY,
|
|
|
|
PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
|
|
|
|
if (err < 0)
|
|
|
|
goto err_devfreq;
|
|
|
|
|
2019-12-05 18:05:06 +08:00
|
|
|
devfreq->nb_min.notifier_call = qos_min_notifier_call;
|
2020-12-16 10:25:38 +08:00
|
|
|
err = dev_pm_qos_add_notifier(dev, &devfreq->nb_min,
|
2019-12-05 18:05:06 +08:00
|
|
|
DEV_PM_QOS_MIN_FREQUENCY);
|
|
|
|
if (err)
|
|
|
|
goto err_devfreq;
|
|
|
|
|
|
|
|
devfreq->nb_max.notifier_call = qos_max_notifier_call;
|
2020-12-16 10:25:38 +08:00
|
|
|
err = dev_pm_qos_add_notifier(dev, &devfreq->nb_max,
|
2019-12-05 18:05:06 +08:00
|
|
|
DEV_PM_QOS_MAX_FREQUENCY);
|
|
|
|
if (err)
|
|
|
|
goto err_devfreq;
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
mutex_lock(&devfreq_list_lock);
|
|
|
|
|
2020-10-20 14:12:12 +08:00
|
|
|
governor = try_then_request_governor(governor_name);
|
2016-12-28 19:52:35 +08:00
|
|
|
if (IS_ERR(governor)) {
|
|
|
|
dev_err(dev, "%s: Unable to find governor for the device\n",
|
|
|
|
__func__);
|
|
|
|
err = PTR_ERR(governor);
|
|
|
|
goto err_init;
|
|
|
|
}
|
|
|
|
|
|
|
|
devfreq->governor = governor;
|
|
|
|
err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
|
|
|
|
NULL);
|
2012-10-26 07:50:09 +08:00
|
|
|
if (err) {
|
|
|
|
dev_err(dev, "%s: Unable to start governor for the device\n",
|
|
|
|
__func__);
|
|
|
|
goto err_init;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
}
|
2020-07-03 16:20:27 +08:00
|
|
|
create_sysfs_files(devfreq, devfreq->governor);
|
2018-07-04 16:45:50 +08:00
|
|
|
|
|
|
|
list_add(&devfreq->node, &devfreq_list);
|
|
|
|
|
2016-09-29 10:13:28 +08:00
|
|
|
mutex_unlock(&devfreq_list_lock);
|
2012-10-26 07:50:09 +08:00
|
|
|
|
2021-03-08 21:30:37 +08:00
|
|
|
if (devfreq->profile->is_cooling_device) {
|
|
|
|
devfreq->cdev = devfreq_cooling_em_register(devfreq, NULL);
|
|
|
|
if (IS_ERR(devfreq->cdev))
|
|
|
|
devfreq->cdev = NULL;
|
|
|
|
}
|
|
|
|
|
2011-11-16 04:59:09 +08:00
|
|
|
return devfreq;
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
err_init:
|
2016-09-29 10:13:28 +08:00
|
|
|
mutex_unlock(&devfreq_list_lock);
|
2019-01-20 00:04:53 +08:00
|
|
|
err_devfreq:
|
2018-09-03 08:02:07 +08:00
|
|
|
devfreq_remove_device(devfreq);
|
2018-03-30 19:44:03 +08:00
|
|
|
devfreq = NULL;
|
2017-08-24 09:42:48 +08:00
|
|
|
err_dev:
|
2018-09-21 21:18:43 +08:00
|
|
|
kfree(devfreq);
|
2011-11-16 04:59:09 +08:00
|
|
|
err_out:
|
|
|
|
return ERR_PTR(err);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
}
|
2012-10-26 07:50:09 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_add_device);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* devfreq_remove_device() - Remove devfreq feature from a device.
|
2012-10-26 07:50:35 +08:00
|
|
|
* @devfreq: the devfreq instance to be removed
|
2013-02-05 17:40:17 +08:00
|
|
|
*
|
|
|
|
* The opposite of devfreq_add_device().
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
*/
|
|
|
|
int devfreq_remove_device(struct devfreq *devfreq)
|
|
|
|
{
|
|
|
|
if (!devfreq)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2021-03-08 21:30:37 +08:00
|
|
|
devfreq_cooling_unregister(devfreq->cdev);
|
|
|
|
|
2020-07-03 16:20:27 +08:00
|
|
|
if (devfreq->governor) {
|
2018-09-03 08:02:07 +08:00
|
|
|
devfreq->governor->event_handler(devfreq,
|
|
|
|
DEVFREQ_GOV_STOP, NULL);
|
2020-07-03 16:20:27 +08:00
|
|
|
remove_sysfs_files(devfreq, devfreq->governor);
|
|
|
|
}
|
|
|
|
|
2014-05-09 15:43:07 +08:00
|
|
|
device_unregister(&devfreq->dev);
|
2011-11-15 06:31:29 +08:00
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2012-10-26 07:50:09 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_remove_device);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
2014-05-09 15:43:08 +08:00
|
|
|
static int devm_devfreq_dev_match(struct device *dev, void *res, void *data)
|
|
|
|
{
|
|
|
|
struct devfreq **r = res;
|
|
|
|
|
|
|
|
if (WARN_ON(!r || !*r))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return *r == data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void devm_devfreq_dev_release(struct device *dev, void *res)
|
|
|
|
{
|
|
|
|
devfreq_remove_device(*(struct devfreq **)res);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* devm_devfreq_add_device() - Resource-managed devfreq_add_device()
|
|
|
|
* @dev: the device to add devfreq feature.
|
|
|
|
* @profile: device-specific profile to run devfreq.
|
|
|
|
* @governor_name: name of the policy to choose frequency.
|
|
|
|
* @data: private data for the governor. The devfreq framework does not
|
|
|
|
* touch this value.
|
|
|
|
*
|
|
|
|
* This function manages automatically the memory of devfreq device using device
|
|
|
|
* resource management and simplify the free operation for memory of devfreq
|
|
|
|
* device.
|
|
|
|
*/
|
|
|
|
struct devfreq *devm_devfreq_add_device(struct device *dev,
|
|
|
|
struct devfreq_dev_profile *profile,
|
|
|
|
const char *governor_name,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
struct devfreq **ptr, *devfreq;
|
|
|
|
|
|
|
|
ptr = devres_alloc(devm_devfreq_dev_release, sizeof(*ptr), GFP_KERNEL);
|
|
|
|
if (!ptr)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
devfreq = devfreq_add_device(dev, profile, governor_name, data);
|
|
|
|
if (IS_ERR(devfreq)) {
|
|
|
|
devres_free(ptr);
|
2017-11-06 13:27:41 +08:00
|
|
|
return devfreq;
|
2014-05-09 15:43:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
*ptr = devfreq;
|
|
|
|
devres_add(dev, ptr);
|
|
|
|
|
|
|
|
return devfreq;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devm_devfreq_add_device);
|
|
|
|
|
2015-11-10 19:31:07 +08:00
|
|
|
#ifdef CONFIG_OF
|
2020-09-08 18:24:45 +08:00
|
|
|
/*
|
|
|
|
* devfreq_get_devfreq_by_node - Get the devfreq device from devicetree
|
|
|
|
* @node - pointer to device_node
|
|
|
|
*
|
|
|
|
* return the instance of devfreq device
|
|
|
|
*/
|
|
|
|
struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node)
|
|
|
|
{
|
|
|
|
struct devfreq *devfreq;
|
|
|
|
|
|
|
|
if (!node)
|
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
|
|
|
|
mutex_lock(&devfreq_list_lock);
|
|
|
|
list_for_each_entry(devfreq, &devfreq_list, node) {
|
|
|
|
if (devfreq->dev.parent
|
|
|
|
&& devfreq->dev.parent->of_node == node) {
|
|
|
|
mutex_unlock(&devfreq_list_lock);
|
|
|
|
return devfreq;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mutex_unlock(&devfreq_list_lock);
|
|
|
|
|
|
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
}
|
|
|
|
|
2015-11-10 19:31:07 +08:00
|
|
|
/*
|
|
|
|
* devfreq_get_devfreq_by_phandle - Get the devfreq device from devicetree
|
|
|
|
* @dev - instance to the given device
|
2020-09-08 18:24:46 +08:00
|
|
|
* @phandle_name - name of property holding a phandle value
|
2015-11-10 19:31:07 +08:00
|
|
|
* @index - index into list of devfreq
|
|
|
|
*
|
|
|
|
* return the instance of devfreq device
|
|
|
|
*/
|
2020-09-08 18:24:46 +08:00
|
|
|
struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
|
|
|
|
const char *phandle_name, int index)
|
2015-11-10 19:31:07 +08:00
|
|
|
{
|
|
|
|
struct device_node *node;
|
|
|
|
struct devfreq *devfreq;
|
|
|
|
|
2020-09-08 18:24:46 +08:00
|
|
|
if (!dev || !phandle_name)
|
2015-11-10 19:31:07 +08:00
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
|
|
|
|
if (!dev->of_node)
|
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
|
2020-09-08 18:24:46 +08:00
|
|
|
node = of_parse_phandle(dev->of_node, phandle_name, index);
|
2015-11-10 19:31:07 +08:00
|
|
|
if (!node)
|
|
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
|
2020-09-08 18:24:45 +08:00
|
|
|
devfreq = devfreq_get_devfreq_by_node(node);
|
2016-07-01 17:42:00 +08:00
|
|
|
of_node_put(node);
|
2015-11-10 19:31:07 +08:00
|
|
|
|
2020-09-08 18:24:45 +08:00
|
|
|
return devfreq;
|
2015-11-10 19:31:07 +08:00
|
|
|
}
|
2020-09-08 18:24:45 +08:00
|
|
|
|
2015-11-10 19:31:07 +08:00
|
|
|
#else
|
2020-09-08 18:24:45 +08:00
|
|
|
struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node)
|
|
|
|
{
|
|
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
}
|
|
|
|
|
2020-09-08 18:24:46 +08:00
|
|
|
struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
|
|
|
|
const char *phandle_name, int index)
|
2015-11-10 19:31:07 +08:00
|
|
|
{
|
|
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_OF */
|
2020-09-08 18:24:45 +08:00
|
|
|
EXPORT_SYMBOL_GPL(devfreq_get_devfreq_by_node);
|
2015-11-10 19:31:07 +08:00
|
|
|
EXPORT_SYMBOL_GPL(devfreq_get_devfreq_by_phandle);
|
|
|
|
|
2014-05-09 15:43:08 +08:00
|
|
|
/**
|
|
|
|
* devm_devfreq_remove_device() - Resource-managed devfreq_remove_device()
|
2019-07-25 02:59:53 +08:00
|
|
|
* @dev: the device from which to remove devfreq feature.
|
2014-05-09 15:43:08 +08:00
|
|
|
* @devfreq: the devfreq instance to be removed
|
|
|
|
*/
|
|
|
|
void devm_devfreq_remove_device(struct device *dev, struct devfreq *devfreq)
|
|
|
|
{
|
|
|
|
WARN_ON(devres_release(dev, devm_devfreq_dev_release,
|
|
|
|
devm_devfreq_dev_match, devfreq));
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devm_devfreq_remove_device);
|
|
|
|
|
2012-10-26 07:50:18 +08:00
|
|
|
/**
|
|
|
|
* devfreq_suspend_device() - Suspend devfreq of a device.
|
|
|
|
* @devfreq: the devfreq instance to be suspended
|
2013-02-05 17:40:17 +08:00
|
|
|
*
|
|
|
|
* This function is intended to be called by the pm callbacks
|
|
|
|
* (e.g., runtime_suspend, suspend) of the device driver that
|
|
|
|
* holds the devfreq.
|
2012-10-26 07:50:18 +08:00
|
|
|
*/
|
|
|
|
int devfreq_suspend_device(struct devfreq *devfreq)
|
|
|
|
{
|
2018-12-05 19:05:53 +08:00
|
|
|
int ret;
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
if (!devfreq)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2018-12-05 19:05:53 +08:00
|
|
|
if (atomic_inc_return(&devfreq->suspend_count) > 1)
|
2012-10-30 04:01:45 +08:00
|
|
|
return 0;
|
|
|
|
|
2018-12-05 19:05:53 +08:00
|
|
|
if (devfreq->governor) {
|
|
|
|
ret = devfreq->governor->event_handler(devfreq,
|
|
|
|
DEVFREQ_GOV_SUSPEND, NULL);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (devfreq->suspend_freq) {
|
2019-11-12 18:47:34 +08:00
|
|
|
mutex_lock(&devfreq->lock);
|
2018-12-05 19:05:53 +08:00
|
|
|
ret = devfreq_set_target(devfreq, devfreq->suspend_freq, 0);
|
2019-11-12 18:47:34 +08:00
|
|
|
mutex_unlock(&devfreq->lock);
|
2018-12-05 19:05:53 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2012-10-26 07:50:18 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devfreq_suspend_device);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* devfreq_resume_device() - Resume devfreq of a device.
|
|
|
|
* @devfreq: the devfreq instance to be resumed
|
2013-02-05 17:40:17 +08:00
|
|
|
*
|
|
|
|
* This function is intended to be called by the pm callbacks
|
|
|
|
* (e.g., runtime_resume, resume) of the device driver that
|
|
|
|
* holds the devfreq.
|
2012-10-26 07:50:18 +08:00
|
|
|
*/
|
|
|
|
int devfreq_resume_device(struct devfreq *devfreq)
|
|
|
|
{
|
2018-12-05 19:05:53 +08:00
|
|
|
int ret;
|
|
|
|
|
2012-10-26 07:50:18 +08:00
|
|
|
if (!devfreq)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2018-12-05 19:05:53 +08:00
|
|
|
if (atomic_dec_return(&devfreq->suspend_count) >= 1)
|
2012-10-30 04:01:45 +08:00
|
|
|
return 0;
|
|
|
|
|
2018-12-05 19:05:53 +08:00
|
|
|
if (devfreq->resume_freq) {
|
2019-11-12 18:47:34 +08:00
|
|
|
mutex_lock(&devfreq->lock);
|
2018-12-05 19:05:53 +08:00
|
|
|
ret = devfreq_set_target(devfreq, devfreq->resume_freq, 0);
|
2019-11-12 18:47:34 +08:00
|
|
|
mutex_unlock(&devfreq->lock);
|
2018-12-05 19:05:53 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (devfreq->governor) {
|
|
|
|
ret = devfreq->governor->event_handler(devfreq,
|
|
|
|
DEVFREQ_GOV_RESUME, NULL);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2012-10-26 07:50:18 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devfreq_resume_device);
|
|
|
|
|
2018-12-05 19:05:54 +08:00
|
|
|
/**
|
|
|
|
* devfreq_suspend() - Suspend devfreq governors and devices
|
|
|
|
*
|
|
|
|
* Called during system wide Suspend/Hibernate cycles for suspending governors
|
|
|
|
* and devices preserving the state for resume. On some platforms the devfreq
|
|
|
|
* device must have precise state (frequency) after resume in order to provide
|
|
|
|
* fully operating setup.
|
|
|
|
*/
|
|
|
|
void devfreq_suspend(void)
|
|
|
|
{
|
|
|
|
struct devfreq *devfreq;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
mutex_lock(&devfreq_list_lock);
|
|
|
|
list_for_each_entry(devfreq, &devfreq_list, node) {
|
|
|
|
ret = devfreq_suspend_device(devfreq);
|
|
|
|
if (ret)
|
|
|
|
dev_err(&devfreq->dev,
|
|
|
|
"failed to suspend devfreq device\n");
|
|
|
|
}
|
|
|
|
mutex_unlock(&devfreq_list_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* devfreq_resume() - Resume devfreq governors and devices
|
|
|
|
*
|
|
|
|
* Called during system wide Suspend/Hibernate cycle for resuming governors and
|
|
|
|
* devices that are suspended with devfreq_suspend().
|
|
|
|
*/
|
|
|
|
void devfreq_resume(void)
|
|
|
|
{
|
|
|
|
struct devfreq *devfreq;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
mutex_lock(&devfreq_list_lock);
|
|
|
|
list_for_each_entry(devfreq, &devfreq_list, node) {
|
|
|
|
ret = devfreq_resume_device(devfreq);
|
|
|
|
if (ret)
|
|
|
|
dev_warn(&devfreq->dev,
|
|
|
|
"failed to resume devfreq device\n");
|
|
|
|
}
|
|
|
|
mutex_unlock(&devfreq_list_lock);
|
|
|
|
}
|
|
|
|
|
2012-10-30 04:01:43 +08:00
|
|
|
/**
|
|
|
|
* devfreq_add_governor() - Add devfreq governor
|
|
|
|
* @governor: the devfreq governor to be added
|
|
|
|
*/
|
|
|
|
int devfreq_add_governor(struct devfreq_governor *governor)
|
|
|
|
{
|
|
|
|
struct devfreq_governor *g;
|
2012-10-30 04:01:45 +08:00
|
|
|
struct devfreq *devfreq;
|
2012-10-30 04:01:43 +08:00
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
if (!governor) {
|
|
|
|
pr_err("%s: Invalid parameters.\n", __func__);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_lock(&devfreq_list_lock);
|
|
|
|
g = find_devfreq_governor(governor->name);
|
|
|
|
if (!IS_ERR(g)) {
|
|
|
|
pr_err("%s: governor %s already registered\n", __func__,
|
|
|
|
g->name);
|
|
|
|
err = -EINVAL;
|
|
|
|
goto err_out;
|
|
|
|
}
|
2011-11-15 06:31:29 +08:00
|
|
|
|
2012-10-30 04:01:43 +08:00
|
|
|
list_add(&governor->node, &devfreq_governor_list);
|
|
|
|
|
2012-10-30 04:01:45 +08:00
|
|
|
list_for_each_entry(devfreq, &devfreq_list, node) {
|
|
|
|
int ret = 0;
|
|
|
|
struct device *dev = devfreq->dev.parent;
|
|
|
|
|
2020-10-20 14:12:12 +08:00
|
|
|
if (!strncmp(devfreq->governor->name, governor->name,
|
2012-10-30 04:01:45 +08:00
|
|
|
DEVFREQ_NAME_LEN)) {
|
|
|
|
/* The following should never occur */
|
|
|
|
if (devfreq->governor) {
|
|
|
|
dev_warn(dev,
|
|
|
|
"%s: Governor %s already present\n",
|
|
|
|
__func__, devfreq->governor->name);
|
|
|
|
ret = devfreq->governor->event_handler(devfreq,
|
|
|
|
DEVFREQ_GOV_STOP, NULL);
|
|
|
|
if (ret) {
|
|
|
|
dev_warn(dev,
|
|
|
|
"%s: Governor %s stop = %d\n",
|
|
|
|
__func__,
|
|
|
|
devfreq->governor->name, ret);
|
|
|
|
}
|
|
|
|
/* Fall through */
|
|
|
|
}
|
|
|
|
devfreq->governor = governor;
|
|
|
|
ret = devfreq->governor->event_handler(devfreq,
|
|
|
|
DEVFREQ_GOV_START, NULL);
|
|
|
|
if (ret) {
|
|
|
|
dev_warn(dev, "%s: Governor %s start=%d\n",
|
|
|
|
__func__, devfreq->governor->name,
|
|
|
|
ret);
|
|
|
|
}
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-30 04:01:43 +08:00
|
|
|
err_out:
|
|
|
|
mutex_unlock(&devfreq_list_lock);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
2012-10-30 04:01:43 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devfreq_add_governor);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
2012-10-30 04:01:43 +08:00
|
|
|
/**
|
2016-11-09 09:29:14 +08:00
|
|
|
* devfreq_remove_governor() - Remove devfreq feature from a device.
|
2012-10-30 04:01:43 +08:00
|
|
|
* @governor: the devfreq governor to be removed
|
|
|
|
*/
|
|
|
|
int devfreq_remove_governor(struct devfreq_governor *governor)
|
|
|
|
{
|
|
|
|
struct devfreq_governor *g;
|
2012-10-30 04:01:45 +08:00
|
|
|
struct devfreq *devfreq;
|
2012-10-30 04:01:43 +08:00
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
if (!governor) {
|
|
|
|
pr_err("%s: Invalid parameters.\n", __func__);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_lock(&devfreq_list_lock);
|
|
|
|
g = find_devfreq_governor(governor->name);
|
|
|
|
if (IS_ERR(g)) {
|
|
|
|
pr_err("%s: governor %s not registered\n", __func__,
|
2012-11-21 13:06:13 +08:00
|
|
|
governor->name);
|
2012-11-21 13:06:14 +08:00
|
|
|
err = PTR_ERR(g);
|
2012-10-30 04:01:43 +08:00
|
|
|
goto err_out;
|
|
|
|
}
|
2012-10-30 04:01:45 +08:00
|
|
|
list_for_each_entry(devfreq, &devfreq_list, node) {
|
|
|
|
int ret;
|
|
|
|
struct device *dev = devfreq->dev.parent;
|
|
|
|
|
2020-10-20 14:12:12 +08:00
|
|
|
if (!strncmp(devfreq->governor->name, governor->name,
|
2012-10-30 04:01:45 +08:00
|
|
|
DEVFREQ_NAME_LEN)) {
|
|
|
|
/* we should have a devfreq governor! */
|
|
|
|
if (!devfreq->governor) {
|
|
|
|
dev_warn(dev, "%s: Governor %s NOT present\n",
|
|
|
|
__func__, governor->name);
|
|
|
|
continue;
|
|
|
|
/* Fall through */
|
|
|
|
}
|
|
|
|
ret = devfreq->governor->event_handler(devfreq,
|
|
|
|
DEVFREQ_GOV_STOP, NULL);
|
|
|
|
if (ret) {
|
|
|
|
dev_warn(dev, "%s: Governor %s stop=%d\n",
|
|
|
|
__func__, devfreq->governor->name,
|
|
|
|
ret);
|
|
|
|
}
|
|
|
|
devfreq->governor = NULL;
|
|
|
|
}
|
|
|
|
}
|
2012-10-30 04:01:43 +08:00
|
|
|
|
|
|
|
list_del(&governor->node);
|
|
|
|
err_out:
|
|
|
|
mutex_unlock(&devfreq_list_lock);
|
|
|
|
|
|
|
|
return err;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
}
|
2012-10-30 04:01:43 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_remove_governor);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
2019-11-05 17:18:03 +08:00
|
|
|
static ssize_t name_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
2020-07-13 16:31:12 +08:00
|
|
|
struct devfreq *df = to_devfreq(dev);
|
|
|
|
return sprintf(buf, "%s\n", dev_name(df->dev.parent));
|
2019-11-05 17:18:03 +08:00
|
|
|
}
|
|
|
|
static DEVICE_ATTR_RO(name);
|
|
|
|
|
2013-07-25 06:05:09 +08:00
|
|
|
static ssize_t governor_show(struct device *dev,
|
2011-10-02 06:19:28 +08:00
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
2020-07-13 16:31:12 +08:00
|
|
|
struct devfreq *df = to_devfreq(dev);
|
|
|
|
|
|
|
|
if (!df->governor)
|
2012-10-30 04:01:45 +08:00
|
|
|
return -EINVAL;
|
|
|
|
|
2020-07-13 16:31:12 +08:00
|
|
|
return sprintf(buf, "%s\n", df->governor->name);
|
2011-10-02 06:19:28 +08:00
|
|
|
}
|
|
|
|
|
2013-07-25 06:05:09 +08:00
|
|
|
static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
|
2012-10-30 04:01:47 +08:00
|
|
|
const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
struct devfreq *df = to_devfreq(dev);
|
|
|
|
int ret;
|
|
|
|
char str_governor[DEVFREQ_NAME_LEN + 1];
|
2019-03-11 18:06:30 +08:00
|
|
|
const struct devfreq_governor *governor, *prev_governor;
|
2012-10-30 04:01:47 +08:00
|
|
|
|
2020-07-13 16:31:12 +08:00
|
|
|
if (!df->governor)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2012-10-30 04:01:47 +08:00
|
|
|
ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
|
|
|
|
if (ret != 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
mutex_lock(&devfreq_list_lock);
|
2018-07-04 16:45:50 +08:00
|
|
|
governor = try_then_request_governor(str_governor);
|
2012-10-30 04:01:47 +08:00
|
|
|
if (IS_ERR(governor)) {
|
|
|
|
ret = PTR_ERR(governor);
|
|
|
|
goto out;
|
|
|
|
}
|
2015-09-22 02:23:52 +08:00
|
|
|
if (df->governor == governor) {
|
|
|
|
ret = 0;
|
2012-10-30 04:01:47 +08:00
|
|
|
goto out;
|
2020-10-05 13:48:01 +08:00
|
|
|
} else if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)
|
|
|
|
|| IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE)) {
|
2017-01-31 14:38:16 +08:00
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
2015-09-22 02:23:52 +08:00
|
|
|
}
|
2012-10-30 04:01:47 +08:00
|
|
|
|
2020-07-03 16:20:27 +08:00
|
|
|
/*
|
|
|
|
* Stop the current governor and remove the specific sysfs files
|
|
|
|
* which depend on current governor.
|
|
|
|
*/
|
2020-07-13 16:31:12 +08:00
|
|
|
ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
|
|
|
|
if (ret) {
|
|
|
|
dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
|
|
|
|
__func__, df->governor->name, ret);
|
|
|
|
goto out;
|
2012-10-30 04:01:47 +08:00
|
|
|
}
|
2020-07-03 16:20:27 +08:00
|
|
|
remove_sysfs_files(df, df->governor);
|
2020-07-13 16:31:12 +08:00
|
|
|
|
2020-07-03 16:20:27 +08:00
|
|
|
/*
|
|
|
|
* Start the new governor and create the specific sysfs files
|
|
|
|
* which depend on the new governor.
|
|
|
|
*/
|
2019-03-11 18:06:30 +08:00
|
|
|
prev_governor = df->governor;
|
2012-10-30 04:01:47 +08:00
|
|
|
df->governor = governor;
|
|
|
|
ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
|
2019-03-11 18:06:30 +08:00
|
|
|
if (ret) {
|
2012-10-30 04:01:47 +08:00
|
|
|
dev_warn(dev, "%s: Governor %s not started(%d)\n",
|
|
|
|
__func__, df->governor->name, ret);
|
2020-07-03 16:20:27 +08:00
|
|
|
|
|
|
|
/* Restore previous governor */
|
2019-03-11 18:06:30 +08:00
|
|
|
df->governor = prev_governor;
|
|
|
|
ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
|
|
|
|
if (ret) {
|
|
|
|
dev_err(dev,
|
|
|
|
"%s: reverting to Governor %s failed (%d)\n",
|
2020-10-20 14:12:12 +08:00
|
|
|
__func__, prev_governor->name, ret);
|
2019-03-11 18:06:30 +08:00
|
|
|
df->governor = NULL;
|
2020-07-03 16:20:27 +08:00
|
|
|
goto out;
|
2019-03-11 18:06:30 +08:00
|
|
|
}
|
|
|
|
}
|
2020-07-03 16:20:27 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the sysfs files for the new governor. But if failed to start
|
|
|
|
* the new governor, restore the sysfs files of previous governor.
|
|
|
|
*/
|
|
|
|
create_sysfs_files(df, df->governor);
|
|
|
|
|
2012-10-30 04:01:47 +08:00
|
|
|
out:
|
|
|
|
mutex_unlock(&devfreq_list_lock);
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
ret = count;
|
|
|
|
return ret;
|
|
|
|
}
|
2013-07-25 06:05:09 +08:00
|
|
|
static DEVICE_ATTR_RW(governor);
|
|
|
|
|
|
|
|
static ssize_t available_governors_show(struct device *d,
|
|
|
|
struct device_attribute *attr,
|
|
|
|
char *buf)
|
2012-10-30 04:01:48 +08:00
|
|
|
{
|
2017-01-31 14:38:16 +08:00
|
|
|
struct devfreq *df = to_devfreq(d);
|
2012-10-30 04:01:48 +08:00
|
|
|
ssize_t count = 0;
|
|
|
|
|
2020-07-13 16:31:12 +08:00
|
|
|
if (!df->governor)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2012-10-30 04:01:48 +08:00
|
|
|
mutex_lock(&devfreq_list_lock);
|
2017-01-31 14:38:16 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The devfreq with immutable governor (e.g., passive) shows
|
|
|
|
* only own governor.
|
|
|
|
*/
|
2020-10-05 13:48:01 +08:00
|
|
|
if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)) {
|
2017-01-31 14:38:16 +08:00
|
|
|
count = scnprintf(&buf[count], DEVFREQ_NAME_LEN,
|
2020-10-20 14:12:12 +08:00
|
|
|
"%s ", df->governor->name);
|
2017-01-31 14:38:16 +08:00
|
|
|
/*
|
|
|
|
* The devfreq device shows the registered governor except for
|
|
|
|
* immutable governors such as passive governor .
|
|
|
|
*/
|
|
|
|
} else {
|
|
|
|
struct devfreq_governor *governor;
|
|
|
|
|
|
|
|
list_for_each_entry(governor, &devfreq_governor_list, node) {
|
2020-10-05 13:48:01 +08:00
|
|
|
if (IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE))
|
2017-01-31 14:38:16 +08:00
|
|
|
continue;
|
|
|
|
count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
|
|
|
|
"%s ", governor->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-30 04:01:48 +08:00
|
|
|
mutex_unlock(&devfreq_list_lock);
|
|
|
|
|
|
|
|
/* Truncate the trailing space */
|
|
|
|
if (count)
|
|
|
|
count--;
|
|
|
|
|
|
|
|
count += sprintf(&buf[count], "\n");
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
2013-07-25 06:05:09 +08:00
|
|
|
static DEVICE_ATTR_RO(available_governors);
|
2012-10-30 04:01:47 +08:00
|
|
|
|
2013-07-25 06:05:09 +08:00
|
|
|
static ssize_t cur_freq_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
2012-10-26 07:50:26 +08:00
|
|
|
{
|
|
|
|
unsigned long freq;
|
2020-07-13 16:31:12 +08:00
|
|
|
struct devfreq *df = to_devfreq(dev);
|
2012-10-26 07:50:26 +08:00
|
|
|
|
2020-07-13 16:31:12 +08:00
|
|
|
if (!df->profile)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (df->profile->get_cur_freq &&
|
|
|
|
!df->profile->get_cur_freq(df->dev.parent, &freq))
|
2016-11-19 21:47:36 +08:00
|
|
|
return sprintf(buf, "%lu\n", freq);
|
2012-10-26 07:50:26 +08:00
|
|
|
|
2020-07-13 16:31:12 +08:00
|
|
|
return sprintf(buf, "%lu\n", df->previous_freq);
|
2012-10-26 07:50:26 +08:00
|
|
|
}
|
2013-07-25 06:05:09 +08:00
|
|
|
static DEVICE_ATTR_RO(cur_freq);
|
2012-10-26 07:50:26 +08:00
|
|
|
|
2013-07-25 06:05:09 +08:00
|
|
|
static ssize_t target_freq_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
2011-10-02 06:19:28 +08:00
|
|
|
{
|
2020-07-13 16:31:12 +08:00
|
|
|
struct devfreq *df = to_devfreq(dev);
|
|
|
|
|
|
|
|
return sprintf(buf, "%lu\n", df->previous_freq);
|
2011-10-02 06:19:28 +08:00
|
|
|
}
|
2013-07-25 06:05:09 +08:00
|
|
|
static DEVICE_ATTR_RO(target_freq);
|
2011-10-02 06:19:28 +08:00
|
|
|
|
2013-07-25 06:05:09 +08:00
|
|
|
static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
|
2011-12-09 15:42:19 +08:00
|
|
|
const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
struct devfreq *df = to_devfreq(dev);
|
|
|
|
unsigned long value;
|
|
|
|
int ret;
|
|
|
|
|
2019-12-05 18:05:07 +08:00
|
|
|
/*
|
|
|
|
* Protect against theoretical sysfs writes between
|
|
|
|
* device_add and dev_pm_qos_add_request
|
|
|
|
*/
|
|
|
|
if (!dev_pm_qos_request_active(&df->user_min_freq_req))
|
|
|
|
return -EAGAIN;
|
|
|
|
|
2011-12-09 15:42:19 +08:00
|
|
|
ret = sscanf(buf, "%lu", &value);
|
|
|
|
if (ret != 1)
|
2012-10-26 07:50:43 +08:00
|
|
|
return -EINVAL;
|
2011-12-09 15:42:19 +08:00
|
|
|
|
2019-12-05 18:05:07 +08:00
|
|
|
/* Round down to kHz for PM QoS */
|
|
|
|
ret = dev_pm_qos_update_request(&df->user_min_freq_req,
|
|
|
|
value / HZ_PER_KHZ);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
2019-11-01 05:34:26 +08:00
|
|
|
|
|
|
|
return count;
|
2011-12-09 15:42:19 +08:00
|
|
|
}
|
|
|
|
|
2017-10-23 09:32:07 +08:00
|
|
|
static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
2017-10-23 09:32:08 +08:00
|
|
|
struct devfreq *df = to_devfreq(dev);
|
2019-11-01 05:34:26 +08:00
|
|
|
unsigned long min_freq, max_freq;
|
|
|
|
|
|
|
|
mutex_lock(&df->lock);
|
|
|
|
get_freq_range(df, &min_freq, &max_freq);
|
|
|
|
mutex_unlock(&df->lock);
|
2017-10-23 09:32:08 +08:00
|
|
|
|
2019-11-01 05:34:26 +08:00
|
|
|
return sprintf(buf, "%lu\n", min_freq);
|
2017-10-23 09:32:07 +08:00
|
|
|
}
|
2019-12-06 18:11:29 +08:00
|
|
|
static DEVICE_ATTR_RW(min_freq);
|
2017-10-23 09:32:07 +08:00
|
|
|
|
2013-07-25 06:05:09 +08:00
|
|
|
static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
|
2011-12-09 15:42:19 +08:00
|
|
|
const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
struct devfreq *df = to_devfreq(dev);
|
|
|
|
unsigned long value;
|
|
|
|
int ret;
|
|
|
|
|
2019-12-05 18:05:07 +08:00
|
|
|
/*
|
|
|
|
* Protect against theoretical sysfs writes between
|
|
|
|
* device_add and dev_pm_qos_add_request
|
|
|
|
*/
|
|
|
|
if (!dev_pm_qos_request_active(&df->user_max_freq_req))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2011-12-09 15:42:19 +08:00
|
|
|
ret = sscanf(buf, "%lu", &value);
|
|
|
|
if (ret != 1)
|
2012-10-26 07:50:43 +08:00
|
|
|
return -EINVAL;
|
2011-12-09 15:42:19 +08:00
|
|
|
|
2019-12-05 18:05:07 +08:00
|
|
|
/*
|
|
|
|
* PM QoS frequencies are in kHz so we need to convert. Convert by
|
|
|
|
* rounding upwards so that the acceptable interval never shrinks.
|
|
|
|
*
|
|
|
|
* For example if the user writes "666666666" to sysfs this value will
|
|
|
|
* be converted to 666667 kHz and back to 666667000 Hz before an OPP
|
|
|
|
* lookup, this ensures that an OPP of 666666666Hz is still accepted.
|
|
|
|
*
|
|
|
|
* A value of zero means "no limit".
|
|
|
|
*/
|
|
|
|
if (value)
|
|
|
|
value = DIV_ROUND_UP(value, HZ_PER_KHZ);
|
|
|
|
else
|
|
|
|
value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
|
2011-12-09 15:42:19 +08:00
|
|
|
|
2019-12-05 18:05:07 +08:00
|
|
|
ret = dev_pm_qos_update_request(&df->user_max_freq_req, value);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
2019-11-01 05:34:26 +08:00
|
|
|
|
|
|
|
return count;
|
2011-12-09 15:42:19 +08:00
|
|
|
}
|
|
|
|
|
2017-10-23 09:32:07 +08:00
|
|
|
static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
2017-10-23 09:32:08 +08:00
|
|
|
struct devfreq *df = to_devfreq(dev);
|
2019-11-01 05:34:26 +08:00
|
|
|
unsigned long min_freq, max_freq;
|
|
|
|
|
|
|
|
mutex_lock(&df->lock);
|
|
|
|
get_freq_range(df, &min_freq, &max_freq);
|
|
|
|
mutex_unlock(&df->lock);
|
2017-10-23 09:32:08 +08:00
|
|
|
|
2019-11-01 05:34:26 +08:00
|
|
|
return sprintf(buf, "%lu\n", max_freq);
|
2011-12-09 15:42:19 +08:00
|
|
|
}
|
2013-07-25 06:05:09 +08:00
|
|
|
static DEVICE_ATTR_RW(max_freq);
|
2011-12-09 15:42:19 +08:00
|
|
|
|
2013-07-25 06:05:09 +08:00
|
|
|
static ssize_t available_frequencies_show(struct device *d,
|
|
|
|
struct device_attribute *attr,
|
|
|
|
char *buf)
|
2012-10-26 08:48:59 +08:00
|
|
|
{
|
|
|
|
struct devfreq *df = to_devfreq(d);
|
|
|
|
ssize_t count = 0;
|
2017-10-23 09:32:10 +08:00
|
|
|
int i;
|
2012-10-26 08:48:59 +08:00
|
|
|
|
2020-07-13 16:31:12 +08:00
|
|
|
if (!df->profile)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2017-10-23 09:32:10 +08:00
|
|
|
mutex_lock(&df->lock);
|
2012-10-26 08:48:59 +08:00
|
|
|
|
2017-10-23 09:32:10 +08:00
|
|
|
for (i = 0; i < df->profile->max_state; i++)
|
2012-10-26 08:48:59 +08:00
|
|
|
count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
|
2017-10-23 09:32:10 +08:00
|
|
|
"%lu ", df->profile->freq_table[i]);
|
2012-10-26 08:48:59 +08:00
|
|
|
|
2017-10-23 09:32:10 +08:00
|
|
|
mutex_unlock(&df->lock);
|
2012-10-26 08:48:59 +08:00
|
|
|
/* Truncate the trailing space */
|
|
|
|
if (count)
|
|
|
|
count--;
|
|
|
|
|
|
|
|
count += sprintf(&buf[count], "\n");
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
2013-07-25 06:05:09 +08:00
|
|
|
static DEVICE_ATTR_RO(available_frequencies);
|
2012-10-26 08:48:59 +08:00
|
|
|
|
2013-07-25 06:05:09 +08:00
|
|
|
static ssize_t trans_stat_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
2012-08-23 19:00:46 +08:00
|
|
|
{
|
2020-07-13 16:31:12 +08:00
|
|
|
struct devfreq *df = to_devfreq(dev);
|
2012-08-23 19:00:46 +08:00
|
|
|
ssize_t len;
|
2013-01-08 13:50:39 +08:00
|
|
|
int i, j;
|
2020-07-13 16:31:12 +08:00
|
|
|
unsigned int max_state;
|
|
|
|
|
|
|
|
if (!df->profile)
|
|
|
|
return -EINVAL;
|
|
|
|
max_state = df->profile->max_state;
|
2012-08-23 19:00:46 +08:00
|
|
|
|
2015-11-23 14:45:36 +08:00
|
|
|
if (max_state == 0)
|
|
|
|
return sprintf(buf, "Not Supported.\n");
|
2012-08-23 19:00:46 +08:00
|
|
|
|
2020-07-13 16:31:12 +08:00
|
|
|
mutex_lock(&df->lock);
|
|
|
|
if (!df->stop_polling &&
|
|
|
|
devfreq_update_status(df, df->previous_freq)) {
|
|
|
|
mutex_unlock(&df->lock);
|
2019-09-24 15:52:23 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2020-07-13 16:31:12 +08:00
|
|
|
mutex_unlock(&df->lock);
|
2019-09-24 15:52:23 +08:00
|
|
|
|
2015-11-19 15:28:46 +08:00
|
|
|
len = sprintf(buf, " From : To\n");
|
|
|
|
len += sprintf(buf + len, " :");
|
2012-08-23 19:00:46 +08:00
|
|
|
for (i = 0; i < max_state; i++)
|
2015-11-19 15:28:46 +08:00
|
|
|
len += sprintf(buf + len, "%10lu",
|
2020-07-13 16:31:12 +08:00
|
|
|
df->profile->freq_table[i]);
|
2012-08-23 19:00:46 +08:00
|
|
|
|
|
|
|
len += sprintf(buf + len, " time(ms)\n");
|
|
|
|
|
|
|
|
for (i = 0; i < max_state; i++) {
|
2020-07-13 16:31:12 +08:00
|
|
|
if (df->profile->freq_table[i]
|
|
|
|
== df->previous_freq) {
|
2012-08-23 19:00:46 +08:00
|
|
|
len += sprintf(buf + len, "*");
|
|
|
|
} else {
|
|
|
|
len += sprintf(buf + len, " ");
|
|
|
|
}
|
2015-11-19 15:28:46 +08:00
|
|
|
len += sprintf(buf + len, "%10lu:",
|
2020-07-13 16:31:12 +08:00
|
|
|
df->profile->freq_table[i]);
|
2012-08-23 19:00:46 +08:00
|
|
|
for (j = 0; j < max_state; j++)
|
2015-11-19 15:28:46 +08:00
|
|
|
len += sprintf(buf + len, "%10u",
|
2020-07-13 16:31:12 +08:00
|
|
|
df->stats.trans_table[(i * max_state) + j]);
|
2019-12-06 12:46:39 +08:00
|
|
|
|
2019-12-05 22:55:25 +08:00
|
|
|
len += sprintf(buf + len, "%10llu\n", (u64)
|
2020-07-13 16:31:12 +08:00
|
|
|
jiffies64_to_msecs(df->stats.time_in_state[i]));
|
2012-08-23 19:00:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
len += sprintf(buf + len, "Total transition : %u\n",
|
2020-07-13 16:31:12 +08:00
|
|
|
df->stats.total_trans);
|
2012-08-23 19:00:46 +08:00
|
|
|
return len;
|
|
|
|
}
|
2019-12-05 22:55:26 +08:00
|
|
|
|
|
|
|
static ssize_t trans_stat_store(struct device *dev,
|
|
|
|
struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
struct devfreq *df = to_devfreq(dev);
|
|
|
|
int err, value;
|
|
|
|
|
2020-07-13 16:31:12 +08:00
|
|
|
if (!df->profile)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2019-12-05 22:55:26 +08:00
|
|
|
if (df->profile->max_state == 0)
|
|
|
|
return count;
|
|
|
|
|
|
|
|
err = kstrtoint(buf, 10, &value);
|
|
|
|
if (err || value != 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
mutex_lock(&df->lock);
|
2019-12-06 12:46:39 +08:00
|
|
|
memset(df->stats.time_in_state, 0, (df->profile->max_state *
|
|
|
|
sizeof(*df->stats.time_in_state)));
|
|
|
|
memset(df->stats.trans_table, 0, array3_size(sizeof(unsigned int),
|
2019-12-05 22:55:26 +08:00
|
|
|
df->profile->max_state,
|
|
|
|
df->profile->max_state));
|
2019-12-06 12:46:39 +08:00
|
|
|
df->stats.total_trans = 0;
|
|
|
|
df->stats.last_update = get_jiffies_64();
|
2019-12-05 22:55:26 +08:00
|
|
|
mutex_unlock(&df->lock);
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
static DEVICE_ATTR_RW(trans_stat);
|
2013-07-25 06:05:09 +08:00
|
|
|
|
2020-07-03 16:20:27 +08:00
|
|
|
static struct attribute *devfreq_attrs[] = {
|
|
|
|
&dev_attr_name.attr,
|
|
|
|
&dev_attr_governor.attr,
|
|
|
|
&dev_attr_available_governors.attr,
|
|
|
|
&dev_attr_cur_freq.attr,
|
|
|
|
&dev_attr_available_frequencies.attr,
|
|
|
|
&dev_attr_target_freq.attr,
|
|
|
|
&dev_attr_min_freq.attr,
|
|
|
|
&dev_attr_max_freq.attr,
|
|
|
|
&dev_attr_trans_stat.attr,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
ATTRIBUTE_GROUPS(devfreq);
|
|
|
|
|
|
|
|
static ssize_t polling_interval_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
struct devfreq *df = to_devfreq(dev);
|
|
|
|
|
|
|
|
if (!df->profile)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
return sprintf(buf, "%d\n", df->profile->polling_ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t polling_interval_store(struct device *dev,
|
|
|
|
struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
struct devfreq *df = to_devfreq(dev);
|
|
|
|
unsigned int value;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!df->governor)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
ret = sscanf(buf, "%u", &value);
|
|
|
|
if (ret != 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
df->governor->event_handler(df, DEVFREQ_GOV_UPDATE_INTERVAL, &value);
|
|
|
|
ret = count;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
static DEVICE_ATTR_RW(polling_interval);
|
|
|
|
|
2020-07-02 19:41:28 +08:00
|
|
|
static ssize_t timer_show(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
|
|
|
struct devfreq *df = to_devfreq(dev);
|
|
|
|
|
|
|
|
if (!df->profile)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
return sprintf(buf, "%s\n", timer_name[df->profile->timer]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t timer_store(struct device *dev, struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
struct devfreq *df = to_devfreq(dev);
|
|
|
|
char str_timer[DEVFREQ_NAME_LEN + 1];
|
|
|
|
int timer = -1;
|
|
|
|
int ret = 0, i;
|
|
|
|
|
|
|
|
if (!df->governor || !df->profile)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
ret = sscanf(buf, "%16s", str_timer);
|
|
|
|
if (ret != 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
for (i = 0; i < DEVFREQ_TIMER_NUM; i++) {
|
|
|
|
if (!strncmp(timer_name[i], str_timer, DEVFREQ_NAME_LEN)) {
|
|
|
|
timer = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (timer < 0) {
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (df->profile->timer == timer) {
|
|
|
|
ret = 0;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_lock(&df->lock);
|
|
|
|
df->profile->timer = timer;
|
|
|
|
mutex_unlock(&df->lock);
|
|
|
|
|
|
|
|
ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
|
|
|
|
if (ret) {
|
|
|
|
dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
|
|
|
|
__func__, df->governor->name, ret);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
|
|
|
|
if (ret)
|
|
|
|
dev_warn(dev, "%s: Governor %s not started(%d)\n",
|
|
|
|
__func__, df->governor->name, ret);
|
|
|
|
out:
|
|
|
|
return ret ? ret : count;
|
|
|
|
}
|
|
|
|
static DEVICE_ATTR_RW(timer);
|
|
|
|
|
2020-07-03 16:20:27 +08:00
|
|
|
#define CREATE_SYSFS_FILE(df, name) \
|
|
|
|
{ \
|
|
|
|
int ret; \
|
|
|
|
ret = sysfs_create_file(&df->dev.kobj, &dev_attr_##name.attr); \
|
|
|
|
if (ret < 0) { \
|
|
|
|
dev_warn(&df->dev, \
|
|
|
|
"Unable to create attr(%s)\n", "##name"); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
|
|
|
|
/* Create the specific sysfs files which depend on each governor. */
|
|
|
|
static void create_sysfs_files(struct devfreq *devfreq,
|
|
|
|
const struct devfreq_governor *gov)
|
|
|
|
{
|
|
|
|
if (IS_SUPPORTED_ATTR(gov->attrs, POLLING_INTERVAL))
|
|
|
|
CREATE_SYSFS_FILE(devfreq, polling_interval);
|
|
|
|
if (IS_SUPPORTED_ATTR(gov->attrs, TIMER))
|
|
|
|
CREATE_SYSFS_FILE(devfreq, timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove the specific sysfs files which depend on each governor. */
|
|
|
|
static void remove_sysfs_files(struct devfreq *devfreq,
|
|
|
|
const struct devfreq_governor *gov)
|
|
|
|
{
|
|
|
|
if (IS_SUPPORTED_ATTR(gov->attrs, POLLING_INTERVAL))
|
|
|
|
sysfs_remove_file(&devfreq->dev.kobj,
|
|
|
|
&dev_attr_polling_interval.attr);
|
|
|
|
if (IS_SUPPORTED_ATTR(gov->attrs, TIMER))
|
|
|
|
sysfs_remove_file(&devfreq->dev.kobj, &dev_attr_timer.attr);
|
|
|
|
}
|
2011-10-02 06:19:28 +08:00
|
|
|
|
2019-12-26 13:23:49 +08:00
|
|
|
/**
|
|
|
|
* devfreq_summary_show() - Show the summary of the devfreq devices
|
|
|
|
* @s: seq_file instance to show the summary of devfreq devices
|
|
|
|
* @data: not used
|
|
|
|
*
|
|
|
|
* Show the summary of the devfreq devices via 'devfreq_summary' debugfs file.
|
|
|
|
* It helps that user can know the detailed information of the devfreq devices.
|
|
|
|
*
|
|
|
|
* Return 0 always because it shows the information without any data change.
|
|
|
|
*/
|
|
|
|
static int devfreq_summary_show(struct seq_file *s, void *data)
|
|
|
|
{
|
|
|
|
struct devfreq *devfreq;
|
|
|
|
struct devfreq *p_devfreq = NULL;
|
|
|
|
unsigned long cur_freq, min_freq, max_freq;
|
|
|
|
unsigned int polling_ms;
|
2020-09-08 18:57:07 +08:00
|
|
|
unsigned int timer;
|
2019-12-26 13:23:49 +08:00
|
|
|
|
2020-09-08 18:57:07 +08:00
|
|
|
seq_printf(s, "%-30s %-30s %-15s %-10s %10s %12s %12s %12s\n",
|
2019-12-26 13:23:49 +08:00
|
|
|
"dev",
|
|
|
|
"parent_dev",
|
|
|
|
"governor",
|
2020-09-08 18:57:07 +08:00
|
|
|
"timer",
|
2019-12-26 13:23:49 +08:00
|
|
|
"polling_ms",
|
|
|
|
"cur_freq_Hz",
|
|
|
|
"min_freq_Hz",
|
|
|
|
"max_freq_Hz");
|
2020-09-08 18:57:07 +08:00
|
|
|
seq_printf(s, "%30s %30s %15s %10s %10s %12s %12s %12s\n",
|
2020-07-09 14:51:34 +08:00
|
|
|
"------------------------------",
|
2019-12-26 13:23:49 +08:00
|
|
|
"------------------------------",
|
|
|
|
"---------------",
|
|
|
|
"----------",
|
2020-09-08 18:57:07 +08:00
|
|
|
"----------",
|
2019-12-26 13:23:49 +08:00
|
|
|
"------------",
|
|
|
|
"------------",
|
|
|
|
"------------");
|
|
|
|
|
|
|
|
mutex_lock(&devfreq_list_lock);
|
|
|
|
|
|
|
|
list_for_each_entry_reverse(devfreq, &devfreq_list, node) {
|
|
|
|
#if IS_ENABLED(CONFIG_DEVFREQ_GOV_PASSIVE)
|
2020-10-20 14:12:12 +08:00
|
|
|
if (!strncmp(devfreq->governor->name, DEVFREQ_GOV_PASSIVE,
|
2019-12-26 13:23:49 +08:00
|
|
|
DEVFREQ_NAME_LEN)) {
|
|
|
|
struct devfreq_passive_data *data = devfreq->data;
|
|
|
|
|
|
|
|
if (data)
|
|
|
|
p_devfreq = data->parent;
|
|
|
|
} else {
|
|
|
|
p_devfreq = NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
mutex_lock(&devfreq->lock);
|
2020-07-27 10:32:31 +08:00
|
|
|
cur_freq = devfreq->previous_freq;
|
2019-12-26 13:23:49 +08:00
|
|
|
get_freq_range(devfreq, &min_freq, &max_freq);
|
2020-09-08 18:57:07 +08:00
|
|
|
timer = devfreq->profile->timer;
|
2020-07-03 16:20:27 +08:00
|
|
|
|
|
|
|
if (IS_SUPPORTED_ATTR(devfreq->governor->attrs, POLLING_INTERVAL))
|
|
|
|
polling_ms = devfreq->profile->polling_ms;
|
|
|
|
else
|
|
|
|
polling_ms = 0;
|
2019-12-26 13:23:49 +08:00
|
|
|
mutex_unlock(&devfreq->lock);
|
|
|
|
|
|
|
|
seq_printf(s,
|
2020-09-08 18:57:07 +08:00
|
|
|
"%-30s %-30s %-15s %-10s %10d %12ld %12ld %12ld\n",
|
2019-12-26 13:23:49 +08:00
|
|
|
dev_name(&devfreq->dev),
|
|
|
|
p_devfreq ? dev_name(&p_devfreq->dev) : "null",
|
2020-10-20 14:12:12 +08:00
|
|
|
devfreq->governor->name,
|
2020-09-08 18:57:07 +08:00
|
|
|
polling_ms ? timer_name[timer] : "null",
|
2019-12-26 13:23:49 +08:00
|
|
|
polling_ms,
|
|
|
|
cur_freq,
|
|
|
|
min_freq,
|
|
|
|
max_freq);
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_unlock(&devfreq_list_lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
DEFINE_SHOW_ATTRIBUTE(devfreq_summary);
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
static int __init devfreq_init(void)
|
|
|
|
{
|
|
|
|
devfreq_class = class_create(THIS_MODULE, "devfreq");
|
|
|
|
if (IS_ERR(devfreq_class)) {
|
|
|
|
pr_err("%s: couldn't create class\n", __FILE__);
|
|
|
|
return PTR_ERR(devfreq_class);
|
|
|
|
}
|
2012-10-26 07:50:09 +08:00
|
|
|
|
|
|
|
devfreq_wq = create_freezable_workqueue("devfreq_wq");
|
2013-08-15 15:55:10 +08:00
|
|
|
if (!devfreq_wq) {
|
2012-10-26 07:50:09 +08:00
|
|
|
class_destroy(devfreq_class);
|
|
|
|
pr_err("%s: couldn't create workqueue\n", __FILE__);
|
2013-08-15 15:55:10 +08:00
|
|
|
return -ENOMEM;
|
2012-10-26 07:50:09 +08:00
|
|
|
}
|
2013-07-25 06:05:09 +08:00
|
|
|
devfreq_class->dev_groups = devfreq_groups;
|
2012-10-26 07:50:09 +08:00
|
|
|
|
2019-12-26 13:23:49 +08:00
|
|
|
devfreq_debugfs = debugfs_create_dir("devfreq", NULL);
|
|
|
|
debugfs_create_file("devfreq_summary", 0444,
|
|
|
|
devfreq_debugfs, NULL,
|
|
|
|
&devfreq_summary_fops);
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
subsys_initcall(devfreq_init);
|
|
|
|
|
|
|
|
/*
|
2017-02-28 06:29:56 +08:00
|
|
|
* The following are helper functions for devfreq user device drivers with
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
* OPP framework.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* devfreq_recommended_opp() - Helper function to get proper OPP for the
|
|
|
|
* freq value given to target callback.
|
2012-10-26 07:50:35 +08:00
|
|
|
* @dev: The devfreq user device. (parent of devfreq)
|
|
|
|
* @freq: The frequency given to target function
|
|
|
|
* @flags: Flags handed from devfreq framework.
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
*
|
2017-01-23 12:41:47 +08:00
|
|
|
* The callers are required to call dev_pm_opp_put() for the returned OPP after
|
|
|
|
* use.
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
*/
|
2013-09-20 05:03:51 +08:00
|
|
|
struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
|
|
|
|
unsigned long *freq,
|
|
|
|
u32 flags)
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
{
|
2013-09-20 05:03:51 +08:00
|
|
|
struct dev_pm_opp *opp;
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
2012-03-17 04:54:53 +08:00
|
|
|
if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) {
|
|
|
|
/* The freq is an upper bound. opp should be lower */
|
2013-09-20 05:03:50 +08:00
|
|
|
opp = dev_pm_opp_find_freq_floor(dev, freq);
|
2012-03-17 04:54:53 +08:00
|
|
|
|
|
|
|
/* If not available, use the closest opp */
|
2012-10-25 04:00:12 +08:00
|
|
|
if (opp == ERR_PTR(-ERANGE))
|
2013-09-20 05:03:50 +08:00
|
|
|
opp = dev_pm_opp_find_freq_ceil(dev, freq);
|
2012-03-17 04:54:53 +08:00
|
|
|
} else {
|
|
|
|
/* The freq is an lower bound. opp should be higher */
|
2013-09-20 05:03:50 +08:00
|
|
|
opp = dev_pm_opp_find_freq_ceil(dev, freq);
|
2012-03-17 04:54:53 +08:00
|
|
|
|
|
|
|
/* If not available, use the closest opp */
|
2012-10-25 04:00:12 +08:00
|
|
|
if (opp == ERR_PTR(-ERANGE))
|
2013-09-20 05:03:50 +08:00
|
|
|
opp = dev_pm_opp_find_freq_floor(dev, freq);
|
2012-03-17 04:54:53 +08:00
|
|
|
}
|
|
|
|
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
return opp;
|
|
|
|
}
|
2014-07-18 22:09:53 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_recommended_opp);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* devfreq_register_opp_notifier() - Helper function to get devfreq notified
|
2019-01-21 10:11:07 +08:00
|
|
|
* for any changes in the OPP availability
|
|
|
|
* changes
|
2012-10-26 07:50:35 +08:00
|
|
|
* @dev: The devfreq user device. (parent of devfreq)
|
|
|
|
* @devfreq: The devfreq object.
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
*/
|
|
|
|
int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
|
|
|
|
{
|
2017-01-02 17:11:03 +08:00
|
|
|
return dev_pm_opp_register_notifier(dev, &devfreq->nb);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
}
|
2014-07-18 22:09:53 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_register_opp_notifier);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq
|
2019-01-21 10:11:07 +08:00
|
|
|
* notified for any changes in the OPP
|
|
|
|
* availability changes anymore.
|
2012-10-26 07:50:35 +08:00
|
|
|
* @dev: The devfreq user device. (parent of devfreq)
|
|
|
|
* @devfreq: The devfreq object.
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
*
|
|
|
|
* At exit() callback of devfreq_dev_profile, this must be included if
|
|
|
|
* devfreq_recommended_opp is used.
|
|
|
|
*/
|
|
|
|
int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
|
|
|
|
{
|
2017-01-02 17:11:03 +08:00
|
|
|
return dev_pm_opp_unregister_notifier(dev, &devfreq->nb);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
}
|
2014-07-18 22:09:53 +08:00
|
|
|
EXPORT_SYMBOL(devfreq_unregister_opp_notifier);
|
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
With OPPs, a device may have multiple operable frequency and voltage
sets. However, there can be multiple possible operable sets and a system
will need to choose one from them. In order to reduce the power
consumption (by reducing frequency and voltage) without affecting the
performance too much, a Dynamic Voltage and Frequency Scaling (DVFS)
scheme may be used.
This patch introduces the DVFS capability to non-CPU devices with OPPs.
DVFS is a techique whereby the frequency and supplied voltage of a
device is adjusted on-the-fly. DVFS usually sets the frequency as low
as possible with given conditions (such as QoS assurance) and adjusts
voltage according to the chosen frequency in order to reduce power
consumption and heat dissipation.
The generic DVFS for devices, devfreq, may appear quite similar with
/drivers/cpufreq. However, cpufreq does not allow to have multiple
devices registered and is not suitable to have multiple heterogenous
devices with different (but simple) governors.
Normally, DVFS mechanism controls frequency based on the demand for
the device, and then, chooses voltage based on the chosen frequency.
devfreq also controls the frequency based on the governor's frequency
recommendation and let OPP pick up the pair of frequency and voltage
based on the recommended frequency. Then, the chosen OPP is passed to
device driver's "target" callback.
When PM QoS is going to be used with the devfreq device, the device
driver should enable OPPs that are appropriate with the current PM QoS
requests. In order to do so, the device driver may call opp_enable and
opp_disable at the notifier callback of PM QoS so that PM QoS's
update_target() call enables the appropriate OPPs. Note that at least
one of OPPs should be enabled at any time; be careful when there is a
transition.
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Mike Turquette <mturquette@ti.com>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-10-02 06:19:15 +08:00
|
|
|
|
2014-05-09 15:43:09 +08:00
|
|
|
static void devm_devfreq_opp_release(struct device *dev, void *res)
|
|
|
|
{
|
|
|
|
devfreq_unregister_opp_notifier(dev, *(struct devfreq **)res);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-01-21 10:11:07 +08:00
|
|
|
* devm_devfreq_register_opp_notifier() - Resource-managed
|
|
|
|
* devfreq_register_opp_notifier()
|
2014-05-09 15:43:09 +08:00
|
|
|
* @dev: The devfreq user device. (parent of devfreq)
|
|
|
|
* @devfreq: The devfreq object.
|
|
|
|
*/
|
|
|
|
int devm_devfreq_register_opp_notifier(struct device *dev,
|
|
|
|
struct devfreq *devfreq)
|
|
|
|
{
|
|
|
|
struct devfreq **ptr;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ptr = devres_alloc(devm_devfreq_opp_release, sizeof(*ptr), GFP_KERNEL);
|
|
|
|
if (!ptr)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
ret = devfreq_register_opp_notifier(dev, devfreq);
|
|
|
|
if (ret) {
|
|
|
|
devres_free(ptr);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ptr = devfreq;
|
|
|
|
devres_add(dev, ptr);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devm_devfreq_register_opp_notifier);
|
|
|
|
|
|
|
|
/**
|
2019-01-21 10:11:07 +08:00
|
|
|
* devm_devfreq_unregister_opp_notifier() - Resource-managed
|
|
|
|
* devfreq_unregister_opp_notifier()
|
2014-05-09 15:43:09 +08:00
|
|
|
* @dev: The devfreq user device. (parent of devfreq)
|
|
|
|
* @devfreq: The devfreq object.
|
|
|
|
*/
|
|
|
|
void devm_devfreq_unregister_opp_notifier(struct device *dev,
|
|
|
|
struct devfreq *devfreq)
|
|
|
|
{
|
|
|
|
WARN_ON(devres_release(dev, devm_devfreq_opp_release,
|
|
|
|
devm_devfreq_dev_match, devfreq));
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devm_devfreq_unregister_opp_notifier);
|
|
|
|
|
2016-01-26 12:21:26 +08:00
|
|
|
/**
|
|
|
|
* devfreq_register_notifier() - Register a driver with devfreq
|
|
|
|
* @devfreq: The devfreq object.
|
|
|
|
* @nb: The notifier block to register.
|
|
|
|
* @list: DEVFREQ_TRANSITION_NOTIFIER.
|
|
|
|
*/
|
|
|
|
int devfreq_register_notifier(struct devfreq *devfreq,
|
2019-01-21 10:11:07 +08:00
|
|
|
struct notifier_block *nb,
|
|
|
|
unsigned int list)
|
2016-01-26 12:21:26 +08:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (!devfreq)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
switch (list) {
|
|
|
|
case DEVFREQ_TRANSITION_NOTIFIER:
|
|
|
|
ret = srcu_notifier_chain_register(
|
|
|
|
&devfreq->transition_notifier_list, nb);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devfreq_register_notifier);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* devfreq_unregister_notifier() - Unregister a driver with devfreq
|
|
|
|
* @devfreq: The devfreq object.
|
|
|
|
* @nb: The notifier block to be unregistered.
|
|
|
|
* @list: DEVFREQ_TRANSITION_NOTIFIER.
|
|
|
|
*/
|
|
|
|
int devfreq_unregister_notifier(struct devfreq *devfreq,
|
|
|
|
struct notifier_block *nb,
|
|
|
|
unsigned int list)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (!devfreq)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
switch (list) {
|
|
|
|
case DEVFREQ_TRANSITION_NOTIFIER:
|
|
|
|
ret = srcu_notifier_chain_unregister(
|
|
|
|
&devfreq->transition_notifier_list, nb);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devfreq_unregister_notifier);
|
|
|
|
|
|
|
|
struct devfreq_notifier_devres {
|
|
|
|
struct devfreq *devfreq;
|
|
|
|
struct notifier_block *nb;
|
|
|
|
unsigned int list;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void devm_devfreq_notifier_release(struct device *dev, void *res)
|
|
|
|
{
|
|
|
|
struct devfreq_notifier_devres *this = res;
|
|
|
|
|
|
|
|
devfreq_unregister_notifier(this->devfreq, this->nb, this->list);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* devm_devfreq_register_notifier()
|
2019-12-15 00:03:11 +08:00
|
|
|
* - Resource-managed devfreq_register_notifier()
|
2016-01-26 12:21:26 +08:00
|
|
|
* @dev: The devfreq user device. (parent of devfreq)
|
|
|
|
* @devfreq: The devfreq object.
|
|
|
|
* @nb: The notifier block to be unregistered.
|
|
|
|
* @list: DEVFREQ_TRANSITION_NOTIFIER.
|
|
|
|
*/
|
|
|
|
int devm_devfreq_register_notifier(struct device *dev,
|
|
|
|
struct devfreq *devfreq,
|
|
|
|
struct notifier_block *nb,
|
|
|
|
unsigned int list)
|
|
|
|
{
|
|
|
|
struct devfreq_notifier_devres *ptr;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ptr = devres_alloc(devm_devfreq_notifier_release, sizeof(*ptr),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!ptr)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
ret = devfreq_register_notifier(devfreq, nb, list);
|
|
|
|
if (ret) {
|
|
|
|
devres_free(ptr);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr->devfreq = devfreq;
|
|
|
|
ptr->nb = nb;
|
|
|
|
ptr->list = list;
|
|
|
|
devres_add(dev, ptr);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devm_devfreq_register_notifier);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* devm_devfreq_unregister_notifier()
|
2019-12-15 00:03:11 +08:00
|
|
|
* - Resource-managed devfreq_unregister_notifier()
|
2016-01-26 12:21:26 +08:00
|
|
|
* @dev: The devfreq user device. (parent of devfreq)
|
|
|
|
* @devfreq: The devfreq object.
|
|
|
|
* @nb: The notifier block to be unregistered.
|
|
|
|
* @list: DEVFREQ_TRANSITION_NOTIFIER.
|
|
|
|
*/
|
|
|
|
void devm_devfreq_unregister_notifier(struct device *dev,
|
2019-01-21 10:11:07 +08:00
|
|
|
struct devfreq *devfreq,
|
|
|
|
struct notifier_block *nb,
|
|
|
|
unsigned int list)
|
2016-01-26 12:21:26 +08:00
|
|
|
{
|
|
|
|
WARN_ON(devres_release(dev, devm_devfreq_notifier_release,
|
|
|
|
devm_devfreq_dev_match, devfreq));
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(devm_devfreq_unregister_notifier);
|