Device Frequency Scaling

Introduction

This framework provides a standard kernel interface for Dynamic Voltage andFrequency Switching on arbitrary devices.

It exposes controls for adjusting frequency through sysfs files which aresimilar to the cpufreq subsystem.

Devices for which current usage can be measured can have their frequencyautomatically adjusted by governors.

API

Device drivers need to initialize adevfreq_profile and call thedevfreq_add_device() function to create adevfreq instance.

structdevfreq_dev_status

Data given from devfreq user device to governors. Represents the performance statistics.

Definition

struct devfreq_dev_status {  unsigned long total_time;  unsigned long busy_time;  unsigned long current_frequency;  void *private_data;};

Members

total_time
The total time represented by this instance ofdevfreq_dev_status
busy_time
The time that the device was working among thetotal_time.
current_frequency
The operating frequency.
private_data
An entry not specified by the devfreq framework.A device and a specific governor may have theirown protocol with private_data. However, becausethis is governor-specific, a governor using thiswill be only compatible with devices aware of it.
structdevfreq_dev_profile

Devfreq’s user device profile

Definition

struct devfreq_dev_profile {  unsigned long initial_freq;  unsigned int polling_ms;  int (*target)(struct device *dev, unsigned long *freq, u32 flags);  int (*get_dev_status)(struct device *dev, struct devfreq_dev_status *stat);  int (*get_cur_freq)(struct device *dev, unsigned long *freq);  void (*exit)(struct device *dev);  unsigned long *freq_table;  unsigned int max_state;};

Members

initial_freq
The operating frequency whendevfreq_add_device() iscalled.
polling_ms
The polling interval in ms. 0 disables polling.
target
The device should set its operating frequency atfreq or lowest-upper-than-freq value. If freq ishigher than any operable frequency, set maximum.Before returning, target function should setfreq at the current frequency.The “flags” parameter’s possible values areexplained above with “DEVFREQ_FLAG_*” macros.
get_dev_status
The device should provide the current performancestatus to devfreq. Governors are recommended not touse this directly. Instead, governors are recommendedto use devfreq_update_stats() along withdevfreq.last_status.
get_cur_freq
The device should provide the current frequencyat which it is operating.
exit
An optional callback that is called when devfreqis removing the devfreq object due to error orfromdevfreq_remove_device() call. If the userhas registered devfreq->nb at a notifier-head,this is the time to unregister it.
freq_table
Optional list of frequencies to support statisticsand freq_table must be generated in ascending order.
max_state
The size of freq_table.
structdevfreq_stats

Statistics of devfreq device behavior

Definition

struct devfreq_stats {  unsigned int total_trans;  unsigned int *trans_table;  u64 *time_in_state;  u64 last_update;};

Members

total_trans
Number of devfreq transitions.
trans_table
Statistics of devfreq transitions.
time_in_state
Statistics of devfreq states.
last_update
The last time stats were updated.
structdevfreq

Device devfreq structure

Definition

struct devfreq {  struct list_head node;  struct mutex lock;  struct device dev;  struct devfreq_dev_profile *profile;  const struct devfreq_governor *governor;  char governor_name[DEVFREQ_NAME_LEN];  struct notifier_block nb;  struct delayed_work work;  unsigned long previous_freq;  struct devfreq_dev_status last_status;  void *data;  struct dev_pm_qos_request user_min_freq_req;  struct dev_pm_qos_request user_max_freq_req;  unsigned long scaling_min_freq;  unsigned long scaling_max_freq;  bool stop_polling;  unsigned long suspend_freq;  unsigned long resume_freq;  atomic_t suspend_count;  struct devfreq_stats stats;  struct srcu_notifier_head transition_notifier_list;  struct notifier_block nb_min;  struct notifier_block nb_max;};

Members

node
list node - contains the devices with devfreq that have beenregistered.
lock
a mutex to protect accessing devfreq.
dev
device registered by devfreq class. dev.parent is the deviceusing devfreq.
profile
device-specific devfreq profile
governor
method how to choose frequency based on the usage.
governor_name
devfreq governor name for use with this devfreq
nb
notifier block used to notify devfreq object that it shouldreevaluate operable frequencies. Devfreq users may usedevfreq.nb to the corresponding register notifier call chain.
work
delayed work for load monitoring.
previous_freq
previously configured frequency value.
last_status
devfreq user device info, performance statistics
data
Private data of the governor. The devfreq framework does nottouch this.
user_min_freq_req
PM QoS minimum frequency request from user (via sysfs)
user_max_freq_req
PM QoS maximum frequency request from user (via sysfs)
scaling_min_freq
Limit minimum frequency requested by OPP interface
scaling_max_freq
Limit maximum frequency requested by OPP interface
stop_polling
devfreq polling status of a device.
suspend_freq
frequency of a device set during suspend phase.
resume_freq
frequency of a device set in resume phase.
suspend_count
suspend requests counter for a device.
stats
Statistics of devfreq device behavior
transition_notifier_list
list head of DEVFREQ_TRANSITION_NOTIFIER notifier
nb_min
Notifier block for DEV_PM_QOS_MIN_FREQUENCY
nb_max
Notifier block for DEV_PM_QOS_MAX_FREQUENCY

Description

This structure stores the devfreq information for a given device.

Note that when a governor accesses entries in struct devfreq in itsfunctions except for the context of callbacks defined in structdevfreq_governor, the governor should protect its access with thestruct mutex lock in struct devfreq. A governor may use this mutexto protect its own private data invoid*data as well.

intupdate_devfreq(structdevfreq * devfreq)

Reevaluate the device and configure frequency

Parameters

structdevfreq*devfreq
the devfreq device

Note

devfreq->lock must be held

structdevfreq_simple_ondemand_data

void*data fed to struct devfreq and devfreq_add_device

Definition

struct devfreq_simple_ondemand_data {  unsigned int upthreshold;  unsigned int downdifferential;};

Members

upthreshold
If the load is over this value, the frequency jumps.Specify 0 to use the default. Valid value = 0 to 100.
downdifferential
If the load is under upthreshold - downdifferential,the governor may consider slowing the frequency down.Specify 0 to use the default. Valid value = 0 to 100.downdifferential < upthreshold must hold.

Description

If the fed devfreq_simple_ondemand_data pointer is NULL to the governor,the governor uses the default values.

structdevfreq_passive_data

void*data fed to struct devfreq and devfreq_add_device

Definition

struct devfreq_passive_data {  struct devfreq *parent;  int (*get_target_freq)(struct devfreq *this, unsigned long *freq);  struct devfreq *this;  struct notifier_block nb;};

Members

parent
the devfreq instance of parent device.
get_target_freq
Optional callback, Returns desired operating frequencyfor the device using passive governor. That is calledwhen passive governor should decide the next frequencyby using the new frequency of parent devfreq deviceusing governors except for passive governor.If the devfreq device has the specific method to decidethe next frequency, should use this callback.
this
the devfreq instance of own device.
nb
the notifier block for DEVFREQ_TRANSITION_NOTIFIER list

Description

The devfreq_passive_data have to set the devfreq instance of parentdevice with governors except for the passive governor. But, don’t need toinitialize the ‘this’ and ‘nb’ field because the devfreq core will handlethem.

structdevfreq_event_dev

the devfreq-event device

Definition

struct devfreq_event_dev {  struct list_head node;  struct device dev;  struct mutex lock;  u32 enable_count;  const struct devfreq_event_desc *desc;};

Members

node
Contain the devfreq-event device that have been registered.
dev
the device registered by devfreq-event class. dev.parent isthe device using devfreq-event.
lock
a mutex to protect accessing devfreq-event.
enable_count
the number of enable function have been called.
desc
the description for devfreq-event device.

Description

This structure contains devfreq-event device information.

structdevfreq_event_data

the devfreq-event data

Definition

struct devfreq_event_data {  unsigned long load_count;  unsigned long total_count;};

Members

load_count
load count of devfreq-event device for the given period.
total_count
total count of devfreq-event device for the given period.each count may represent a clock cycle, a time unit(ns/us/…), or anything the device driver wants.Generally, utilization is load_count / total_count.

Description

This structure contains the data of devfreq-event device for polling period.

structdevfreq_event_ops

the operations of devfreq-event device

Definition

struct devfreq_event_ops {  int (*enable)(struct devfreq_event_dev *edev);  int (*disable)(struct devfreq_event_dev *edev);  int (*reset)(struct devfreq_event_dev *edev);  int (*set_event)(struct devfreq_event_dev *edev);  int (*get_event)(struct devfreq_event_dev *edev, struct devfreq_event_data *edata);};

Members

enable
Enable the devfreq-event device.
disable
Disable the devfreq-event device.
reset
Reset all setting of the devfreq-event device.
set_event
Set the specific event type for the devfreq-event device.
get_event
Get the result of the devfreq-event devie with specificevent type.

Description

This structure contains devfreq-event device operations which can beimplemented by devfreq-event device drivers.

structdevfreq_event_desc

the descriptor of devfreq-event device

Definition

struct devfreq_event_desc {  const char *name;  u32 event_type;  void *driver_data;  const struct devfreq_event_ops *ops;};

Members

name
the name of devfreq-event device.
event_type
the type of the event determined and used by driver
driver_data
the private data for devfreq-event driver.
ops
the operation to control devfreq-event device.

Description

Each devfreq-event device is described with a this structure.This structure contains the various data for devfreq-event device.The event_type describes what is going to be counted in the register.It might choose to count e.g. read requests, write data in bytes, etc.The full supported list of types is present in specyfic header in:include/dt-bindings/pmu/.

intdevfreq_update_status(structdevfreq * devfreq, unsigned long freq)

Update statistics of devfreq behavior

Parameters

structdevfreq*devfreq
the devfreq instance
unsignedlongfreq
the update target frequency
intupdate_devfreq(structdevfreq * devfreq)

Reevaluate the device and configure frequency.

Parameters

structdevfreq*devfreq
the devfreq instance.

Note

Lock devfreq->lock before calling update_devfreq
This function is exported for governors.
voiddevfreq_monitor_start(structdevfreq * devfreq)

Start load monitoring of devfreq instance

Parameters

structdevfreq*devfreq
the devfreq instance.

Description

Helper function for starting devfreq device load monitoring. Bydefault delayed work based monitoring is supported. Functionto be called from governor in response to DEVFREQ_GOV_STARTevent when device is added to devfreq framework.

voiddevfreq_monitor_stop(structdevfreq * devfreq)

Stop load monitoring of a devfreq instance

Parameters

structdevfreq*devfreq
the devfreq instance.

Description

Helper function to stop devfreq device load monitoring. Functionto be called from governor in response to DEVFREQ_GOV_STOPevent when device is removed from devfreq framework.

voiddevfreq_monitor_suspend(structdevfreq * devfreq)

Suspend load monitoring of a devfreq instance

Parameters

structdevfreq*devfreq
the devfreq instance.

Description

Helper function to suspend devfreq device load monitoring. Functionto be called from governor in response to DEVFREQ_GOV_SUSPENDevent or when polling interval is set to zero.

Note

Though this function is same asdevfreq_monitor_stop(),intentionally kept separate to provide hooks for collectingtransition statistics.

voiddevfreq_monitor_resume(structdevfreq * devfreq)

Resume load monitoring of a devfreq instance

Parameters

structdevfreq*devfreq
the devfreq instance.

Description

Helper function to resume devfreq device load monitoring. Functionto be called from governor in response to DEVFREQ_GOV_RESUMEevent or when polling interval is set to non-zero.

voiddevfreq_update_interval(structdevfreq * devfreq, unsigned int * delay)

Update device devfreq monitoring interval

Parameters

structdevfreq*devfreq
the devfreq instance.
unsignedint*delay
new polling interval to be set.

Description

Helper function to set new load monitoring polling interval. Functionto be called from governor in response to DEVFREQ_GOV_UPDATE_INTERVAL event.

structdevfreq *devfreq_add_device(structdevice * dev, structdevfreq_dev_profile * profile, const char * governor_name, void * data)

Add devfreq feature to the device

Parameters

structdevice*dev
the device to add devfreq feature.
structdevfreq_dev_profile*profile
device-specific profile to run devfreq.
constchar*governor_name
name of the policy to choose frequency.
void*data
private data for the governor. The devfreq framework does nottouch this value.
intdevfreq_remove_device(structdevfreq * devfreq)

Remove devfreq feature from a device.

Parameters

structdevfreq*devfreq
the devfreq instance to be removed

Description

The opposite ofdevfreq_add_device().

structdevfreq *devm_devfreq_add_device(structdevice * dev, structdevfreq_dev_profile * profile, const char * governor_name, void * data)

Resource-manageddevfreq_add_device()

Parameters

structdevice*dev
the device to add devfreq feature.
structdevfreq_dev_profile*profile
device-specific profile to run devfreq.
constchar*governor_name
name of the policy to choose frequency.
void*data
private data for the governor. The devfreq framework does nottouch this value.

Description

This function manages automatically the memory of devfreq device using deviceresource management and simplify the free operation for memory of devfreqdevice.

voiddevm_devfreq_remove_device(structdevice * dev, structdevfreq * devfreq)

Resource-manageddevfreq_remove_device()

Parameters

structdevice*dev
the device from which to remove devfreq feature.
structdevfreq*devfreq
the devfreq instance to be removed
intdevfreq_suspend_device(structdevfreq * devfreq)

Suspend devfreq of a device.

Parameters

structdevfreq*devfreq
the devfreq instance to be suspended

Description

This function is intended to be called by the pm callbacks(e.g., runtime_suspend, suspend) of the device driver thatholds the devfreq.

intdevfreq_resume_device(structdevfreq * devfreq)

Resume devfreq of a device.

Parameters

structdevfreq*devfreq
the devfreq instance to be resumed

Description

This function is intended to be called by the pm callbacks(e.g., runtime_resume, resume) of the device driver thatholds the devfreq.

intdevfreq_add_governor(struct devfreq_governor * governor)

Add devfreq governor

Parameters

structdevfreq_governor*governor
the devfreq governor to be added
intdevfreq_remove_governor(struct devfreq_governor * governor)

Remove devfreq feature from a device.

Parameters

structdevfreq_governor*governor
the devfreq governor to be removed
struct dev_pm_opp *devfreq_recommended_opp(structdevice * dev, unsigned long * freq, u32 flags)

Helper function to get proper OPP for the freq value given to target callback.

Parameters

structdevice*dev
The devfreq user device. (parent of devfreq)
unsignedlong*freq
The frequency given to target function
u32flags
Flags handed from devfreq framework.

Description

The callers are required to call dev_pm_opp_put() for the returned OPP afteruse.

intdevfreq_register_opp_notifier(structdevice * dev, structdevfreq * devfreq)

Helper function to get devfreq notified for any changes in the OPP availability changes

Parameters

structdevice*dev
The devfreq user device. (parent of devfreq)
structdevfreq*devfreq
The devfreq object.
intdevfreq_unregister_opp_notifier(structdevice * dev, structdevfreq * devfreq)

Helper function to stop getting devfreq notified for any changes in the OPP availability changes anymore.

Parameters

structdevice*dev
The devfreq user device. (parent of devfreq)
structdevfreq*devfreq
The devfreq object.

Description

At exit() callback of devfreq_dev_profile, this must be included ifdevfreq_recommended_opp is used.

intdevm_devfreq_register_opp_notifier(structdevice * dev, structdevfreq * devfreq)

Resource-manageddevfreq_register_opp_notifier()

Parameters

structdevice*dev
The devfreq user device. (parent of devfreq)
structdevfreq*devfreq
The devfreq object.
voiddevm_devfreq_unregister_opp_notifier(structdevice * dev, structdevfreq * devfreq)

Resource-manageddevfreq_unregister_opp_notifier()

Parameters

structdevice*dev
The devfreq user device. (parent of devfreq)
structdevfreq*devfreq
The devfreq object.
intdevfreq_register_notifier(structdevfreq * devfreq, struct notifier_block * nb, unsigned int list)

Register a driver with devfreq

Parameters

structdevfreq*devfreq
The devfreq object.
structnotifier_block*nb
The notifier block to register.
unsignedintlist
DEVFREQ_TRANSITION_NOTIFIER.
intdevm_devfreq_register_notifier(structdevice * dev, structdevfreq * devfreq, struct notifier_block * nb, unsigned int list)

Parameters

structdevice*dev
The devfreq user device. (parent of devfreq)
structdevfreq*devfreq
The devfreq object.
structnotifier_block*nb
The notifier block to be unregistered.
unsignedintlist
DEVFREQ_TRANSITION_NOTIFIER.

Description

voiddevm_devfreq_unregister_notifier(structdevice * dev, structdevfreq * devfreq, struct notifier_block * nb, unsigned int list)

Parameters

structdevice*dev
The devfreq user device. (parent of devfreq)
structdevfreq*devfreq
The devfreq object.
structnotifier_block*nb
The notifier block to be unregistered.
unsignedintlist
DEVFREQ_TRANSITION_NOTIFIER.

Description

  • Resource-managed devfreq_unregister_notifier()
intdevfreq_event_enable_edev(structdevfreq_event_dev * edev)

Enable the devfreq-event dev and increase the enable_count of devfreq-event dev.

Parameters

structdevfreq_event_dev*edev
the devfreq-event device

Description

Note that this function increase the enable_count and enable thedevfreq-event device. The devfreq-event device should be enabled beforeusing it by devfreq device.

intdevfreq_event_disable_edev(structdevfreq_event_dev * edev)

Disable the devfreq-event dev and decrease the enable_count of the devfreq-event dev.

Parameters

structdevfreq_event_dev*edev
the devfreq-event device

Description

Note that this function decrease the enable_count and disable thedevfreq-event device. After the devfreq-event device is disabled,devfreq device can’t use the devfreq-event device for get/set/resetoperations.

booldevfreq_event_is_enabled(structdevfreq_event_dev * edev)

Check whether devfreq-event dev is enabled or not.

Parameters

structdevfreq_event_dev*edev
the devfreq-event device

Description

Note that this function check whether devfreq-event dev is enabled or not.If return true, the devfreq-event dev is enabeld. If return false, thedevfreq-event dev is disabled.

intdevfreq_event_set_event(structdevfreq_event_dev * edev)

Set event to devfreq-event dev to start.

Parameters

structdevfreq_event_dev*edev
the devfreq-event device

Description

Note that this function set the event to the devfreq-event device to startfor getting the event data which could be various event type.

intdevfreq_event_get_event(structdevfreq_event_dev * edev, structdevfreq_event_data * edata)

Get {load|total}_count from devfreq-event dev.

Parameters

structdevfreq_event_dev*edev
the devfreq-event device
structdevfreq_event_data*edata
the calculated data of devfreq-event device

Description

Note that this function get the calculated event data from devfreq-event devafter stoping the progress of whole sequence of devfreq-event dev.

intdevfreq_event_reset_event(structdevfreq_event_dev * edev)

Reset all opeations of devfreq-event dev.

Parameters

structdevfreq_event_dev*edev
the devfreq-event device

Description

Note that this function stop all operations of devfreq-event dev and resetthe current event data to make the devfreq-event device into initial state.

structdevfreq_event_dev *devfreq_event_get_edev_by_phandle(structdevice * dev, int index)

Get the devfreq-event dev from devicetree.

Parameters

structdevice*dev
the pointer to the given device
intindex
the index into list of devfreq-event device

Description

Note that this function return the pointer of devfreq-event device.

intdevfreq_event_get_edev_count(structdevice * dev)

Get the count of devfreq-event dev

Parameters

structdevice*dev
the pointer to the given device

Description

Note that this function return the count of devfreq-event devices.

structdevfreq_event_dev *devfreq_event_add_edev(structdevice * dev, structdevfreq_event_desc * desc)

Add new devfreq-event device.

Parameters

structdevice*dev
the device owning the devfreq-event device being created
structdevfreq_event_desc*desc
the devfreq-event device’s decriptor which include essentialdata for devfreq-event device.

Description

Note that this function add new devfreq-event device to devfreq-event classlist and register the device of the devfreq-event device.

intdevfreq_event_remove_edev(structdevfreq_event_dev * edev)

Remove the devfreq-event device registered.

Parameters

structdevfreq_event_dev*edev
the devfreq-event device

Description

Note that this function removes the registered devfreq-event device.

structdevfreq_event_dev *devm_devfreq_event_add_edev(structdevice * dev, structdevfreq_event_desc * desc)

Resource-manageddevfreq_event_add_edev()

Parameters

structdevice*dev
the device owning the devfreq-event device being created
structdevfreq_event_desc*desc
the devfreq-event device’s decriptor which include essentialdata for devfreq-event device.

Description

Note that this function manages automatically the memory of devfreq-eventdevice using device resource management and simplify the free operationfor memory of devfreq-event device.

voiddevm_devfreq_event_remove_edev(structdevice * dev, structdevfreq_event_dev * edev)

Resource-manageddevfreq_event_remove_edev()

Parameters

structdevice*dev
the device owning the devfreq-event device being created
structdevfreq_event_dev*edev
the devfreq-event device

Description

Note that this function manages automatically the memory of devfreq-eventdevice using device resource management.