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. 76*e552bbafSJonghwa Lee * @freq_table: Optional list of frequencies to support statistics. 77*e552bbafSJonghwa 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); 88*e552bbafSJonghwa Lee 89*e552bbafSJonghwa Lee unsigned int *freq_table; 90*e552bbafSJonghwa Lee unsigned int max_state; 91a3c98b8bSMyungJoo Ham }; 92a3c98b8bSMyungJoo Ham 93a3c98b8bSMyungJoo Ham /** 94a3c98b8bSMyungJoo Ham * struct devfreq_governor - Devfreq policy governor 95e09651fcSNishanth Menon * @name: Governor's name 96e09651fcSNishanth Menon * @get_target_freq: Returns desired operating frequency for the device. 97a3c98b8bSMyungJoo Ham * Basically, get_target_freq will run 98a3c98b8bSMyungJoo Ham * devfreq_dev_profile.get_dev_status() to get the 99a3c98b8bSMyungJoo Ham * status of the device (load = busy_time / total_time). 100a3c98b8bSMyungJoo Ham * If no_central_polling is set, this callback is called 101a3c98b8bSMyungJoo Ham * only with update_devfreq() notified by OPP. 102e09651fcSNishanth Menon * @event_handler: Callback for devfreq core framework to notify events 1037e6fdd4bSRajagopal Venkat * to governors. Events include per device governor 1047e6fdd4bSRajagopal Venkat * init and exit, opp changes out of devfreq, suspend 1057e6fdd4bSRajagopal Venkat * and resume of per device devfreq during device idle. 106a3c98b8bSMyungJoo Ham * 107a3c98b8bSMyungJoo Ham * Note that the callbacks are called with devfreq->lock locked by devfreq. 108a3c98b8bSMyungJoo Ham */ 109a3c98b8bSMyungJoo Ham struct devfreq_governor { 110a3c98b8bSMyungJoo Ham const char name[DEVFREQ_NAME_LEN]; 111a3c98b8bSMyungJoo Ham int (*get_target_freq)(struct devfreq *this, unsigned long *freq); 1127e6fdd4bSRajagopal Venkat int (*event_handler)(struct devfreq *devfreq, 1137e6fdd4bSRajagopal Venkat unsigned int event, void *data); 114a3c98b8bSMyungJoo Ham }; 115a3c98b8bSMyungJoo Ham 116a3c98b8bSMyungJoo Ham /** 117a3c98b8bSMyungJoo Ham * struct devfreq - Device devfreq structure 118e09651fcSNishanth Menon * @node: list node - contains the devices with devfreq that have been 119a3c98b8bSMyungJoo Ham * registered. 120e09651fcSNishanth Menon * @lock: a mutex to protect accessing devfreq. 121e09651fcSNishanth Menon * @dev: device registered by devfreq class. dev.parent is the device 122a3c98b8bSMyungJoo Ham * using devfreq. 123e09651fcSNishanth Menon * @profile: device-specific devfreq profile 124e09651fcSNishanth Menon * @governor: method how to choose frequency based on the usage. 125e09651fcSNishanth Menon * @nb: notifier block used to notify devfreq object that it should 126a3c98b8bSMyungJoo Ham * reevaluate operable frequencies. Devfreq users may use 127a3c98b8bSMyungJoo Ham * devfreq.nb to the corresponding register notifier call chain. 128e09651fcSNishanth Menon * @work: delayed work for load monitoring. 129e09651fcSNishanth Menon * @previous_freq: previously configured frequency value. 130e09651fcSNishanth Menon * @data: Private data of the governor. The devfreq framework does not 131a3c98b8bSMyungJoo Ham * touch this. 132e09651fcSNishanth Menon * @min_freq: Limit minimum frequency requested by user (0: none) 133e09651fcSNishanth Menon * @max_freq: Limit maximum frequency requested by user (0: none) 134e09651fcSNishanth Menon * @stop_polling: devfreq polling status of a device. 135*e552bbafSJonghwa Lee * @total_trans: Number of devfreq transitions 136*e552bbafSJonghwa Lee * @trans_table: Statistics of devfreq transitions 137*e552bbafSJonghwa Lee * @time_in_state: Statistics of devfreq states 138*e552bbafSJonghwa Lee * @last_stat_updated: The last time stat updated 139a3c98b8bSMyungJoo Ham * 140a3c98b8bSMyungJoo Ham * This structure stores the devfreq information for a give device. 141a3c98b8bSMyungJoo Ham * 142a3c98b8bSMyungJoo Ham * Note that when a governor accesses entries in struct devfreq in its 143a3c98b8bSMyungJoo Ham * functions except for the context of callbacks defined in struct 144a3c98b8bSMyungJoo Ham * devfreq_governor, the governor should protect its access with the 145a3c98b8bSMyungJoo Ham * struct mutex lock in struct devfreq. A governor may use this mutex 146a3c98b8bSMyungJoo Ham * to protect its own private data in void *data as well. 147a3c98b8bSMyungJoo Ham */ 148a3c98b8bSMyungJoo Ham struct devfreq { 149a3c98b8bSMyungJoo Ham struct list_head node; 150a3c98b8bSMyungJoo Ham 151a3c98b8bSMyungJoo Ham struct mutex lock; 152a3c98b8bSMyungJoo Ham struct device dev; 153a3c98b8bSMyungJoo Ham struct devfreq_dev_profile *profile; 154a3c98b8bSMyungJoo Ham const struct devfreq_governor *governor; 155a3c98b8bSMyungJoo Ham struct notifier_block nb; 1567e6fdd4bSRajagopal Venkat struct delayed_work work; 157a3c98b8bSMyungJoo Ham 158a3c98b8bSMyungJoo Ham unsigned long previous_freq; 159a3c98b8bSMyungJoo Ham 160a3c98b8bSMyungJoo Ham void *data; /* private data for governors */ 161a3c98b8bSMyungJoo Ham 1626530b9deSMyungJoo Ham unsigned long min_freq; 1636530b9deSMyungJoo Ham unsigned long max_freq; 1647e6fdd4bSRajagopal Venkat bool stop_polling; 165*e552bbafSJonghwa Lee 166*e552bbafSJonghwa Lee /* information for device freqeuncy transition */ 167*e552bbafSJonghwa Lee unsigned int total_trans; 168*e552bbafSJonghwa Lee unsigned int *trans_table; 169*e552bbafSJonghwa Lee unsigned long *time_in_state; 170*e552bbafSJonghwa Lee unsigned long last_stat_updated; 171a3c98b8bSMyungJoo Ham }; 172a3c98b8bSMyungJoo Ham 173a3c98b8bSMyungJoo Ham #if defined(CONFIG_PM_DEVFREQ) 174a3c98b8bSMyungJoo Ham extern struct devfreq *devfreq_add_device(struct device *dev, 175a3c98b8bSMyungJoo Ham struct devfreq_dev_profile *profile, 176a3c98b8bSMyungJoo Ham const struct devfreq_governor *governor, 177a3c98b8bSMyungJoo Ham void *data); 178a3c98b8bSMyungJoo Ham extern int devfreq_remove_device(struct devfreq *devfreq); 179206c30cfSRajagopal Venkat extern int devfreq_suspend_device(struct devfreq *devfreq); 180206c30cfSRajagopal Venkat extern int devfreq_resume_device(struct devfreq *devfreq); 181a3c98b8bSMyungJoo Ham 182a3c98b8bSMyungJoo Ham /* Helper functions for devfreq user device driver with OPP. */ 183a3c98b8bSMyungJoo Ham extern struct opp *devfreq_recommended_opp(struct device *dev, 184ab5f299fSMyungJoo Ham unsigned long *freq, u32 flags); 185a3c98b8bSMyungJoo Ham extern int devfreq_register_opp_notifier(struct device *dev, 186a3c98b8bSMyungJoo Ham struct devfreq *devfreq); 187a3c98b8bSMyungJoo Ham extern int devfreq_unregister_opp_notifier(struct device *dev, 188a3c98b8bSMyungJoo Ham struct devfreq *devfreq); 189a3c98b8bSMyungJoo Ham 190ce26c5bbSMyungJoo Ham #ifdef CONFIG_DEVFREQ_GOV_POWERSAVE 191ce26c5bbSMyungJoo Ham extern const struct devfreq_governor devfreq_powersave; 192ce26c5bbSMyungJoo Ham #endif 193ce26c5bbSMyungJoo Ham #ifdef CONFIG_DEVFREQ_GOV_PERFORMANCE 194ce26c5bbSMyungJoo Ham extern const struct devfreq_governor devfreq_performance; 195ce26c5bbSMyungJoo Ham #endif 196ce26c5bbSMyungJoo Ham #ifdef CONFIG_DEVFREQ_GOV_USERSPACE 197ce26c5bbSMyungJoo Ham extern const struct devfreq_governor devfreq_userspace; 198ce26c5bbSMyungJoo Ham #endif 199ce26c5bbSMyungJoo Ham #ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND 200ce26c5bbSMyungJoo Ham extern const struct devfreq_governor devfreq_simple_ondemand; 201ce26c5bbSMyungJoo Ham /** 202ce26c5bbSMyungJoo Ham * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq 203ce26c5bbSMyungJoo Ham * and devfreq_add_device 204e09651fcSNishanth Menon * @upthreshold: If the load is over this value, the frequency jumps. 205ce26c5bbSMyungJoo Ham * Specify 0 to use the default. Valid value = 0 to 100. 206e09651fcSNishanth Menon * @downdifferential: If the load is under upthreshold - downdifferential, 207ce26c5bbSMyungJoo Ham * the governor may consider slowing the frequency down. 208ce26c5bbSMyungJoo Ham * Specify 0 to use the default. Valid value = 0 to 100. 209ce26c5bbSMyungJoo Ham * downdifferential < upthreshold must hold. 210ce26c5bbSMyungJoo Ham * 211ce26c5bbSMyungJoo Ham * If the fed devfreq_simple_ondemand_data pointer is NULL to the governor, 212ce26c5bbSMyungJoo Ham * the governor uses the default values. 213ce26c5bbSMyungJoo Ham */ 214ce26c5bbSMyungJoo Ham struct devfreq_simple_ondemand_data { 215ce26c5bbSMyungJoo Ham unsigned int upthreshold; 216ce26c5bbSMyungJoo Ham unsigned int downdifferential; 217ce26c5bbSMyungJoo Ham }; 218ce26c5bbSMyungJoo Ham #endif 219ce26c5bbSMyungJoo Ham 220a3c98b8bSMyungJoo Ham #else /* !CONFIG_PM_DEVFREQ */ 221a3c98b8bSMyungJoo Ham static struct devfreq *devfreq_add_device(struct device *dev, 222a3c98b8bSMyungJoo Ham struct devfreq_dev_profile *profile, 223a3c98b8bSMyungJoo Ham struct devfreq_governor *governor, 224a95e1f5dSMyungJoo Ham void *data) 225a3c98b8bSMyungJoo Ham { 226a3c98b8bSMyungJoo Ham return NULL; 227a3c98b8bSMyungJoo Ham } 228a3c98b8bSMyungJoo Ham 229a95e1f5dSMyungJoo Ham static int devfreq_remove_device(struct devfreq *devfreq) 230a3c98b8bSMyungJoo Ham { 231a3c98b8bSMyungJoo Ham return 0; 232a3c98b8bSMyungJoo Ham } 233a3c98b8bSMyungJoo Ham 234206c30cfSRajagopal Venkat static int devfreq_suspend_device(struct devfreq *devfreq) 235206c30cfSRajagopal Venkat { 236206c30cfSRajagopal Venkat return 0; 237206c30cfSRajagopal Venkat } 238206c30cfSRajagopal Venkat 239206c30cfSRajagopal Venkat static int devfreq_resume_device(struct devfreq *devfreq) 240206c30cfSRajagopal Venkat { 241206c30cfSRajagopal Venkat return 0; 242206c30cfSRajagopal Venkat } 243206c30cfSRajagopal Venkat 244a3c98b8bSMyungJoo Ham static struct opp *devfreq_recommended_opp(struct device *dev, 245ab5f299fSMyungJoo Ham unsigned long *freq, u32 flags) 246a3c98b8bSMyungJoo Ham { 247a3c98b8bSMyungJoo Ham return -EINVAL; 248a3c98b8bSMyungJoo Ham } 249a3c98b8bSMyungJoo Ham 250a3c98b8bSMyungJoo Ham static int devfreq_register_opp_notifier(struct device *dev, 251a3c98b8bSMyungJoo Ham struct devfreq *devfreq) 252a3c98b8bSMyungJoo Ham { 253a3c98b8bSMyungJoo Ham return -EINVAL; 254a3c98b8bSMyungJoo Ham } 255a3c98b8bSMyungJoo Ham 256a3c98b8bSMyungJoo Ham static int devfreq_unregister_opp_notifier(struct device *dev, 257a3c98b8bSMyungJoo Ham struct devfreq *devfreq) 258a3c98b8bSMyungJoo Ham { 259a3c98b8bSMyungJoo Ham return -EINVAL; 260a3c98b8bSMyungJoo Ham } 261a3c98b8bSMyungJoo Ham 262ce26c5bbSMyungJoo Ham #define devfreq_powersave NULL 263ce26c5bbSMyungJoo Ham #define devfreq_performance NULL 264ce26c5bbSMyungJoo Ham #define devfreq_userspace NULL 265ce26c5bbSMyungJoo Ham #define devfreq_simple_ondemand NULL 266ce26c5bbSMyungJoo Ham 267a3c98b8bSMyungJoo Ham #endif /* CONFIG_PM_DEVFREQ */ 268a3c98b8bSMyungJoo Ham 269a3c98b8bSMyungJoo Ham #endif /* __LINUX_DEVFREQ_H__ */ 270