10de967f2SLukasz Luba // SPDX-License-Identifier: GPL-2.0 2a76caf55SØrjan Eide /* 3a76caf55SØrjan Eide * devfreq_cooling: Thermal cooling device implementation for devices using 4a76caf55SØrjan Eide * devfreq 5a76caf55SØrjan Eide * 6a76caf55SØrjan Eide * Copyright (C) 2014-2015 ARM Limited 7a76caf55SØrjan Eide * 8a76caf55SØrjan Eide * TODO: 9a76caf55SØrjan Eide * - If OPPs are added or removed after devfreq cooling has 10a76caf55SØrjan Eide * registered, the devfreq cooling won't react to it. 11a76caf55SØrjan Eide */ 12a76caf55SØrjan Eide 13a76caf55SØrjan Eide #include <linux/devfreq.h> 14a76caf55SØrjan Eide #include <linux/devfreq_cooling.h> 1584e0d87cSLukasz Luba #include <linux/energy_model.h> 16a76caf55SØrjan Eide #include <linux/export.h> 172f96c035SMatthew Wilcox #include <linux/idr.h> 18a76caf55SØrjan Eide #include <linux/slab.h> 19a76caf55SØrjan Eide #include <linux/pm_opp.h> 2004fa9c80SMatthias Kaehlcke #include <linux/pm_qos.h> 21a76caf55SØrjan Eide #include <linux/thermal.h> 22a76caf55SØrjan Eide 239876b1a4SJavi Merino #include <trace/events/thermal.h> 249876b1a4SJavi Merino 2504fa9c80SMatthias Kaehlcke #define HZ_PER_KHZ 1000 262be83da8SLukasz Luba #define SCALE_ERROR_MITIGATION 100 272be83da8SLukasz Luba 282f96c035SMatthew Wilcox static DEFINE_IDA(devfreq_ida); 29a76caf55SØrjan Eide 30a76caf55SØrjan Eide /** 31a76caf55SØrjan Eide * struct devfreq_cooling_device - Devfreq cooling device 32a76caf55SØrjan Eide * @id: unique integer value corresponding to each 33a76caf55SØrjan Eide * devfreq_cooling_device registered. 34a76caf55SØrjan Eide * @cdev: Pointer to associated thermal cooling device. 35a76caf55SØrjan Eide * @devfreq: Pointer to associated devfreq device. 36a76caf55SØrjan Eide * @cooling_state: Current cooling state. 37a76caf55SØrjan Eide * @freq_table: Pointer to a table with the frequencies sorted in descending 38a76caf55SØrjan Eide * order. You can index the table by cooling device state 39*615510feSLukasz Luba * @max_state: It is the last index, that is, one less than the number of the 40*615510feSLukasz Luba * OPPs 41*615510feSLukasz Luba * @power_ops: Pointer to devfreq_cooling_power, a more precised model. 422be83da8SLukasz Luba * @res_util: Resource utilization scaling factor for the power. 432be83da8SLukasz Luba * It is multiplied by 100 to minimize the error. It is used 442be83da8SLukasz Luba * for estimation of the power budget instead of using 45*615510feSLukasz Luba * 'utilization' (which is 'busy_time' / 'total_time'). 46*615510feSLukasz Luba * The 'res_util' range is from 100 to power * 100 for the 47*615510feSLukasz Luba * corresponding 'state'. 481b5cb957SAmit Kucheria * @capped_state: index to cooling state with in dynamic power budget 4904fa9c80SMatthias Kaehlcke * @req_max_freq: PM QoS request for limiting the maximum frequency 5004fa9c80SMatthias Kaehlcke * of the devfreq device. 51a76caf55SØrjan Eide */ 52a76caf55SØrjan Eide struct devfreq_cooling_device { 53a76caf55SØrjan Eide int id; 54a76caf55SØrjan Eide struct thermal_cooling_device *cdev; 55a76caf55SØrjan Eide struct devfreq *devfreq; 56a76caf55SØrjan Eide unsigned long cooling_state; 57a76caf55SØrjan Eide u32 *freq_table; 58*615510feSLukasz Luba size_t max_state; 59a76caf55SØrjan Eide struct devfreq_cooling_power *power_ops; 602be83da8SLukasz Luba u32 res_util; 612be83da8SLukasz Luba int capped_state; 6204fa9c80SMatthias Kaehlcke struct dev_pm_qos_request req_max_freq; 63a76caf55SØrjan Eide }; 64a76caf55SØrjan Eide 65a76caf55SØrjan Eide static int devfreq_cooling_get_max_state(struct thermal_cooling_device *cdev, 66a76caf55SØrjan Eide unsigned long *state) 67a76caf55SØrjan Eide { 68a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 69a76caf55SØrjan Eide 70*615510feSLukasz Luba *state = dfc->max_state; 71a76caf55SØrjan Eide 72a76caf55SØrjan Eide return 0; 73a76caf55SØrjan Eide } 74a76caf55SØrjan Eide 75a76caf55SØrjan Eide static int devfreq_cooling_get_cur_state(struct thermal_cooling_device *cdev, 76a76caf55SØrjan Eide unsigned long *state) 77a76caf55SØrjan Eide { 78a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 79a76caf55SØrjan Eide 80a76caf55SØrjan Eide *state = dfc->cooling_state; 81a76caf55SØrjan Eide 82a76caf55SØrjan Eide return 0; 83a76caf55SØrjan Eide } 84a76caf55SØrjan Eide 85a76caf55SØrjan Eide static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev, 86a76caf55SØrjan Eide unsigned long state) 87a76caf55SØrjan Eide { 88a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 89a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 90a76caf55SØrjan Eide struct device *dev = df->dev.parent; 9104fa9c80SMatthias Kaehlcke unsigned long freq; 92*615510feSLukasz Luba int perf_idx; 93a76caf55SØrjan Eide 94a76caf55SØrjan Eide if (state == dfc->cooling_state) 95a76caf55SØrjan Eide return 0; 96a76caf55SØrjan Eide 97a76caf55SØrjan Eide dev_dbg(dev, "Setting cooling state %lu\n", state); 98a76caf55SØrjan Eide 99*615510feSLukasz Luba if (state > dfc->max_state) 100a76caf55SØrjan Eide return -EINVAL; 101a76caf55SØrjan Eide 102*615510feSLukasz Luba if (dev->em_pd) { 103*615510feSLukasz Luba perf_idx = dfc->max_state - state; 104*615510feSLukasz Luba freq = dev->em_pd->table[perf_idx].frequency * 1000; 105*615510feSLukasz Luba } else { 10604fa9c80SMatthias Kaehlcke freq = dfc->freq_table[state]; 107*615510feSLukasz Luba } 10804fa9c80SMatthias Kaehlcke 10904fa9c80SMatthias Kaehlcke dev_pm_qos_update_request(&dfc->req_max_freq, 11004fa9c80SMatthias Kaehlcke DIV_ROUND_UP(freq, HZ_PER_KHZ)); 111a76caf55SØrjan Eide 112a76caf55SØrjan Eide dfc->cooling_state = state; 113a76caf55SØrjan Eide 114a76caf55SØrjan Eide return 0; 115a76caf55SØrjan Eide } 116a76caf55SØrjan Eide 117a76caf55SØrjan Eide /** 118*615510feSLukasz Luba * get_perf_idx() - get the performance index corresponding to a frequency 119*615510feSLukasz Luba * @em_pd: Pointer to device's Energy Model 120*615510feSLukasz Luba * @freq: frequency in kHz 121a76caf55SØrjan Eide * 122*615510feSLukasz Luba * Return: the performance index associated with the @freq, or 123*615510feSLukasz Luba * -EINVAL if it wasn't found. 124a76caf55SØrjan Eide */ 125*615510feSLukasz Luba static int get_perf_idx(struct em_perf_domain *em_pd, unsigned long freq) 126a76caf55SØrjan Eide { 127a76caf55SØrjan Eide int i; 128a76caf55SØrjan Eide 129*615510feSLukasz Luba for (i = 0; i < em_pd->nr_perf_states; i++) { 130*615510feSLukasz Luba if (em_pd->table[i].frequency == freq) 131a76caf55SØrjan Eide return i; 132a76caf55SØrjan Eide } 133a76caf55SØrjan Eide 134*615510feSLukasz Luba return -EINVAL; 135a76caf55SØrjan Eide } 136a76caf55SØrjan Eide 137e34cab4cSLukasz Luba static unsigned long get_voltage(struct devfreq *df, unsigned long freq) 138a76caf55SØrjan Eide { 139a76caf55SØrjan Eide struct device *dev = df->dev.parent; 140a76caf55SØrjan Eide unsigned long voltage; 141a76caf55SØrjan Eide struct dev_pm_opp *opp; 142a76caf55SØrjan Eide 143a76caf55SØrjan Eide opp = dev_pm_opp_find_freq_exact(dev, freq, true); 144a4e49c9bSViresh Kumar if (PTR_ERR(opp) == -ERANGE) 145a76caf55SØrjan Eide opp = dev_pm_opp_find_freq_exact(dev, freq, false); 146a76caf55SØrjan Eide 147afd1f4e0SViresh Kumar if (IS_ERR(opp)) { 148afd1f4e0SViresh Kumar dev_err_ratelimited(dev, "Failed to find OPP for frequency %lu: %ld\n", 149afd1f4e0SViresh Kumar freq, PTR_ERR(opp)); 150afd1f4e0SViresh Kumar return 0; 151afd1f4e0SViresh Kumar } 152afd1f4e0SViresh Kumar 153a76caf55SØrjan Eide voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ 1548a31d9d9SViresh Kumar dev_pm_opp_put(opp); 155a76caf55SØrjan Eide 156a76caf55SØrjan Eide if (voltage == 0) { 1578327b830SViresh Kumar dev_err_ratelimited(dev, 158afd1f4e0SViresh Kumar "Failed to get voltage for frequency %lu\n", 159afd1f4e0SViresh Kumar freq); 160a76caf55SØrjan Eide } 161a76caf55SØrjan Eide 162e34cab4cSLukasz Luba return voltage; 163e34cab4cSLukasz Luba } 164e34cab4cSLukasz Luba 165229794eeSLukasz Luba static void _normalize_load(struct devfreq_dev_status *status) 166229794eeSLukasz Luba { 167229794eeSLukasz Luba if (status->total_time > 0xfffff) { 168229794eeSLukasz Luba status->total_time >>= 10; 169229794eeSLukasz Luba status->busy_time >>= 10; 170229794eeSLukasz Luba } 171229794eeSLukasz Luba 172229794eeSLukasz Luba status->busy_time <<= 10; 173229794eeSLukasz Luba status->busy_time /= status->total_time ? : 1; 174229794eeSLukasz Luba 175229794eeSLukasz Luba status->busy_time = status->busy_time ? : 1; 176229794eeSLukasz Luba status->total_time = 1024; 177229794eeSLukasz Luba } 1782be83da8SLukasz Luba 179a76caf55SØrjan Eide static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev, 180a76caf55SØrjan Eide u32 *power) 181a76caf55SØrjan Eide { 182a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 183a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 184*615510feSLukasz Luba struct device *dev = df->dev.parent; 185229794eeSLukasz Luba struct devfreq_dev_status status; 186a76caf55SØrjan Eide unsigned long state; 187229794eeSLukasz Luba unsigned long freq; 1882be83da8SLukasz Luba unsigned long voltage; 189*615510feSLukasz Luba int res, perf_idx; 190a76caf55SØrjan Eide 191229794eeSLukasz Luba mutex_lock(&df->lock); 192229794eeSLukasz Luba status = df->last_status; 193229794eeSLukasz Luba mutex_unlock(&df->lock); 194229794eeSLukasz Luba 195229794eeSLukasz Luba freq = status.current_frequency; 196229794eeSLukasz Luba 197*615510feSLukasz Luba if (dfc->power_ops && dfc->power_ops->get_real_power) { 1982be83da8SLukasz Luba voltage = get_voltage(df, freq); 1992be83da8SLukasz Luba if (voltage == 0) { 2002be83da8SLukasz Luba res = -EINVAL; 2012be83da8SLukasz Luba goto fail; 2022be83da8SLukasz Luba } 2032be83da8SLukasz Luba 2042be83da8SLukasz Luba res = dfc->power_ops->get_real_power(df, power, freq, voltage); 2052be83da8SLukasz Luba if (!res) { 2062be83da8SLukasz Luba state = dfc->capped_state; 207*615510feSLukasz Luba dfc->res_util = dev->em_pd->table[state].power; 2082be83da8SLukasz Luba dfc->res_util *= SCALE_ERROR_MITIGATION; 2092be83da8SLukasz Luba 2102be83da8SLukasz Luba if (*power > 1) 2112be83da8SLukasz Luba dfc->res_util /= *power; 2122be83da8SLukasz Luba } else { 2132be83da8SLukasz Luba goto fail; 2142be83da8SLukasz Luba } 2152be83da8SLukasz Luba } else { 216*615510feSLukasz Luba /* Energy Model frequencies are in kHz */ 217*615510feSLukasz Luba perf_idx = get_perf_idx(dev->em_pd, freq / 1000); 218*615510feSLukasz Luba if (perf_idx < 0) { 219*615510feSLukasz Luba res = -EAGAIN; 220*615510feSLukasz Luba goto fail; 221*615510feSLukasz Luba } 222a76caf55SØrjan Eide 223229794eeSLukasz Luba _normalize_load(&status); 224229794eeSLukasz Luba 225*615510feSLukasz Luba /* Scale power for utilization */ 226*615510feSLukasz Luba *power = dev->em_pd->table[perf_idx].power; 227*615510feSLukasz Luba *power *= status.busy_time; 228*615510feSLukasz Luba *power >>= 10; 2292be83da8SLukasz Luba } 2302be83da8SLukasz Luba 231229794eeSLukasz Luba trace_thermal_power_devfreq_get_power(cdev, &status, freq, *power); 2329876b1a4SJavi Merino 233a76caf55SØrjan Eide return 0; 2342be83da8SLukasz Luba fail: 2352be83da8SLukasz Luba /* It is safe to set max in this case */ 2362be83da8SLukasz Luba dfc->res_util = SCALE_ERROR_MITIGATION; 2372be83da8SLukasz Luba return res; 238a76caf55SØrjan Eide } 239a76caf55SØrjan Eide 240a76caf55SØrjan Eide static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev, 241*615510feSLukasz Luba unsigned long state, u32 *power) 242a76caf55SØrjan Eide { 243a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 244*615510feSLukasz Luba struct devfreq *df = dfc->devfreq; 245*615510feSLukasz Luba struct device *dev = df->dev.parent; 246*615510feSLukasz Luba int perf_idx; 247a76caf55SØrjan Eide 248*615510feSLukasz Luba if (state > dfc->max_state) 249a76caf55SØrjan Eide return -EINVAL; 250a76caf55SØrjan Eide 251*615510feSLukasz Luba perf_idx = dfc->max_state - state; 252*615510feSLukasz Luba *power = dev->em_pd->table[perf_idx].power; 253a76caf55SØrjan Eide 254a76caf55SØrjan Eide return 0; 255a76caf55SØrjan Eide } 256a76caf55SØrjan Eide 257a76caf55SØrjan Eide static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev, 258a76caf55SØrjan Eide u32 power, unsigned long *state) 259a76caf55SØrjan Eide { 260a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 261a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 262*615510feSLukasz Luba struct device *dev = df->dev.parent; 263229794eeSLukasz Luba struct devfreq_dev_status status; 264229794eeSLukasz Luba unsigned long freq; 2652be83da8SLukasz Luba s32 est_power; 266a76caf55SØrjan Eide int i; 267a76caf55SØrjan Eide 268229794eeSLukasz Luba mutex_lock(&df->lock); 269229794eeSLukasz Luba status = df->last_status; 270229794eeSLukasz Luba mutex_unlock(&df->lock); 271229794eeSLukasz Luba 272229794eeSLukasz Luba freq = status.current_frequency; 273229794eeSLukasz Luba 274*615510feSLukasz Luba if (dfc->power_ops && dfc->power_ops->get_real_power) { 2752be83da8SLukasz Luba /* Scale for resource utilization */ 2762be83da8SLukasz Luba est_power = power * dfc->res_util; 2772be83da8SLukasz Luba est_power /= SCALE_ERROR_MITIGATION; 2782be83da8SLukasz Luba } else { 279a76caf55SØrjan Eide /* Scale dynamic power for utilization */ 280229794eeSLukasz Luba _normalize_load(&status); 281*615510feSLukasz Luba est_power = power << 10; 282*615510feSLukasz Luba est_power /= status.busy_time; 2832be83da8SLukasz Luba } 284a76caf55SØrjan Eide 285a76caf55SØrjan Eide /* 286a76caf55SØrjan Eide * Find the first cooling state that is within the power 287*615510feSLukasz Luba * budget. The EM power table is sorted ascending. 288a76caf55SØrjan Eide */ 289*615510feSLukasz Luba for (i = dfc->max_state; i > 0; i--) 290*615510feSLukasz Luba if (est_power >= dev->em_pd->table[i].power) 291a76caf55SØrjan Eide break; 292a76caf55SØrjan Eide 293*615510feSLukasz Luba *state = dfc->max_state - i; 294*615510feSLukasz Luba dfc->capped_state = *state; 295*615510feSLukasz Luba 2969876b1a4SJavi Merino trace_thermal_power_devfreq_limit(cdev, freq, *state, power); 297a76caf55SØrjan Eide return 0; 298a76caf55SØrjan Eide } 299a76caf55SØrjan Eide 300a76caf55SØrjan Eide static struct thermal_cooling_device_ops devfreq_cooling_ops = { 301a76caf55SØrjan Eide .get_max_state = devfreq_cooling_get_max_state, 302a76caf55SØrjan Eide .get_cur_state = devfreq_cooling_get_cur_state, 303a76caf55SØrjan Eide .set_cur_state = devfreq_cooling_set_cur_state, 304a76caf55SØrjan Eide }; 305a76caf55SØrjan Eide 306a76caf55SØrjan Eide /** 307*615510feSLukasz Luba * devfreq_cooling_gen_tables() - Generate frequency table. 308a76caf55SØrjan Eide * @dfc: Pointer to devfreq cooling device. 309*615510feSLukasz Luba * @num_opps: Number of OPPs 310a76caf55SØrjan Eide * 311*615510feSLukasz Luba * Generate frequency table which holds the frequencies in descending 312*615510feSLukasz Luba * order. That way its indexed by cooling device state. This is for 313*615510feSLukasz Luba * compatibility with drivers which do not register Energy Model. 314a76caf55SØrjan Eide * 315a76caf55SØrjan Eide * Return: 0 on success, negative error code on failure. 316a76caf55SØrjan Eide */ 317*615510feSLukasz Luba static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc, 318*615510feSLukasz Luba int num_opps) 319a76caf55SØrjan Eide { 320a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 321a76caf55SØrjan Eide struct device *dev = df->dev.parent; 322a76caf55SØrjan Eide unsigned long freq; 323a76caf55SØrjan Eide int i; 324a76caf55SØrjan Eide 325*615510feSLukasz Luba dfc->freq_table = kcalloc(num_opps, sizeof(*dfc->freq_table), 326a76caf55SØrjan Eide GFP_KERNEL); 327*615510feSLukasz Luba if (!dfc->freq_table) 328ce5ee161SDan Carpenter return -ENOMEM; 329a76caf55SØrjan Eide 330a76caf55SØrjan Eide for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) { 331a76caf55SØrjan Eide struct dev_pm_opp *opp; 332a76caf55SØrjan Eide 333a76caf55SØrjan Eide opp = dev_pm_opp_find_freq_floor(dev, &freq); 334a76caf55SØrjan Eide if (IS_ERR(opp)) { 335*615510feSLukasz Luba kfree(dfc->freq_table); 336*615510feSLukasz Luba return PTR_ERR(opp); 337a76caf55SØrjan Eide } 338a76caf55SØrjan Eide 3398a31d9d9SViresh Kumar dev_pm_opp_put(opp); 340*615510feSLukasz Luba dfc->freq_table[i] = freq; 341a76caf55SØrjan Eide } 342a76caf55SØrjan Eide 343a76caf55SØrjan Eide return 0; 344a76caf55SØrjan Eide } 345a76caf55SØrjan Eide 346a76caf55SØrjan Eide /** 347a76caf55SØrjan Eide * of_devfreq_cooling_register_power() - Register devfreq cooling device, 348a76caf55SØrjan Eide * with OF and power information. 349a76caf55SØrjan Eide * @np: Pointer to OF device_node. 350a76caf55SØrjan Eide * @df: Pointer to devfreq device. 351a76caf55SØrjan Eide * @dfc_power: Pointer to devfreq_cooling_power. 352a76caf55SØrjan Eide * 353a76caf55SØrjan Eide * Register a devfreq cooling device. The available OPPs must be 354a76caf55SØrjan Eide * registered on the device. 355a76caf55SØrjan Eide * 356a76caf55SØrjan Eide * If @dfc_power is provided, the cooling device is registered with the 357a76caf55SØrjan Eide * power extensions. For the power extensions to work correctly, 358a76caf55SØrjan Eide * devfreq should use the simple_ondemand governor, other governors 359a76caf55SØrjan Eide * are not currently supported. 360a76caf55SØrjan Eide */ 3613c99c2ceSJavi Merino struct thermal_cooling_device * 362a76caf55SØrjan Eide of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, 363a76caf55SØrjan Eide struct devfreq_cooling_power *dfc_power) 364a76caf55SØrjan Eide { 365a76caf55SØrjan Eide struct thermal_cooling_device *cdev; 366*615510feSLukasz Luba struct device *dev = df->dev.parent; 367a76caf55SØrjan Eide struct devfreq_cooling_device *dfc; 368a76caf55SØrjan Eide char dev_name[THERMAL_NAME_LENGTH]; 369*615510feSLukasz Luba int err, num_opps; 370a76caf55SØrjan Eide 371a76caf55SØrjan Eide dfc = kzalloc(sizeof(*dfc), GFP_KERNEL); 372a76caf55SØrjan Eide if (!dfc) 373a76caf55SØrjan Eide return ERR_PTR(-ENOMEM); 374a76caf55SØrjan Eide 375a76caf55SØrjan Eide dfc->devfreq = df; 376a76caf55SØrjan Eide 377*615510feSLukasz Luba if (dev->em_pd) { 378a76caf55SØrjan Eide devfreq_cooling_ops.get_requested_power = 379a76caf55SØrjan Eide devfreq_cooling_get_requested_power; 380a76caf55SØrjan Eide devfreq_cooling_ops.state2power = devfreq_cooling_state2power; 381a76caf55SØrjan Eide devfreq_cooling_ops.power2state = devfreq_cooling_power2state; 382a76caf55SØrjan Eide 383*615510feSLukasz Luba dfc->power_ops = dfc_power; 384*615510feSLukasz Luba 385*615510feSLukasz Luba num_opps = em_pd_nr_perf_states(dev->em_pd); 386*615510feSLukasz Luba } else { 387*615510feSLukasz Luba /* Backward compatibility for drivers which do not use IPA */ 388*615510feSLukasz Luba dev_dbg(dev, "missing EM for cooling device\n"); 389*615510feSLukasz Luba 390*615510feSLukasz Luba num_opps = dev_pm_opp_get_opp_count(dev); 391*615510feSLukasz Luba 392*615510feSLukasz Luba err = devfreq_cooling_gen_tables(dfc, num_opps); 393a76caf55SØrjan Eide if (err) 394a76caf55SØrjan Eide goto free_dfc; 395*615510feSLukasz Luba } 396a76caf55SØrjan Eide 397*615510feSLukasz Luba if (num_opps <= 0) { 398*615510feSLukasz Luba err = -EINVAL; 399*615510feSLukasz Luba goto free_dfc; 400*615510feSLukasz Luba } 401*615510feSLukasz Luba 402*615510feSLukasz Luba /* max_state is an index, not a counter */ 403*615510feSLukasz Luba dfc->max_state = num_opps - 1; 404*615510feSLukasz Luba 405*615510feSLukasz Luba err = dev_pm_qos_add_request(dev, &dfc->req_max_freq, 40604fa9c80SMatthias Kaehlcke DEV_PM_QOS_MAX_FREQUENCY, 40704fa9c80SMatthias Kaehlcke PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE); 4082f96c035SMatthew Wilcox if (err < 0) 409*615510feSLukasz Luba goto free_table; 41004fa9c80SMatthias Kaehlcke 41104fa9c80SMatthias Kaehlcke err = ida_simple_get(&devfreq_ida, 0, 0, GFP_KERNEL); 41204fa9c80SMatthias Kaehlcke if (err < 0) 41304fa9c80SMatthias Kaehlcke goto remove_qos_req; 414*615510feSLukasz Luba 4152f96c035SMatthew Wilcox dfc->id = err; 416a76caf55SØrjan Eide 417a76caf55SØrjan Eide snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id); 418a76caf55SØrjan Eide 419a76caf55SØrjan Eide cdev = thermal_of_cooling_device_register(np, dev_name, dfc, 420a76caf55SØrjan Eide &devfreq_cooling_ops); 421a76caf55SØrjan Eide if (IS_ERR(cdev)) { 422a76caf55SØrjan Eide err = PTR_ERR(cdev); 423*615510feSLukasz Luba dev_err(dev, 424a76caf55SØrjan Eide "Failed to register devfreq cooling device (%d)\n", 425a76caf55SØrjan Eide err); 4262f96c035SMatthew Wilcox goto release_ida; 427a76caf55SØrjan Eide } 428a76caf55SØrjan Eide 429a76caf55SØrjan Eide dfc->cdev = cdev; 430a76caf55SØrjan Eide 4313c99c2ceSJavi Merino return cdev; 432a76caf55SØrjan Eide 4332f96c035SMatthew Wilcox release_ida: 4342f96c035SMatthew Wilcox ida_simple_remove(&devfreq_ida, dfc->id); 43504fa9c80SMatthias Kaehlcke remove_qos_req: 43604fa9c80SMatthias Kaehlcke dev_pm_qos_remove_request(&dfc->req_max_freq); 437*615510feSLukasz Luba free_table: 438a76caf55SØrjan Eide kfree(dfc->freq_table); 439a76caf55SØrjan Eide free_dfc: 440a76caf55SØrjan Eide kfree(dfc); 441a76caf55SØrjan Eide 442a76caf55SØrjan Eide return ERR_PTR(err); 443a76caf55SØrjan Eide } 444a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(of_devfreq_cooling_register_power); 445a76caf55SØrjan Eide 446a76caf55SØrjan Eide /** 447a76caf55SØrjan Eide * of_devfreq_cooling_register() - Register devfreq cooling device, 448a76caf55SØrjan Eide * with OF information. 449a76caf55SØrjan Eide * @np: Pointer to OF device_node. 450a76caf55SØrjan Eide * @df: Pointer to devfreq device. 451a76caf55SØrjan Eide */ 4523c99c2ceSJavi Merino struct thermal_cooling_device * 453a76caf55SØrjan Eide of_devfreq_cooling_register(struct device_node *np, struct devfreq *df) 454a76caf55SØrjan Eide { 455a76caf55SØrjan Eide return of_devfreq_cooling_register_power(np, df, NULL); 456a76caf55SØrjan Eide } 457a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(of_devfreq_cooling_register); 458a76caf55SØrjan Eide 459a76caf55SØrjan Eide /** 460a76caf55SØrjan Eide * devfreq_cooling_register() - Register devfreq cooling device. 461a76caf55SØrjan Eide * @df: Pointer to devfreq device. 462a76caf55SØrjan Eide */ 4633c99c2ceSJavi Merino struct thermal_cooling_device *devfreq_cooling_register(struct devfreq *df) 464a76caf55SØrjan Eide { 465a76caf55SØrjan Eide return of_devfreq_cooling_register(NULL, df); 466a76caf55SØrjan Eide } 467a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(devfreq_cooling_register); 468a76caf55SØrjan Eide 469a76caf55SØrjan Eide /** 47084e0d87cSLukasz Luba * devfreq_cooling_em_register_power() - Register devfreq cooling device with 47184e0d87cSLukasz Luba * power information and automatically register Energy Model (EM) 47284e0d87cSLukasz Luba * @df: Pointer to devfreq device. 47384e0d87cSLukasz Luba * @dfc_power: Pointer to devfreq_cooling_power. 47484e0d87cSLukasz Luba * 47584e0d87cSLukasz Luba * Register a devfreq cooling device and automatically register EM. The 47684e0d87cSLukasz Luba * available OPPs must be registered for the device. 47784e0d87cSLukasz Luba * 47884e0d87cSLukasz Luba * If @dfc_power is provided, the cooling device is registered with the 47984e0d87cSLukasz Luba * power extensions. It is using the simple Energy Model which requires 48084e0d87cSLukasz Luba * "dynamic-power-coefficient" a devicetree property. To not break drivers 48184e0d87cSLukasz Luba * which miss that DT property, the function won't bail out when the EM 48284e0d87cSLukasz Luba * registration failed. The cooling device will be registered if everything 48384e0d87cSLukasz Luba * else is OK. 48484e0d87cSLukasz Luba */ 48584e0d87cSLukasz Luba struct thermal_cooling_device * 48684e0d87cSLukasz Luba devfreq_cooling_em_register(struct devfreq *df, 48784e0d87cSLukasz Luba struct devfreq_cooling_power *dfc_power) 48884e0d87cSLukasz Luba { 48984e0d87cSLukasz Luba struct thermal_cooling_device *cdev; 49084e0d87cSLukasz Luba struct device *dev; 49184e0d87cSLukasz Luba int ret; 49284e0d87cSLukasz Luba 49384e0d87cSLukasz Luba if (IS_ERR_OR_NULL(df)) 49484e0d87cSLukasz Luba return ERR_PTR(-EINVAL); 49584e0d87cSLukasz Luba 49684e0d87cSLukasz Luba dev = df->dev.parent; 49784e0d87cSLukasz Luba 49884e0d87cSLukasz Luba ret = dev_pm_opp_of_register_em(dev, NULL); 49984e0d87cSLukasz Luba if (ret) 50084e0d87cSLukasz Luba dev_dbg(dev, "Unable to register EM for devfreq cooling device (%d)\n", 50184e0d87cSLukasz Luba ret); 50284e0d87cSLukasz Luba 50384e0d87cSLukasz Luba cdev = of_devfreq_cooling_register_power(dev->of_node, df, dfc_power); 50484e0d87cSLukasz Luba 50584e0d87cSLukasz Luba if (IS_ERR_OR_NULL(cdev)) 50684e0d87cSLukasz Luba em_dev_unregister_perf_domain(dev); 50784e0d87cSLukasz Luba 50884e0d87cSLukasz Luba return cdev; 50984e0d87cSLukasz Luba } 51084e0d87cSLukasz Luba EXPORT_SYMBOL_GPL(devfreq_cooling_em_register); 51184e0d87cSLukasz Luba 51284e0d87cSLukasz Luba /** 513a76caf55SØrjan Eide * devfreq_cooling_unregister() - Unregister devfreq cooling device. 5141b5cb957SAmit Kucheria * @cdev: Pointer to devfreq cooling device to unregister. 51584e0d87cSLukasz Luba * 51684e0d87cSLukasz Luba * Unregisters devfreq cooling device and related Energy Model if it was 51784e0d87cSLukasz Luba * present. 518a76caf55SØrjan Eide */ 5193c99c2ceSJavi Merino void devfreq_cooling_unregister(struct thermal_cooling_device *cdev) 520a76caf55SØrjan Eide { 5213c99c2ceSJavi Merino struct devfreq_cooling_device *dfc; 52284e0d87cSLukasz Luba struct device *dev; 5233c99c2ceSJavi Merino 52484e0d87cSLukasz Luba if (IS_ERR_OR_NULL(cdev)) 525a76caf55SØrjan Eide return; 526a76caf55SØrjan Eide 5273c99c2ceSJavi Merino dfc = cdev->devdata; 52884e0d87cSLukasz Luba dev = dfc->devfreq->dev.parent; 5293c99c2ceSJavi Merino 530a76caf55SØrjan Eide thermal_cooling_device_unregister(dfc->cdev); 5312f96c035SMatthew Wilcox ida_simple_remove(&devfreq_ida, dfc->id); 53204fa9c80SMatthias Kaehlcke dev_pm_qos_remove_request(&dfc->req_max_freq); 53384e0d87cSLukasz Luba 53484e0d87cSLukasz Luba em_dev_unregister_perf_domain(dev); 53584e0d87cSLukasz Luba 536a76caf55SØrjan Eide kfree(dfc->freq_table); 537a76caf55SØrjan Eide kfree(dfc); 538a76caf55SØrjan Eide } 539a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(devfreq_cooling_unregister); 540