1a76caf55SØrjan Eide /* 2a76caf55SØrjan Eide * devfreq_cooling: Thermal cooling device implementation for devices using 3a76caf55SØrjan Eide * devfreq 4a76caf55SØrjan Eide * 5a76caf55SØrjan Eide * Copyright (C) 2014-2015 ARM Limited 6a76caf55SØrjan Eide * 7a76caf55SØrjan Eide * This program is free software; you can redistribute it and/or modify 8a76caf55SØrjan Eide * it under the terms of the GNU General Public License version 2 as 9a76caf55SØrjan Eide * published by the Free Software Foundation. 10a76caf55SØrjan Eide * 11a76caf55SØrjan Eide * This program is distributed "as is" WITHOUT ANY WARRANTY of any 12a76caf55SØrjan Eide * kind, whether express or implied; without even the implied warranty 13a76caf55SØrjan Eide * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14a76caf55SØrjan Eide * GNU General Public License for more details. 15a76caf55SØrjan Eide * 16a76caf55SØrjan Eide * TODO: 17a76caf55SØrjan Eide * - If OPPs are added or removed after devfreq cooling has 18a76caf55SØrjan Eide * registered, the devfreq cooling won't react to it. 19a76caf55SØrjan Eide */ 20a76caf55SØrjan Eide 21a76caf55SØrjan Eide #include <linux/devfreq.h> 22a76caf55SØrjan Eide #include <linux/devfreq_cooling.h> 23a76caf55SØrjan Eide #include <linux/export.h> 24a76caf55SØrjan Eide #include <linux/slab.h> 25a76caf55SØrjan Eide #include <linux/pm_opp.h> 26a76caf55SØrjan Eide #include <linux/thermal.h> 27a76caf55SØrjan Eide 289876b1a4SJavi Merino #include <trace/events/thermal.h> 299876b1a4SJavi Merino 30a76caf55SØrjan Eide static DEFINE_MUTEX(devfreq_lock); 31a76caf55SØrjan Eide static DEFINE_IDR(devfreq_idr); 32a76caf55SØrjan Eide 33a76caf55SØrjan Eide /** 34a76caf55SØrjan Eide * struct devfreq_cooling_device - Devfreq cooling device 35a76caf55SØrjan Eide * @id: unique integer value corresponding to each 36a76caf55SØrjan Eide * devfreq_cooling_device registered. 37a76caf55SØrjan Eide * @cdev: Pointer to associated thermal cooling device. 38a76caf55SØrjan Eide * @devfreq: Pointer to associated devfreq device. 39a76caf55SØrjan Eide * @cooling_state: Current cooling state. 40a76caf55SØrjan Eide * @power_table: Pointer to table with maximum power draw for each 41a76caf55SØrjan Eide * cooling state. State is the index into the table, and 42a76caf55SØrjan Eide * the power is in mW. 43a76caf55SØrjan Eide * @freq_table: Pointer to a table with the frequencies sorted in descending 44a76caf55SØrjan Eide * order. You can index the table by cooling device state 45a76caf55SØrjan Eide * @freq_table_size: Size of the @freq_table and @power_table 46a76caf55SØrjan Eide * @power_ops: Pointer to devfreq_cooling_power, used to generate the 47a76caf55SØrjan Eide * @power_table. 48a76caf55SØrjan Eide */ 49a76caf55SØrjan Eide struct devfreq_cooling_device { 50a76caf55SØrjan Eide int id; 51a76caf55SØrjan Eide struct thermal_cooling_device *cdev; 52a76caf55SØrjan Eide struct devfreq *devfreq; 53a76caf55SØrjan Eide unsigned long cooling_state; 54a76caf55SØrjan Eide u32 *power_table; 55a76caf55SØrjan Eide u32 *freq_table; 56a76caf55SØrjan Eide size_t freq_table_size; 57a76caf55SØrjan Eide struct devfreq_cooling_power *power_ops; 58a76caf55SØrjan Eide }; 59a76caf55SØrjan Eide 60a76caf55SØrjan Eide /** 61a76caf55SØrjan Eide * get_idr - function to get a unique id. 62a76caf55SØrjan Eide * @idr: struct idr * handle used to create a id. 63a76caf55SØrjan Eide * @id: int * value generated by this function. 64a76caf55SØrjan Eide * 65a76caf55SØrjan Eide * This function will populate @id with an unique 66a76caf55SØrjan Eide * id, using the idr API. 67a76caf55SØrjan Eide * 68a76caf55SØrjan Eide * Return: 0 on success, an error code on failure. 69a76caf55SØrjan Eide */ 70a76caf55SØrjan Eide static int get_idr(struct idr *idr, int *id) 71a76caf55SØrjan Eide { 72a76caf55SØrjan Eide int ret; 73a76caf55SØrjan Eide 74a76caf55SØrjan Eide mutex_lock(&devfreq_lock); 75a76caf55SØrjan Eide ret = idr_alloc(idr, NULL, 0, 0, GFP_KERNEL); 76a76caf55SØrjan Eide mutex_unlock(&devfreq_lock); 77a76caf55SØrjan Eide if (unlikely(ret < 0)) 78a76caf55SØrjan Eide return ret; 79a76caf55SØrjan Eide *id = ret; 80a76caf55SØrjan Eide 81a76caf55SØrjan Eide return 0; 82a76caf55SØrjan Eide } 83a76caf55SØrjan Eide 84a76caf55SØrjan Eide /** 85a76caf55SØrjan Eide * release_idr - function to free the unique id. 86a76caf55SØrjan Eide * @idr: struct idr * handle used for creating the id. 87a76caf55SØrjan Eide * @id: int value representing the unique id. 88a76caf55SØrjan Eide */ 89a76caf55SØrjan Eide static void release_idr(struct idr *idr, int id) 90a76caf55SØrjan Eide { 91a76caf55SØrjan Eide mutex_lock(&devfreq_lock); 92a76caf55SØrjan Eide idr_remove(idr, id); 93a76caf55SØrjan Eide mutex_unlock(&devfreq_lock); 94a76caf55SØrjan Eide } 95a76caf55SØrjan Eide 96a76caf55SØrjan Eide /** 97a76caf55SØrjan Eide * partition_enable_opps() - disable all opps above a given state 98a76caf55SØrjan Eide * @dfc: Pointer to devfreq we are operating on 99a76caf55SØrjan Eide * @cdev_state: cooling device state we're setting 100a76caf55SØrjan Eide * 101a76caf55SØrjan Eide * Go through the OPPs of the device, enabling all OPPs until 102a76caf55SØrjan Eide * @cdev_state and disabling those frequencies above it. 103a76caf55SØrjan Eide */ 104a76caf55SØrjan Eide static int partition_enable_opps(struct devfreq_cooling_device *dfc, 105a76caf55SØrjan Eide unsigned long cdev_state) 106a76caf55SØrjan Eide { 107a76caf55SØrjan Eide int i; 108a76caf55SØrjan Eide struct device *dev = dfc->devfreq->dev.parent; 109a76caf55SØrjan Eide 110a76caf55SØrjan Eide for (i = 0; i < dfc->freq_table_size; i++) { 111a76caf55SØrjan Eide struct dev_pm_opp *opp; 112a76caf55SØrjan Eide int ret = 0; 113a76caf55SØrjan Eide unsigned int freq = dfc->freq_table[i]; 114a76caf55SØrjan Eide bool want_enable = i >= cdev_state ? true : false; 115a76caf55SØrjan Eide 116a76caf55SØrjan Eide rcu_read_lock(); 117a76caf55SØrjan Eide opp = dev_pm_opp_find_freq_exact(dev, freq, !want_enable); 118a76caf55SØrjan Eide rcu_read_unlock(); 119a76caf55SØrjan Eide 120a76caf55SØrjan Eide if (PTR_ERR(opp) == -ERANGE) 121a76caf55SØrjan Eide continue; 122a76caf55SØrjan Eide else if (IS_ERR(opp)) 123a76caf55SØrjan Eide return PTR_ERR(opp); 124a76caf55SØrjan Eide 125a76caf55SØrjan Eide if (want_enable) 126a76caf55SØrjan Eide ret = dev_pm_opp_enable(dev, freq); 127a76caf55SØrjan Eide else 128a76caf55SØrjan Eide ret = dev_pm_opp_disable(dev, freq); 129a76caf55SØrjan Eide 130a76caf55SØrjan Eide if (ret) 131a76caf55SØrjan Eide return ret; 132a76caf55SØrjan Eide } 133a76caf55SØrjan Eide 134a76caf55SØrjan Eide return 0; 135a76caf55SØrjan Eide } 136a76caf55SØrjan Eide 137a76caf55SØrjan Eide static int devfreq_cooling_get_max_state(struct thermal_cooling_device *cdev, 138a76caf55SØrjan Eide unsigned long *state) 139a76caf55SØrjan Eide { 140a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 141a76caf55SØrjan Eide 142a76caf55SØrjan Eide *state = dfc->freq_table_size - 1; 143a76caf55SØrjan Eide 144a76caf55SØrjan Eide return 0; 145a76caf55SØrjan Eide } 146a76caf55SØrjan Eide 147a76caf55SØrjan Eide static int devfreq_cooling_get_cur_state(struct thermal_cooling_device *cdev, 148a76caf55SØrjan Eide unsigned long *state) 149a76caf55SØrjan Eide { 150a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 151a76caf55SØrjan Eide 152a76caf55SØrjan Eide *state = dfc->cooling_state; 153a76caf55SØrjan Eide 154a76caf55SØrjan Eide return 0; 155a76caf55SØrjan Eide } 156a76caf55SØrjan Eide 157a76caf55SØrjan Eide static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev, 158a76caf55SØrjan Eide unsigned long state) 159a76caf55SØrjan Eide { 160a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 161a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 162a76caf55SØrjan Eide struct device *dev = df->dev.parent; 163a76caf55SØrjan Eide int ret; 164a76caf55SØrjan Eide 165a76caf55SØrjan Eide if (state == dfc->cooling_state) 166a76caf55SØrjan Eide return 0; 167a76caf55SØrjan Eide 168a76caf55SØrjan Eide dev_dbg(dev, "Setting cooling state %lu\n", state); 169a76caf55SØrjan Eide 170a76caf55SØrjan Eide if (state >= dfc->freq_table_size) 171a76caf55SØrjan Eide return -EINVAL; 172a76caf55SØrjan Eide 173a76caf55SØrjan Eide ret = partition_enable_opps(dfc, state); 174a76caf55SØrjan Eide if (ret) 175a76caf55SØrjan Eide return ret; 176a76caf55SØrjan Eide 177a76caf55SØrjan Eide dfc->cooling_state = state; 178a76caf55SØrjan Eide 179a76caf55SØrjan Eide return 0; 180a76caf55SØrjan Eide } 181a76caf55SØrjan Eide 182a76caf55SØrjan Eide /** 183a76caf55SØrjan Eide * freq_get_state() - get the cooling state corresponding to a frequency 184a76caf55SØrjan Eide * @dfc: Pointer to devfreq cooling device 185a76caf55SØrjan Eide * @freq: frequency in Hz 186a76caf55SØrjan Eide * 187a76caf55SØrjan Eide * Return: the cooling state associated with the @freq, or 188a76caf55SØrjan Eide * THERMAL_CSTATE_INVALID if it wasn't found. 189a76caf55SØrjan Eide */ 190a76caf55SØrjan Eide static unsigned long 191a76caf55SØrjan Eide freq_get_state(struct devfreq_cooling_device *dfc, unsigned long freq) 192a76caf55SØrjan Eide { 193a76caf55SØrjan Eide int i; 194a76caf55SØrjan Eide 195a76caf55SØrjan Eide for (i = 0; i < dfc->freq_table_size; i++) { 196a76caf55SØrjan Eide if (dfc->freq_table[i] == freq) 197a76caf55SØrjan Eide return i; 198a76caf55SØrjan Eide } 199a76caf55SØrjan Eide 200a76caf55SØrjan Eide return THERMAL_CSTATE_INVALID; 201a76caf55SØrjan Eide } 202a76caf55SØrjan Eide 203a76caf55SØrjan Eide /** 204a76caf55SØrjan Eide * get_static_power() - calculate the static power 205a76caf55SØrjan Eide * @dfc: Pointer to devfreq cooling device 206a76caf55SØrjan Eide * @freq: Frequency in Hz 207a76caf55SØrjan Eide * 208a76caf55SØrjan Eide * Calculate the static power in milliwatts using the supplied 209a76caf55SØrjan Eide * get_static_power(). The current voltage is calculated using the 210a76caf55SØrjan Eide * OPP library. If no get_static_power() was supplied, assume the 211a76caf55SØrjan Eide * static power is negligible. 212a76caf55SØrjan Eide */ 213a76caf55SØrjan Eide static unsigned long 214a76caf55SØrjan Eide get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq) 215a76caf55SØrjan Eide { 216a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 217a76caf55SØrjan Eide struct device *dev = df->dev.parent; 218a76caf55SØrjan Eide unsigned long voltage; 219a76caf55SØrjan Eide struct dev_pm_opp *opp; 220a76caf55SØrjan Eide 221a76caf55SØrjan Eide if (!dfc->power_ops->get_static_power) 222a76caf55SØrjan Eide return 0; 223a76caf55SØrjan Eide 224a76caf55SØrjan Eide rcu_read_lock(); 225a76caf55SØrjan Eide 226a76caf55SØrjan Eide opp = dev_pm_opp_find_freq_exact(dev, freq, true); 227a76caf55SØrjan Eide if (IS_ERR(opp) && (PTR_ERR(opp) == -ERANGE)) 228a76caf55SØrjan Eide opp = dev_pm_opp_find_freq_exact(dev, freq, false); 229a76caf55SØrjan Eide 230a76caf55SØrjan Eide voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ 231a76caf55SØrjan Eide 232a76caf55SØrjan Eide rcu_read_unlock(); 233a76caf55SØrjan Eide 234a76caf55SØrjan Eide if (voltage == 0) { 235a76caf55SØrjan Eide dev_warn_ratelimited(dev, 236a76caf55SØrjan Eide "Failed to get voltage for frequency %lu: %ld\n", 237a76caf55SØrjan Eide freq, IS_ERR(opp) ? PTR_ERR(opp) : 0); 238a76caf55SØrjan Eide return 0; 239a76caf55SØrjan Eide } 240a76caf55SØrjan Eide 241a76caf55SØrjan Eide return dfc->power_ops->get_static_power(voltage); 242a76caf55SØrjan Eide } 243a76caf55SØrjan Eide 244a76caf55SØrjan Eide /** 245a76caf55SØrjan Eide * get_dynamic_power - calculate the dynamic power 246a76caf55SØrjan Eide * @dfc: Pointer to devfreq cooling device 247a76caf55SØrjan Eide * @freq: Frequency in Hz 248a76caf55SØrjan Eide * @voltage: Voltage in millivolts 249a76caf55SØrjan Eide * 250a76caf55SØrjan Eide * Calculate the dynamic power in milliwatts consumed by the device at 251a76caf55SØrjan Eide * frequency @freq and voltage @voltage. If the get_dynamic_power() 252a76caf55SØrjan Eide * was supplied as part of the devfreq_cooling_power struct, then that 253a76caf55SØrjan Eide * function is used. Otherwise, a simple power model (Pdyn = Coeff * 254a76caf55SØrjan Eide * Voltage^2 * Frequency) is used. 255a76caf55SØrjan Eide */ 256a76caf55SØrjan Eide static unsigned long 257a76caf55SØrjan Eide get_dynamic_power(struct devfreq_cooling_device *dfc, unsigned long freq, 258a76caf55SØrjan Eide unsigned long voltage) 259a76caf55SØrjan Eide { 260a76caf55SØrjan Eide unsigned long power; 261a76caf55SØrjan Eide u32 freq_mhz; 262a76caf55SØrjan Eide struct devfreq_cooling_power *dfc_power = dfc->power_ops; 263a76caf55SØrjan Eide 264a76caf55SØrjan Eide if (dfc_power->get_dynamic_power) 265a76caf55SØrjan Eide return dfc_power->get_dynamic_power(freq, voltage); 266a76caf55SØrjan Eide 267a76caf55SØrjan Eide freq_mhz = freq / 1000000; 268a76caf55SØrjan Eide power = (u64)dfc_power->dyn_power_coeff * freq_mhz * voltage * voltage; 269a76caf55SØrjan Eide do_div(power, 1000000000); 270a76caf55SØrjan Eide 271a76caf55SØrjan Eide return power; 272a76caf55SØrjan Eide } 273a76caf55SØrjan Eide 274a76caf55SØrjan Eide static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev, 275a76caf55SØrjan Eide struct thermal_zone_device *tz, 276a76caf55SØrjan Eide u32 *power) 277a76caf55SØrjan Eide { 278a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 279a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 280a76caf55SØrjan Eide struct devfreq_dev_status *status = &df->last_status; 281a76caf55SØrjan Eide unsigned long state; 282a76caf55SØrjan Eide unsigned long freq = status->current_frequency; 283a76caf55SØrjan Eide u32 dyn_power, static_power; 284a76caf55SØrjan Eide 285a76caf55SØrjan Eide /* Get dynamic power for state */ 286a76caf55SØrjan Eide state = freq_get_state(dfc, freq); 287a76caf55SØrjan Eide if (state == THERMAL_CSTATE_INVALID) 288a76caf55SØrjan Eide return -EAGAIN; 289a76caf55SØrjan Eide 290a76caf55SØrjan Eide dyn_power = dfc->power_table[state]; 291a76caf55SØrjan Eide 292a76caf55SØrjan Eide /* Scale dynamic power for utilization */ 293a76caf55SØrjan Eide dyn_power = (dyn_power * status->busy_time) / status->total_time; 294a76caf55SØrjan Eide 295a76caf55SØrjan Eide /* Get static power */ 296a76caf55SØrjan Eide static_power = get_static_power(dfc, freq); 297a76caf55SØrjan Eide 2989876b1a4SJavi Merino trace_thermal_power_devfreq_get_power(cdev, status, freq, dyn_power, 2999876b1a4SJavi Merino static_power); 3009876b1a4SJavi Merino 301a76caf55SØrjan Eide *power = dyn_power + static_power; 302a76caf55SØrjan Eide 303a76caf55SØrjan Eide return 0; 304a76caf55SØrjan Eide } 305a76caf55SØrjan Eide 306a76caf55SØrjan Eide static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev, 307a76caf55SØrjan Eide struct thermal_zone_device *tz, 308a76caf55SØrjan Eide unsigned long state, 309a76caf55SØrjan Eide u32 *power) 310a76caf55SØrjan Eide { 311a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 312a76caf55SØrjan Eide unsigned long freq; 313a76caf55SØrjan Eide u32 static_power; 314a76caf55SØrjan Eide 315a76caf55SØrjan Eide if (state < 0 || state >= dfc->freq_table_size) 316a76caf55SØrjan Eide return -EINVAL; 317a76caf55SØrjan Eide 318a76caf55SØrjan Eide freq = dfc->freq_table[state]; 319a76caf55SØrjan Eide static_power = get_static_power(dfc, freq); 320a76caf55SØrjan Eide 321a76caf55SØrjan Eide *power = dfc->power_table[state] + static_power; 322a76caf55SØrjan Eide return 0; 323a76caf55SØrjan Eide } 324a76caf55SØrjan Eide 325a76caf55SØrjan Eide static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev, 326a76caf55SØrjan Eide struct thermal_zone_device *tz, 327a76caf55SØrjan Eide u32 power, unsigned long *state) 328a76caf55SØrjan Eide { 329a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 330a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 331a76caf55SØrjan Eide struct devfreq_dev_status *status = &df->last_status; 332a76caf55SØrjan Eide unsigned long freq = status->current_frequency; 333a76caf55SØrjan Eide unsigned long busy_time; 334a76caf55SØrjan Eide s32 dyn_power; 335a76caf55SØrjan Eide u32 static_power; 336a76caf55SØrjan Eide int i; 337a76caf55SØrjan Eide 338a76caf55SØrjan Eide static_power = get_static_power(dfc, freq); 339a76caf55SØrjan Eide 340a76caf55SØrjan Eide dyn_power = power - static_power; 341a76caf55SØrjan Eide dyn_power = dyn_power > 0 ? dyn_power : 0; 342a76caf55SØrjan Eide 343a76caf55SØrjan Eide /* Scale dynamic power for utilization */ 344a76caf55SØrjan Eide busy_time = status->busy_time ?: 1; 345a76caf55SØrjan Eide dyn_power = (dyn_power * status->total_time) / busy_time; 346a76caf55SØrjan Eide 347a76caf55SØrjan Eide /* 348a76caf55SØrjan Eide * Find the first cooling state that is within the power 349a76caf55SØrjan Eide * budget for dynamic power. 350a76caf55SØrjan Eide */ 351a76caf55SØrjan Eide for (i = 0; i < dfc->freq_table_size - 1; i++) 352a76caf55SØrjan Eide if (dyn_power >= dfc->power_table[i]) 353a76caf55SØrjan Eide break; 354a76caf55SØrjan Eide 355a76caf55SØrjan Eide *state = i; 3569876b1a4SJavi Merino trace_thermal_power_devfreq_limit(cdev, freq, *state, power); 357a76caf55SØrjan Eide return 0; 358a76caf55SØrjan Eide } 359a76caf55SØrjan Eide 360a76caf55SØrjan Eide static struct thermal_cooling_device_ops devfreq_cooling_ops = { 361a76caf55SØrjan Eide .get_max_state = devfreq_cooling_get_max_state, 362a76caf55SØrjan Eide .get_cur_state = devfreq_cooling_get_cur_state, 363a76caf55SØrjan Eide .set_cur_state = devfreq_cooling_set_cur_state, 364a76caf55SØrjan Eide }; 365a76caf55SØrjan Eide 366a76caf55SØrjan Eide /** 367a76caf55SØrjan Eide * devfreq_cooling_gen_tables() - Generate power and freq tables. 368a76caf55SØrjan Eide * @dfc: Pointer to devfreq cooling device. 369a76caf55SØrjan Eide * 370a76caf55SØrjan Eide * Generate power and frequency tables: the power table hold the 371a76caf55SØrjan Eide * device's maximum power usage at each cooling state (OPP). The 372a76caf55SØrjan Eide * static and dynamic power using the appropriate voltage and 373a76caf55SØrjan Eide * frequency for the state, is acquired from the struct 374a76caf55SØrjan Eide * devfreq_cooling_power, and summed to make the maximum power draw. 375a76caf55SØrjan Eide * 376a76caf55SØrjan Eide * The frequency table holds the frequencies in descending order. 377a76caf55SØrjan Eide * That way its indexed by cooling device state. 378a76caf55SØrjan Eide * 379a76caf55SØrjan Eide * The tables are malloced, and pointers put in dfc. They must be 380a76caf55SØrjan Eide * freed when unregistering the devfreq cooling device. 381a76caf55SØrjan Eide * 382a76caf55SØrjan Eide * Return: 0 on success, negative error code on failure. 383a76caf55SØrjan Eide */ 384a76caf55SØrjan Eide static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc) 385a76caf55SØrjan Eide { 386a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 387a76caf55SØrjan Eide struct device *dev = df->dev.parent; 388a76caf55SØrjan Eide int ret, num_opps; 389a76caf55SØrjan Eide unsigned long freq; 390a76caf55SØrjan Eide u32 *power_table = NULL; 391a76caf55SØrjan Eide u32 *freq_table; 392a76caf55SØrjan Eide int i; 393a76caf55SØrjan Eide 394a76caf55SØrjan Eide num_opps = dev_pm_opp_get_opp_count(dev); 395a76caf55SØrjan Eide 396a76caf55SØrjan Eide if (dfc->power_ops) { 397a76caf55SØrjan Eide power_table = kcalloc(num_opps, sizeof(*power_table), 398a76caf55SØrjan Eide GFP_KERNEL); 399a76caf55SØrjan Eide if (!power_table) 400a76caf55SØrjan Eide ret = -ENOMEM; 401a76caf55SØrjan Eide } 402a76caf55SØrjan Eide 403a76caf55SØrjan Eide freq_table = kcalloc(num_opps, sizeof(*freq_table), 404a76caf55SØrjan Eide GFP_KERNEL); 405a76caf55SØrjan Eide if (!freq_table) { 406a76caf55SØrjan Eide ret = -ENOMEM; 407a76caf55SØrjan Eide goto free_power_table; 408a76caf55SØrjan Eide } 409a76caf55SØrjan Eide 410a76caf55SØrjan Eide for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) { 411a76caf55SØrjan Eide unsigned long power_dyn, voltage; 412a76caf55SØrjan Eide struct dev_pm_opp *opp; 413a76caf55SØrjan Eide 414a76caf55SØrjan Eide rcu_read_lock(); 415a76caf55SØrjan Eide 416a76caf55SØrjan Eide opp = dev_pm_opp_find_freq_floor(dev, &freq); 417a76caf55SØrjan Eide if (IS_ERR(opp)) { 418a76caf55SØrjan Eide rcu_read_unlock(); 419a76caf55SØrjan Eide ret = PTR_ERR(opp); 420a76caf55SØrjan Eide goto free_tables; 421a76caf55SØrjan Eide } 422a76caf55SØrjan Eide 423a76caf55SØrjan Eide voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ 424a76caf55SØrjan Eide 425a76caf55SØrjan Eide rcu_read_unlock(); 426a76caf55SØrjan Eide 427a76caf55SØrjan Eide if (dfc->power_ops) { 428a76caf55SØrjan Eide power_dyn = get_dynamic_power(dfc, freq, voltage); 429a76caf55SØrjan Eide 430a76caf55SØrjan Eide dev_dbg(dev, "Dynamic power table: %lu MHz @ %lu mV: %lu = %lu mW\n", 431a76caf55SØrjan Eide freq / 1000000, voltage, power_dyn, power_dyn); 432a76caf55SØrjan Eide 433a76caf55SØrjan Eide power_table[i] = power_dyn; 434a76caf55SØrjan Eide } 435a76caf55SØrjan Eide 436a76caf55SØrjan Eide freq_table[i] = freq; 437a76caf55SØrjan Eide } 438a76caf55SØrjan Eide 439a76caf55SØrjan Eide if (dfc->power_ops) 440a76caf55SØrjan Eide dfc->power_table = power_table; 441a76caf55SØrjan Eide 442a76caf55SØrjan Eide dfc->freq_table = freq_table; 443a76caf55SØrjan Eide dfc->freq_table_size = num_opps; 444a76caf55SØrjan Eide 445a76caf55SØrjan Eide return 0; 446a76caf55SØrjan Eide 447a76caf55SØrjan Eide free_tables: 448a76caf55SØrjan Eide kfree(freq_table); 449a76caf55SØrjan Eide free_power_table: 450a76caf55SØrjan Eide kfree(power_table); 451a76caf55SØrjan Eide 452a76caf55SØrjan Eide return ret; 453a76caf55SØrjan Eide } 454a76caf55SØrjan Eide 455a76caf55SØrjan Eide /** 456a76caf55SØrjan Eide * of_devfreq_cooling_register_power() - Register devfreq cooling device, 457a76caf55SØrjan Eide * with OF and power information. 458a76caf55SØrjan Eide * @np: Pointer to OF device_node. 459a76caf55SØrjan Eide * @df: Pointer to devfreq device. 460a76caf55SØrjan Eide * @dfc_power: Pointer to devfreq_cooling_power. 461a76caf55SØrjan Eide * 462a76caf55SØrjan Eide * Register a devfreq cooling device. The available OPPs must be 463a76caf55SØrjan Eide * registered on the device. 464a76caf55SØrjan Eide * 465a76caf55SØrjan Eide * If @dfc_power is provided, the cooling device is registered with the 466a76caf55SØrjan Eide * power extensions. For the power extensions to work correctly, 467a76caf55SØrjan Eide * devfreq should use the simple_ondemand governor, other governors 468a76caf55SØrjan Eide * are not currently supported. 469a76caf55SØrjan Eide */ 4703c99c2ceSJavi Merino struct thermal_cooling_device * 471a76caf55SØrjan Eide of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, 472a76caf55SØrjan Eide struct devfreq_cooling_power *dfc_power) 473a76caf55SØrjan Eide { 474a76caf55SØrjan Eide struct thermal_cooling_device *cdev; 475a76caf55SØrjan Eide struct devfreq_cooling_device *dfc; 476a76caf55SØrjan Eide char dev_name[THERMAL_NAME_LENGTH]; 477a76caf55SØrjan Eide int err; 478a76caf55SØrjan Eide 479a76caf55SØrjan Eide dfc = kzalloc(sizeof(*dfc), GFP_KERNEL); 480a76caf55SØrjan Eide if (!dfc) 481a76caf55SØrjan Eide return ERR_PTR(-ENOMEM); 482a76caf55SØrjan Eide 483a76caf55SØrjan Eide dfc->devfreq = df; 484a76caf55SØrjan Eide 485a76caf55SØrjan Eide if (dfc_power) { 486a76caf55SØrjan Eide dfc->power_ops = dfc_power; 487a76caf55SØrjan Eide 488a76caf55SØrjan Eide devfreq_cooling_ops.get_requested_power = 489a76caf55SØrjan Eide devfreq_cooling_get_requested_power; 490a76caf55SØrjan Eide devfreq_cooling_ops.state2power = devfreq_cooling_state2power; 491a76caf55SØrjan Eide devfreq_cooling_ops.power2state = devfreq_cooling_power2state; 492a76caf55SØrjan Eide } 493a76caf55SØrjan Eide 494a76caf55SØrjan Eide err = devfreq_cooling_gen_tables(dfc); 495a76caf55SØrjan Eide if (err) 496a76caf55SØrjan Eide goto free_dfc; 497a76caf55SØrjan Eide 498a76caf55SØrjan Eide err = get_idr(&devfreq_idr, &dfc->id); 499a76caf55SØrjan Eide if (err) 500a76caf55SØrjan Eide goto free_tables; 501a76caf55SØrjan Eide 502a76caf55SØrjan Eide snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id); 503a76caf55SØrjan Eide 504a76caf55SØrjan Eide cdev = thermal_of_cooling_device_register(np, dev_name, dfc, 505a76caf55SØrjan Eide &devfreq_cooling_ops); 506a76caf55SØrjan Eide if (IS_ERR(cdev)) { 507a76caf55SØrjan Eide err = PTR_ERR(cdev); 508a76caf55SØrjan Eide dev_err(df->dev.parent, 509a76caf55SØrjan Eide "Failed to register devfreq cooling device (%d)\n", 510a76caf55SØrjan Eide err); 511a76caf55SØrjan Eide goto release_idr; 512a76caf55SØrjan Eide } 513a76caf55SØrjan Eide 514a76caf55SØrjan Eide dfc->cdev = cdev; 515a76caf55SØrjan Eide 5163c99c2ceSJavi Merino return cdev; 517a76caf55SØrjan Eide 518a76caf55SØrjan Eide release_idr: 519a76caf55SØrjan Eide release_idr(&devfreq_idr, dfc->id); 520a76caf55SØrjan Eide free_tables: 521a76caf55SØrjan Eide kfree(dfc->power_table); 522a76caf55SØrjan Eide kfree(dfc->freq_table); 523a76caf55SØrjan Eide free_dfc: 524a76caf55SØrjan Eide kfree(dfc); 525a76caf55SØrjan Eide 526a76caf55SØrjan Eide return ERR_PTR(err); 527a76caf55SØrjan Eide } 528a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(of_devfreq_cooling_register_power); 529a76caf55SØrjan Eide 530a76caf55SØrjan Eide /** 531a76caf55SØrjan Eide * of_devfreq_cooling_register() - Register devfreq cooling device, 532a76caf55SØrjan Eide * with OF information. 533a76caf55SØrjan Eide * @np: Pointer to OF device_node. 534a76caf55SØrjan Eide * @df: Pointer to devfreq device. 535a76caf55SØrjan Eide */ 5363c99c2ceSJavi Merino struct thermal_cooling_device * 537a76caf55SØrjan Eide of_devfreq_cooling_register(struct device_node *np, struct devfreq *df) 538a76caf55SØrjan Eide { 539a76caf55SØrjan Eide return of_devfreq_cooling_register_power(np, df, NULL); 540a76caf55SØrjan Eide } 541a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(of_devfreq_cooling_register); 542a76caf55SØrjan Eide 543a76caf55SØrjan Eide /** 544a76caf55SØrjan Eide * devfreq_cooling_register() - Register devfreq cooling device. 545a76caf55SØrjan Eide * @df: Pointer to devfreq device. 546a76caf55SØrjan Eide */ 5473c99c2ceSJavi Merino struct thermal_cooling_device *devfreq_cooling_register(struct devfreq *df) 548a76caf55SØrjan Eide { 549a76caf55SØrjan Eide return of_devfreq_cooling_register(NULL, df); 550a76caf55SØrjan Eide } 551a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(devfreq_cooling_register); 552a76caf55SØrjan Eide 553a76caf55SØrjan Eide /** 554a76caf55SØrjan Eide * devfreq_cooling_unregister() - Unregister devfreq cooling device. 555a76caf55SØrjan Eide * @dfc: Pointer to devfreq cooling device to unregister. 556a76caf55SØrjan Eide */ 5573c99c2ceSJavi Merino void devfreq_cooling_unregister(struct thermal_cooling_device *cdev) 558a76caf55SØrjan Eide { 5593c99c2ceSJavi Merino struct devfreq_cooling_device *dfc; 5603c99c2ceSJavi Merino 5613c99c2ceSJavi Merino if (!cdev) 562a76caf55SØrjan Eide return; 563a76caf55SØrjan Eide 5643c99c2ceSJavi Merino dfc = cdev->devdata; 5653c99c2ceSJavi Merino 566a76caf55SØrjan Eide thermal_cooling_device_unregister(dfc->cdev); 567a76caf55SØrjan Eide release_idr(&devfreq_idr, dfc->id); 568a76caf55SØrjan Eide kfree(dfc->power_table); 569a76caf55SØrjan Eide kfree(dfc->freq_table); 570a76caf55SØrjan Eide 571a76caf55SØrjan Eide kfree(dfc); 572a76caf55SØrjan Eide } 573a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(devfreq_cooling_unregister); 574