1a3c98b8bSMyungJoo Ham /* 2a3c98b8bSMyungJoo Ham * devfreq: Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework 3a3c98b8bSMyungJoo Ham * for Non-CPU Devices. 4a3c98b8bSMyungJoo Ham * 5a3c98b8bSMyungJoo Ham * Copyright (C) 2011 Samsung Electronics 6a3c98b8bSMyungJoo Ham * MyungJoo Ham <[email protected]> 7a3c98b8bSMyungJoo Ham * 8a3c98b8bSMyungJoo Ham * This program is free software; you can redistribute it and/or modify 9a3c98b8bSMyungJoo Ham * it under the terms of the GNU General Public License version 2 as 10a3c98b8bSMyungJoo Ham * published by the Free Software Foundation. 11a3c98b8bSMyungJoo Ham */ 12a3c98b8bSMyungJoo Ham 13a3c98b8bSMyungJoo Ham #ifndef __LINUX_DEVFREQ_H__ 14a3c98b8bSMyungJoo Ham #define __LINUX_DEVFREQ_H__ 15a3c98b8bSMyungJoo Ham 16a3c98b8bSMyungJoo Ham #include <linux/device.h> 17a3c98b8bSMyungJoo Ham #include <linux/notifier.h> 18a3c98b8bSMyungJoo Ham #include <linux/opp.h> 19a3c98b8bSMyungJoo Ham 20a3c98b8bSMyungJoo Ham #define DEVFREQ_NAME_LEN 16 21a3c98b8bSMyungJoo Ham 22a3c98b8bSMyungJoo Ham struct devfreq; 23a3c98b8bSMyungJoo Ham 24a3c98b8bSMyungJoo Ham /** 25a3c98b8bSMyungJoo Ham * struct devfreq_dev_status - Data given from devfreq user device to 26a3c98b8bSMyungJoo Ham * governors. Represents the performance 27a3c98b8bSMyungJoo Ham * statistics. 28e09651fcSNishanth Menon * @total_time: The total time represented by this instance of 29a3c98b8bSMyungJoo Ham * devfreq_dev_status 30e09651fcSNishanth Menon * @busy_time: The time that the device was working among the 31a3c98b8bSMyungJoo Ham * total_time. 32e09651fcSNishanth Menon * @current_frequency: The operating frequency. 33e09651fcSNishanth Menon * @private_data: An entry not specified by the devfreq framework. 34a3c98b8bSMyungJoo Ham * A device and a specific governor may have their 35a3c98b8bSMyungJoo Ham * own protocol with private_data. However, because 36a3c98b8bSMyungJoo Ham * this is governor-specific, a governor using this 37a3c98b8bSMyungJoo Ham * will be only compatible with devices aware of it. 38a3c98b8bSMyungJoo Ham */ 39a3c98b8bSMyungJoo Ham struct devfreq_dev_status { 40a3c98b8bSMyungJoo Ham /* both since the last measure */ 41a3c98b8bSMyungJoo Ham unsigned long total_time; 42a3c98b8bSMyungJoo Ham unsigned long busy_time; 43a3c98b8bSMyungJoo Ham unsigned long current_frequency; 441a51cfdcSJonathan Corbet void *private_data; 45a3c98b8bSMyungJoo Ham }; 46a3c98b8bSMyungJoo Ham 47ab5f299fSMyungJoo Ham /* 48ab5f299fSMyungJoo Ham * The resulting frequency should be at most this. (this bound is the 49ab5f299fSMyungJoo Ham * least upper bound; thus, the resulting freq should be lower or same) 50ab5f299fSMyungJoo Ham * If the flag is not set, the resulting frequency should be at most the 51ab5f299fSMyungJoo Ham * bound (greatest lower bound) 52ab5f299fSMyungJoo Ham */ 53ab5f299fSMyungJoo Ham #define DEVFREQ_FLAG_LEAST_UPPER_BOUND 0x1 54ab5f299fSMyungJoo Ham 55a3c98b8bSMyungJoo Ham /** 56a3c98b8bSMyungJoo Ham * struct devfreq_dev_profile - Devfreq's user device profile 57e09651fcSNishanth Menon * @initial_freq: The operating frequency when devfreq_add_device() is 58a3c98b8bSMyungJoo Ham * called. 59e09651fcSNishanth Menon * @polling_ms: The polling interval in ms. 0 disables polling. 60e09651fcSNishanth Menon * @target: The device should set its operating frequency at 61a3c98b8bSMyungJoo Ham * freq or lowest-upper-than-freq value. If freq is 62a3c98b8bSMyungJoo Ham * higher than any operable frequency, set maximum. 63a3c98b8bSMyungJoo Ham * Before returning, target function should set 64a3c98b8bSMyungJoo Ham * freq at the current frequency. 65ab5f299fSMyungJoo Ham * The "flags" parameter's possible values are 66ab5f299fSMyungJoo Ham * explained above with "DEVFREQ_FLAG_*" macros. 67e09651fcSNishanth Menon * @get_dev_status: The device should provide the current performance 68a3c98b8bSMyungJoo Ham * status to devfreq, which is used by governors. 69e09651fcSNishanth Menon * @get_cur_freq: The device should provide the current frequency 707f98a905SRajagopal Venkat * at which it is operating. 71e09651fcSNishanth Menon * @exit: An optional callback that is called when devfreq 72a3c98b8bSMyungJoo Ham * is removing the devfreq object due to error or 73a3c98b8bSMyungJoo Ham * from devfreq_remove_device() call. If the user 74a3c98b8bSMyungJoo Ham * has registered devfreq->nb at a notifier-head, 75a3c98b8bSMyungJoo Ham * this is the time to unregister it. 76e552bbafSJonghwa Lee * @freq_table: Optional list of frequencies to support statistics. 77e552bbafSJonghwa Lee * @max_state: The size of freq_table. 78a3c98b8bSMyungJoo Ham */ 79a3c98b8bSMyungJoo Ham struct devfreq_dev_profile { 80a3c98b8bSMyungJoo Ham unsigned long initial_freq; 81a3c98b8bSMyungJoo Ham unsigned int polling_ms; 82a3c98b8bSMyungJoo Ham 83ab5f299fSMyungJoo Ham int (*target)(struct device *dev, unsigned long *freq, u32 flags); 84a3c98b8bSMyungJoo Ham int (*get_dev_status)(struct device *dev, 85a3c98b8bSMyungJoo Ham struct devfreq_dev_status *stat); 867f98a905SRajagopal Venkat int (*get_cur_freq)(struct device *dev, unsigned long *freq); 87a3c98b8bSMyungJoo Ham void (*exit)(struct device *dev); 88e552bbafSJonghwa Lee 89e552bbafSJonghwa Lee unsigned int *freq_table; 90e552bbafSJonghwa Lee unsigned int max_state; 91a3c98b8bSMyungJoo Ham }; 92a3c98b8bSMyungJoo Ham 93a3c98b8bSMyungJoo Ham /** 94a3c98b8bSMyungJoo Ham * struct devfreq_governor - Devfreq policy governor 953aa173b8SNishanth Menon * @node: list node - contains registered devfreq governors 96e09651fcSNishanth Menon * @name: Governor's name 97e09651fcSNishanth Menon * @get_target_freq: Returns desired operating frequency for the device. 98a3c98b8bSMyungJoo Ham * Basically, get_target_freq will run 99a3c98b8bSMyungJoo Ham * devfreq_dev_profile.get_dev_status() to get the 100a3c98b8bSMyungJoo Ham * status of the device (load = busy_time / total_time). 101a3c98b8bSMyungJoo Ham * If no_central_polling is set, this callback is called 102a3c98b8bSMyungJoo Ham * only with update_devfreq() notified by OPP. 103e09651fcSNishanth Menon * @event_handler: Callback for devfreq core framework to notify events 1047e6fdd4bSRajagopal Venkat * to governors. Events include per device governor 1057e6fdd4bSRajagopal Venkat * init and exit, opp changes out of devfreq, suspend 1067e6fdd4bSRajagopal Venkat * and resume of per device devfreq during device idle. 107a3c98b8bSMyungJoo Ham * 108a3c98b8bSMyungJoo Ham * Note that the callbacks are called with devfreq->lock locked by devfreq. 109a3c98b8bSMyungJoo Ham */ 110a3c98b8bSMyungJoo Ham struct devfreq_governor { 1113aa173b8SNishanth Menon struct list_head node; 1123aa173b8SNishanth Menon 113a3c98b8bSMyungJoo Ham const char name[DEVFREQ_NAME_LEN]; 114a3c98b8bSMyungJoo Ham int (*get_target_freq)(struct devfreq *this, unsigned long *freq); 1157e6fdd4bSRajagopal Venkat int (*event_handler)(struct devfreq *devfreq, 1167e6fdd4bSRajagopal Venkat unsigned int event, void *data); 117a3c98b8bSMyungJoo Ham }; 118a3c98b8bSMyungJoo Ham 119a3c98b8bSMyungJoo Ham /** 120a3c98b8bSMyungJoo Ham * struct devfreq - Device devfreq structure 121e09651fcSNishanth Menon * @node: list node - contains the devices with devfreq that have been 122a3c98b8bSMyungJoo Ham * registered. 123e09651fcSNishanth Menon * @lock: a mutex to protect accessing devfreq. 124e09651fcSNishanth Menon * @dev: device registered by devfreq class. dev.parent is the device 125a3c98b8bSMyungJoo Ham * using devfreq. 126e09651fcSNishanth Menon * @profile: device-specific devfreq profile 127e09651fcSNishanth Menon * @governor: method how to choose frequency based on the usage. 1281b5c1be2SNishanth Menon * @governor_name: devfreq governor name for use with this devfreq 129e09651fcSNishanth Menon * @nb: notifier block used to notify devfreq object that it should 130a3c98b8bSMyungJoo Ham * reevaluate operable frequencies. Devfreq users may use 131a3c98b8bSMyungJoo Ham * devfreq.nb to the corresponding register notifier call chain. 132e09651fcSNishanth Menon * @work: delayed work for load monitoring. 133e09651fcSNishanth Menon * @previous_freq: previously configured frequency value. 134e09651fcSNishanth Menon * @data: Private data of the governor. The devfreq framework does not 135a3c98b8bSMyungJoo Ham * touch this. 136e09651fcSNishanth Menon * @min_freq: Limit minimum frequency requested by user (0: none) 137e09651fcSNishanth Menon * @max_freq: Limit maximum frequency requested by user (0: none) 138e09651fcSNishanth Menon * @stop_polling: devfreq polling status of a device. 139e552bbafSJonghwa Lee * @total_trans: Number of devfreq transitions 140e552bbafSJonghwa Lee * @trans_table: Statistics of devfreq transitions 141e552bbafSJonghwa Lee * @time_in_state: Statistics of devfreq states 142e552bbafSJonghwa Lee * @last_stat_updated: The last time stat updated 143a3c98b8bSMyungJoo Ham * 144a3c98b8bSMyungJoo Ham * This structure stores the devfreq information for a give device. 145a3c98b8bSMyungJoo Ham * 146a3c98b8bSMyungJoo Ham * Note that when a governor accesses entries in struct devfreq in its 147a3c98b8bSMyungJoo Ham * functions except for the context of callbacks defined in struct 148a3c98b8bSMyungJoo Ham * devfreq_governor, the governor should protect its access with the 149a3c98b8bSMyungJoo Ham * struct mutex lock in struct devfreq. A governor may use this mutex 150a3c98b8bSMyungJoo Ham * to protect its own private data in void *data as well. 151a3c98b8bSMyungJoo Ham */ 152a3c98b8bSMyungJoo Ham struct devfreq { 153a3c98b8bSMyungJoo Ham struct list_head node; 154a3c98b8bSMyungJoo Ham 155a3c98b8bSMyungJoo Ham struct mutex lock; 156a3c98b8bSMyungJoo Ham struct device dev; 157a3c98b8bSMyungJoo Ham struct devfreq_dev_profile *profile; 158a3c98b8bSMyungJoo Ham const struct devfreq_governor *governor; 1591b5c1be2SNishanth Menon char governor_name[DEVFREQ_NAME_LEN]; 160a3c98b8bSMyungJoo Ham struct notifier_block nb; 1617e6fdd4bSRajagopal Venkat struct delayed_work work; 162a3c98b8bSMyungJoo Ham 163a3c98b8bSMyungJoo Ham unsigned long previous_freq; 164a3c98b8bSMyungJoo Ham 165a3c98b8bSMyungJoo Ham void *data; /* private data for governors */ 166a3c98b8bSMyungJoo Ham 1676530b9deSMyungJoo Ham unsigned long min_freq; 1686530b9deSMyungJoo Ham unsigned long max_freq; 1697e6fdd4bSRajagopal Venkat bool stop_polling; 170e552bbafSJonghwa Lee 171e552bbafSJonghwa Lee /* information for device freqeuncy transition */ 172e552bbafSJonghwa Lee unsigned int total_trans; 173e552bbafSJonghwa Lee unsigned int *trans_table; 174e552bbafSJonghwa Lee unsigned long *time_in_state; 175e552bbafSJonghwa Lee unsigned long last_stat_updated; 176a3c98b8bSMyungJoo Ham }; 177a3c98b8bSMyungJoo Ham 178a3c98b8bSMyungJoo Ham #if defined(CONFIG_PM_DEVFREQ) 179a3c98b8bSMyungJoo Ham extern struct devfreq *devfreq_add_device(struct device *dev, 180a3c98b8bSMyungJoo Ham struct devfreq_dev_profile *profile, 1811b5c1be2SNishanth Menon const char *governor_name, 182a3c98b8bSMyungJoo Ham void *data); 183a3c98b8bSMyungJoo Ham extern int devfreq_remove_device(struct devfreq *devfreq); 184206c30cfSRajagopal Venkat extern int devfreq_suspend_device(struct devfreq *devfreq); 185206c30cfSRajagopal Venkat extern int devfreq_resume_device(struct devfreq *devfreq); 186a3c98b8bSMyungJoo Ham 187a3c98b8bSMyungJoo Ham /* Helper functions for devfreq user device driver with OPP. */ 188a3c98b8bSMyungJoo Ham extern struct opp *devfreq_recommended_opp(struct device *dev, 189ab5f299fSMyungJoo Ham unsigned long *freq, u32 flags); 190a3c98b8bSMyungJoo Ham extern int devfreq_register_opp_notifier(struct device *dev, 191a3c98b8bSMyungJoo Ham struct devfreq *devfreq); 192a3c98b8bSMyungJoo Ham extern int devfreq_unregister_opp_notifier(struct device *dev, 193a3c98b8bSMyungJoo Ham struct devfreq *devfreq); 194a3c98b8bSMyungJoo Ham 195883d588eSMyungJoo Ham #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) 196ce26c5bbSMyungJoo Ham /** 197ce26c5bbSMyungJoo Ham * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq 198ce26c5bbSMyungJoo Ham * and devfreq_add_device 199e09651fcSNishanth Menon * @upthreshold: If the load is over this value, the frequency jumps. 200ce26c5bbSMyungJoo Ham * Specify 0 to use the default. Valid value = 0 to 100. 201e09651fcSNishanth Menon * @downdifferential: If the load is under upthreshold - downdifferential, 202ce26c5bbSMyungJoo Ham * the governor may consider slowing the frequency down. 203ce26c5bbSMyungJoo Ham * Specify 0 to use the default. Valid value = 0 to 100. 204ce26c5bbSMyungJoo Ham * downdifferential < upthreshold must hold. 205ce26c5bbSMyungJoo Ham * 206ce26c5bbSMyungJoo Ham * If the fed devfreq_simple_ondemand_data pointer is NULL to the governor, 207ce26c5bbSMyungJoo Ham * the governor uses the default values. 208ce26c5bbSMyungJoo Ham */ 209ce26c5bbSMyungJoo Ham struct devfreq_simple_ondemand_data { 210ce26c5bbSMyungJoo Ham unsigned int upthreshold; 211ce26c5bbSMyungJoo Ham unsigned int downdifferential; 212ce26c5bbSMyungJoo Ham }; 213ce26c5bbSMyungJoo Ham #endif 214ce26c5bbSMyungJoo Ham 215a3c98b8bSMyungJoo Ham #else /* !CONFIG_PM_DEVFREQ */ 216*5faaa035SRajagopal Venkat static inline struct devfreq *devfreq_add_device(struct device *dev, 217a3c98b8bSMyungJoo Ham struct devfreq_dev_profile *profile, 2181b5c1be2SNishanth Menon const char *governor_name, 219a95e1f5dSMyungJoo Ham void *data) 220a3c98b8bSMyungJoo Ham { 221a3c98b8bSMyungJoo Ham return NULL; 222a3c98b8bSMyungJoo Ham } 223a3c98b8bSMyungJoo Ham 224*5faaa035SRajagopal Venkat static inline int devfreq_remove_device(struct devfreq *devfreq) 225a3c98b8bSMyungJoo Ham { 226a3c98b8bSMyungJoo Ham return 0; 227a3c98b8bSMyungJoo Ham } 228a3c98b8bSMyungJoo Ham 229*5faaa035SRajagopal Venkat static inline int devfreq_suspend_device(struct devfreq *devfreq) 230206c30cfSRajagopal Venkat { 231206c30cfSRajagopal Venkat return 0; 232206c30cfSRajagopal Venkat } 233206c30cfSRajagopal Venkat 234*5faaa035SRajagopal Venkat static inline int devfreq_resume_device(struct devfreq *devfreq) 235206c30cfSRajagopal Venkat { 236206c30cfSRajagopal Venkat return 0; 237206c30cfSRajagopal Venkat } 238206c30cfSRajagopal Venkat 239*5faaa035SRajagopal Venkat static inline struct opp *devfreq_recommended_opp(struct device *dev, 240ab5f299fSMyungJoo Ham unsigned long *freq, u32 flags) 241a3c98b8bSMyungJoo Ham { 242*5faaa035SRajagopal Venkat return ERR_PTR(-EINVAL); 243a3c98b8bSMyungJoo Ham } 244a3c98b8bSMyungJoo Ham 245*5faaa035SRajagopal Venkat static inline int devfreq_register_opp_notifier(struct device *dev, 246a3c98b8bSMyungJoo Ham struct devfreq *devfreq) 247a3c98b8bSMyungJoo Ham { 248a3c98b8bSMyungJoo Ham return -EINVAL; 249a3c98b8bSMyungJoo Ham } 250a3c98b8bSMyungJoo Ham 251*5faaa035SRajagopal Venkat static inline int devfreq_unregister_opp_notifier(struct device *dev, 252a3c98b8bSMyungJoo Ham struct devfreq *devfreq) 253a3c98b8bSMyungJoo Ham { 254a3c98b8bSMyungJoo Ham return -EINVAL; 255a3c98b8bSMyungJoo Ham } 256a3c98b8bSMyungJoo Ham 257a3c98b8bSMyungJoo Ham #endif /* CONFIG_PM_DEVFREQ */ 258a3c98b8bSMyungJoo Ham 259a3c98b8bSMyungJoo Ham #endif /* __LINUX_DEVFREQ_H__ */ 260