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> 17a76caf55SØrjan Eide #include <linux/slab.h> 18a76caf55SØrjan Eide #include <linux/pm_opp.h> 1904fa9c80SMatthias Kaehlcke #include <linux/pm_qos.h> 20a76caf55SØrjan Eide #include <linux/thermal.h> 21a76caf55SØrjan Eide 229876b1a4SJavi Merino #include <trace/events/thermal.h> 239876b1a4SJavi Merino 2404fa9c80SMatthias Kaehlcke #define HZ_PER_KHZ 1000 252be83da8SLukasz Luba #define SCALE_ERROR_MITIGATION 100 262be83da8SLukasz Luba 27a76caf55SØrjan Eide /** 28a76caf55SØrjan Eide * struct devfreq_cooling_device - Devfreq cooling device 29a76caf55SØrjan Eide * devfreq_cooling_device registered. 30a76caf55SØrjan Eide * @cdev: Pointer to associated thermal cooling device. 31a76caf55SØrjan Eide * @devfreq: Pointer to associated devfreq device. 32a76caf55SØrjan Eide * @cooling_state: Current cooling state. 33a76caf55SØrjan Eide * @freq_table: Pointer to a table with the frequencies sorted in descending 34a76caf55SØrjan Eide * order. You can index the table by cooling device state 35615510feSLukasz Luba * @max_state: It is the last index, that is, one less than the number of the 36615510feSLukasz Luba * OPPs 37615510feSLukasz Luba * @power_ops: Pointer to devfreq_cooling_power, a more precised model. 382be83da8SLukasz Luba * @res_util: Resource utilization scaling factor for the power. 392be83da8SLukasz Luba * It is multiplied by 100 to minimize the error. It is used 402be83da8SLukasz Luba * for estimation of the power budget instead of using 41615510feSLukasz Luba * 'utilization' (which is 'busy_time' / 'total_time'). 42615510feSLukasz Luba * The 'res_util' range is from 100 to power * 100 for the 43615510feSLukasz Luba * corresponding 'state'. 441b5cb957SAmit Kucheria * @capped_state: index to cooling state with in dynamic power budget 4504fa9c80SMatthias Kaehlcke * @req_max_freq: PM QoS request for limiting the maximum frequency 4604fa9c80SMatthias Kaehlcke * of the devfreq device. 474401117bSLukasz Luba * @em_pd: Energy Model for the associated Devfreq device 48a76caf55SØrjan Eide */ 49a76caf55SØrjan Eide struct devfreq_cooling_device { 50a76caf55SØrjan Eide struct thermal_cooling_device *cdev; 51a76caf55SØrjan Eide struct devfreq *devfreq; 52a76caf55SØrjan Eide unsigned long cooling_state; 53a76caf55SØrjan Eide u32 *freq_table; 54615510feSLukasz Luba size_t max_state; 55a76caf55SØrjan Eide struct devfreq_cooling_power *power_ops; 562be83da8SLukasz Luba u32 res_util; 572be83da8SLukasz Luba int capped_state; 5804fa9c80SMatthias Kaehlcke struct dev_pm_qos_request req_max_freq; 594401117bSLukasz Luba struct em_perf_domain *em_pd; 60a76caf55SØrjan Eide }; 61a76caf55SØrjan Eide 62a76caf55SØrjan Eide static int devfreq_cooling_get_max_state(struct thermal_cooling_device *cdev, 63a76caf55SØrjan Eide unsigned long *state) 64a76caf55SØrjan Eide { 65a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 66a76caf55SØrjan Eide 67615510feSLukasz Luba *state = dfc->max_state; 68a76caf55SØrjan Eide 69a76caf55SØrjan Eide return 0; 70a76caf55SØrjan Eide } 71a76caf55SØrjan Eide 72a76caf55SØrjan Eide static int devfreq_cooling_get_cur_state(struct thermal_cooling_device *cdev, 73a76caf55SØrjan Eide unsigned long *state) 74a76caf55SØrjan Eide { 75a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 76a76caf55SØrjan Eide 77a76caf55SØrjan Eide *state = dfc->cooling_state; 78a76caf55SØrjan Eide 79a76caf55SØrjan Eide return 0; 80a76caf55SØrjan Eide } 81a76caf55SØrjan Eide 82a76caf55SØrjan Eide static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev, 83a76caf55SØrjan Eide unsigned long state) 84a76caf55SØrjan Eide { 85a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 86a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 87a76caf55SØrjan Eide struct device *dev = df->dev.parent; 8804fa9c80SMatthias Kaehlcke unsigned long freq; 89615510feSLukasz Luba int perf_idx; 90a76caf55SØrjan Eide 91a76caf55SØrjan Eide if (state == dfc->cooling_state) 92a76caf55SØrjan Eide return 0; 93a76caf55SØrjan Eide 94a76caf55SØrjan Eide dev_dbg(dev, "Setting cooling state %lu\n", state); 95a76caf55SØrjan Eide 96615510feSLukasz Luba if (state > dfc->max_state) 97a76caf55SØrjan Eide return -EINVAL; 98a76caf55SØrjan Eide 994401117bSLukasz Luba if (dfc->em_pd) { 100615510feSLukasz Luba perf_idx = dfc->max_state - state; 1014401117bSLukasz Luba freq = dfc->em_pd->table[perf_idx].frequency * 1000; 102615510feSLukasz Luba } else { 10304fa9c80SMatthias Kaehlcke freq = dfc->freq_table[state]; 104615510feSLukasz Luba } 10504fa9c80SMatthias Kaehlcke 10604fa9c80SMatthias Kaehlcke dev_pm_qos_update_request(&dfc->req_max_freq, 10704fa9c80SMatthias Kaehlcke DIV_ROUND_UP(freq, HZ_PER_KHZ)); 108a76caf55SØrjan Eide 109a76caf55SØrjan Eide dfc->cooling_state = state; 110a76caf55SØrjan Eide 111a76caf55SØrjan Eide return 0; 112a76caf55SØrjan Eide } 113a76caf55SØrjan Eide 114a76caf55SØrjan Eide /** 115615510feSLukasz Luba * get_perf_idx() - get the performance index corresponding to a frequency 116615510feSLukasz Luba * @em_pd: Pointer to device's Energy Model 117615510feSLukasz Luba * @freq: frequency in kHz 118a76caf55SØrjan Eide * 119615510feSLukasz Luba * Return: the performance index associated with the @freq, or 120615510feSLukasz Luba * -EINVAL if it wasn't found. 121a76caf55SØrjan Eide */ 122615510feSLukasz Luba static int get_perf_idx(struct em_perf_domain *em_pd, unsigned long freq) 123a76caf55SØrjan Eide { 124a76caf55SØrjan Eide int i; 125a76caf55SØrjan Eide 126615510feSLukasz Luba for (i = 0; i < em_pd->nr_perf_states; i++) { 127615510feSLukasz Luba if (em_pd->table[i].frequency == freq) 128a76caf55SØrjan Eide return i; 129a76caf55SØrjan Eide } 130a76caf55SØrjan Eide 131615510feSLukasz Luba return -EINVAL; 132a76caf55SØrjan Eide } 133a76caf55SØrjan Eide 134e34cab4cSLukasz Luba static unsigned long get_voltage(struct devfreq *df, unsigned long freq) 135a76caf55SØrjan Eide { 136a76caf55SØrjan Eide struct device *dev = df->dev.parent; 137a76caf55SØrjan Eide unsigned long voltage; 138a76caf55SØrjan Eide struct dev_pm_opp *opp; 139a76caf55SØrjan Eide 140a76caf55SØrjan Eide opp = dev_pm_opp_find_freq_exact(dev, freq, true); 141a4e49c9bSViresh Kumar if (PTR_ERR(opp) == -ERANGE) 142a76caf55SØrjan Eide opp = dev_pm_opp_find_freq_exact(dev, freq, false); 143a76caf55SØrjan Eide 144afd1f4e0SViresh Kumar if (IS_ERR(opp)) { 145afd1f4e0SViresh Kumar dev_err_ratelimited(dev, "Failed to find OPP for frequency %lu: %ld\n", 146afd1f4e0SViresh Kumar freq, PTR_ERR(opp)); 147afd1f4e0SViresh Kumar return 0; 148afd1f4e0SViresh Kumar } 149afd1f4e0SViresh Kumar 150a76caf55SØrjan Eide voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ 1518a31d9d9SViresh Kumar dev_pm_opp_put(opp); 152a76caf55SØrjan Eide 153a76caf55SØrjan Eide if (voltage == 0) { 1548327b830SViresh Kumar dev_err_ratelimited(dev, 155afd1f4e0SViresh Kumar "Failed to get voltage for frequency %lu\n", 156afd1f4e0SViresh Kumar freq); 157a76caf55SØrjan Eide } 158a76caf55SØrjan Eide 159e34cab4cSLukasz Luba return voltage; 160e34cab4cSLukasz Luba } 161e34cab4cSLukasz Luba 162229794eeSLukasz Luba static void _normalize_load(struct devfreq_dev_status *status) 163229794eeSLukasz Luba { 164229794eeSLukasz Luba if (status->total_time > 0xfffff) { 165229794eeSLukasz Luba status->total_time >>= 10; 166229794eeSLukasz Luba status->busy_time >>= 10; 167229794eeSLukasz Luba } 168229794eeSLukasz Luba 169229794eeSLukasz Luba status->busy_time <<= 10; 170229794eeSLukasz Luba status->busy_time /= status->total_time ? : 1; 171229794eeSLukasz Luba 172229794eeSLukasz Luba status->busy_time = status->busy_time ? : 1; 173229794eeSLukasz Luba status->total_time = 1024; 174229794eeSLukasz Luba } 1752be83da8SLukasz Luba 176a76caf55SØrjan Eide static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev, 177a76caf55SØrjan Eide u32 *power) 178a76caf55SØrjan Eide { 179a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 180a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 181229794eeSLukasz Luba struct devfreq_dev_status status; 182a76caf55SØrjan Eide unsigned long state; 183229794eeSLukasz Luba unsigned long freq; 1842be83da8SLukasz Luba unsigned long voltage; 185615510feSLukasz Luba int res, perf_idx; 186a76caf55SØrjan Eide 187229794eeSLukasz Luba mutex_lock(&df->lock); 188229794eeSLukasz Luba status = df->last_status; 189229794eeSLukasz Luba mutex_unlock(&df->lock); 190229794eeSLukasz Luba 191229794eeSLukasz Luba freq = status.current_frequency; 192229794eeSLukasz Luba 193615510feSLukasz Luba if (dfc->power_ops && dfc->power_ops->get_real_power) { 1942be83da8SLukasz Luba voltage = get_voltage(df, freq); 1952be83da8SLukasz Luba if (voltage == 0) { 1962be83da8SLukasz Luba res = -EINVAL; 1972be83da8SLukasz Luba goto fail; 1982be83da8SLukasz Luba } 1992be83da8SLukasz Luba 2002be83da8SLukasz Luba res = dfc->power_ops->get_real_power(df, power, freq, voltage); 2012be83da8SLukasz Luba if (!res) { 2022be83da8SLukasz Luba state = dfc->capped_state; 2034401117bSLukasz Luba dfc->res_util = dfc->em_pd->table[state].power; 2042be83da8SLukasz Luba dfc->res_util *= SCALE_ERROR_MITIGATION; 2052be83da8SLukasz Luba 2062be83da8SLukasz Luba if (*power > 1) 2072be83da8SLukasz Luba dfc->res_util /= *power; 2082be83da8SLukasz Luba } else { 2092be83da8SLukasz Luba goto fail; 2102be83da8SLukasz Luba } 2112be83da8SLukasz Luba } else { 212615510feSLukasz Luba /* Energy Model frequencies are in kHz */ 2134401117bSLukasz Luba perf_idx = get_perf_idx(dfc->em_pd, freq / 1000); 214615510feSLukasz Luba if (perf_idx < 0) { 215615510feSLukasz Luba res = -EAGAIN; 216615510feSLukasz Luba goto fail; 217615510feSLukasz Luba } 218a76caf55SØrjan Eide 219229794eeSLukasz Luba _normalize_load(&status); 220229794eeSLukasz Luba 221615510feSLukasz Luba /* Scale power for utilization */ 2224401117bSLukasz Luba *power = dfc->em_pd->table[perf_idx].power; 223615510feSLukasz Luba *power *= status.busy_time; 224615510feSLukasz Luba *power >>= 10; 2252be83da8SLukasz Luba } 2262be83da8SLukasz Luba 227229794eeSLukasz Luba trace_thermal_power_devfreq_get_power(cdev, &status, freq, *power); 2289876b1a4SJavi Merino 229a76caf55SØrjan Eide return 0; 2302be83da8SLukasz Luba fail: 2312be83da8SLukasz Luba /* It is safe to set max in this case */ 2322be83da8SLukasz Luba dfc->res_util = SCALE_ERROR_MITIGATION; 2332be83da8SLukasz Luba return res; 234a76caf55SØrjan Eide } 235a76caf55SØrjan Eide 236a76caf55SØrjan Eide static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev, 237615510feSLukasz Luba unsigned long state, u32 *power) 238a76caf55SØrjan Eide { 239a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 240615510feSLukasz Luba int perf_idx; 241a76caf55SØrjan Eide 242615510feSLukasz Luba if (state > dfc->max_state) 243a76caf55SØrjan Eide return -EINVAL; 244a76caf55SØrjan Eide 245615510feSLukasz Luba perf_idx = dfc->max_state - state; 2464401117bSLukasz Luba *power = dfc->em_pd->table[perf_idx].power; 247a76caf55SØrjan Eide 248a76caf55SØrjan Eide return 0; 249a76caf55SØrjan Eide } 250a76caf55SØrjan Eide 251a76caf55SØrjan Eide static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev, 252a76caf55SØrjan Eide u32 power, unsigned long *state) 253a76caf55SØrjan Eide { 254a76caf55SØrjan Eide struct devfreq_cooling_device *dfc = cdev->devdata; 255a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 256229794eeSLukasz Luba struct devfreq_dev_status status; 257229794eeSLukasz Luba unsigned long freq; 2582be83da8SLukasz Luba s32 est_power; 259a76caf55SØrjan Eide int i; 260a76caf55SØrjan Eide 261229794eeSLukasz Luba mutex_lock(&df->lock); 262229794eeSLukasz Luba status = df->last_status; 263229794eeSLukasz Luba mutex_unlock(&df->lock); 264229794eeSLukasz Luba 265229794eeSLukasz Luba freq = status.current_frequency; 266229794eeSLukasz Luba 267615510feSLukasz Luba if (dfc->power_ops && dfc->power_ops->get_real_power) { 2682be83da8SLukasz Luba /* Scale for resource utilization */ 2692be83da8SLukasz Luba est_power = power * dfc->res_util; 2702be83da8SLukasz Luba est_power /= SCALE_ERROR_MITIGATION; 2712be83da8SLukasz Luba } else { 272a76caf55SØrjan Eide /* Scale dynamic power for utilization */ 273229794eeSLukasz Luba _normalize_load(&status); 274615510feSLukasz Luba est_power = power << 10; 275615510feSLukasz Luba est_power /= status.busy_time; 2762be83da8SLukasz Luba } 277a76caf55SØrjan Eide 278a76caf55SØrjan Eide /* 279a76caf55SØrjan Eide * Find the first cooling state that is within the power 280615510feSLukasz Luba * budget. The EM power table is sorted ascending. 281a76caf55SØrjan Eide */ 282615510feSLukasz Luba for (i = dfc->max_state; i > 0; i--) 2834401117bSLukasz Luba if (est_power >= dfc->em_pd->table[i].power) 284a76caf55SØrjan Eide break; 285a76caf55SØrjan Eide 286615510feSLukasz Luba *state = dfc->max_state - i; 287615510feSLukasz Luba dfc->capped_state = *state; 288615510feSLukasz Luba 2899876b1a4SJavi Merino trace_thermal_power_devfreq_limit(cdev, freq, *state, power); 290a76caf55SØrjan Eide return 0; 291a76caf55SØrjan Eide } 292a76caf55SØrjan Eide 293a76caf55SØrjan Eide static struct thermal_cooling_device_ops devfreq_cooling_ops = { 294a76caf55SØrjan Eide .get_max_state = devfreq_cooling_get_max_state, 295a76caf55SØrjan Eide .get_cur_state = devfreq_cooling_get_cur_state, 296a76caf55SØrjan Eide .set_cur_state = devfreq_cooling_set_cur_state, 297a76caf55SØrjan Eide }; 298a76caf55SØrjan Eide 299a76caf55SØrjan Eide /** 300615510feSLukasz Luba * devfreq_cooling_gen_tables() - Generate frequency table. 301a76caf55SØrjan Eide * @dfc: Pointer to devfreq cooling device. 302615510feSLukasz Luba * @num_opps: Number of OPPs 303a76caf55SØrjan Eide * 304615510feSLukasz Luba * Generate frequency table which holds the frequencies in descending 305615510feSLukasz Luba * order. That way its indexed by cooling device state. This is for 306615510feSLukasz Luba * compatibility with drivers which do not register Energy Model. 307a76caf55SØrjan Eide * 308a76caf55SØrjan Eide * Return: 0 on success, negative error code on failure. 309a76caf55SØrjan Eide */ 310615510feSLukasz Luba static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc, 311615510feSLukasz Luba int num_opps) 312a76caf55SØrjan Eide { 313a76caf55SØrjan Eide struct devfreq *df = dfc->devfreq; 314a76caf55SØrjan Eide struct device *dev = df->dev.parent; 315a76caf55SØrjan Eide unsigned long freq; 316a76caf55SØrjan Eide int i; 317a76caf55SØrjan Eide 318615510feSLukasz Luba dfc->freq_table = kcalloc(num_opps, sizeof(*dfc->freq_table), 319a76caf55SØrjan Eide GFP_KERNEL); 320615510feSLukasz Luba if (!dfc->freq_table) 321ce5ee161SDan Carpenter return -ENOMEM; 322a76caf55SØrjan Eide 323a76caf55SØrjan Eide for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) { 324a76caf55SØrjan Eide struct dev_pm_opp *opp; 325a76caf55SØrjan Eide 326a76caf55SØrjan Eide opp = dev_pm_opp_find_freq_floor(dev, &freq); 327a76caf55SØrjan Eide if (IS_ERR(opp)) { 328615510feSLukasz Luba kfree(dfc->freq_table); 329615510feSLukasz Luba return PTR_ERR(opp); 330a76caf55SØrjan Eide } 331a76caf55SØrjan Eide 3328a31d9d9SViresh Kumar dev_pm_opp_put(opp); 333615510feSLukasz Luba dfc->freq_table[i] = freq; 334a76caf55SØrjan Eide } 335a76caf55SØrjan Eide 336a76caf55SØrjan Eide return 0; 337a76caf55SØrjan Eide } 338a76caf55SØrjan Eide 339a76caf55SØrjan Eide /** 340a76caf55SØrjan Eide * of_devfreq_cooling_register_power() - Register devfreq cooling device, 341a76caf55SØrjan Eide * with OF and power information. 342a76caf55SØrjan Eide * @np: Pointer to OF device_node. 343a76caf55SØrjan Eide * @df: Pointer to devfreq device. 344a76caf55SØrjan Eide * @dfc_power: Pointer to devfreq_cooling_power. 345a76caf55SØrjan Eide * 346a76caf55SØrjan Eide * Register a devfreq cooling device. The available OPPs must be 347a76caf55SØrjan Eide * registered on the device. 348a76caf55SØrjan Eide * 349a76caf55SØrjan Eide * If @dfc_power is provided, the cooling device is registered with the 350a76caf55SØrjan Eide * power extensions. For the power extensions to work correctly, 351a76caf55SØrjan Eide * devfreq should use the simple_ondemand governor, other governors 352a76caf55SØrjan Eide * are not currently supported. 353a76caf55SØrjan Eide */ 3543c99c2ceSJavi Merino struct thermal_cooling_device * 355a76caf55SØrjan Eide of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, 356a76caf55SØrjan Eide struct devfreq_cooling_power *dfc_power) 357a76caf55SØrjan Eide { 358a76caf55SØrjan Eide struct thermal_cooling_device *cdev; 359615510feSLukasz Luba struct device *dev = df->dev.parent; 360a76caf55SØrjan Eide struct devfreq_cooling_device *dfc; 361f8d354e8SDaniel Lezcano char *name; 362615510feSLukasz Luba int err, num_opps; 363a76caf55SØrjan Eide 364a76caf55SØrjan Eide dfc = kzalloc(sizeof(*dfc), GFP_KERNEL); 365a76caf55SØrjan Eide if (!dfc) 366a76caf55SØrjan Eide return ERR_PTR(-ENOMEM); 367a76caf55SØrjan Eide 368a76caf55SØrjan Eide dfc->devfreq = df; 369a76caf55SØrjan Eide 3704401117bSLukasz Luba dfc->em_pd = em_pd_get(dev); 3714401117bSLukasz Luba if (dfc->em_pd) { 372a76caf55SØrjan Eide devfreq_cooling_ops.get_requested_power = 373a76caf55SØrjan Eide devfreq_cooling_get_requested_power; 374a76caf55SØrjan Eide devfreq_cooling_ops.state2power = devfreq_cooling_state2power; 375a76caf55SØrjan Eide devfreq_cooling_ops.power2state = devfreq_cooling_power2state; 376a76caf55SØrjan Eide 377615510feSLukasz Luba dfc->power_ops = dfc_power; 378615510feSLukasz Luba 3794401117bSLukasz Luba num_opps = em_pd_nr_perf_states(dfc->em_pd); 380615510feSLukasz Luba } else { 381615510feSLukasz Luba /* Backward compatibility for drivers which do not use IPA */ 382615510feSLukasz Luba dev_dbg(dev, "missing EM for cooling device\n"); 383615510feSLukasz Luba 384615510feSLukasz Luba num_opps = dev_pm_opp_get_opp_count(dev); 385615510feSLukasz Luba 386615510feSLukasz Luba err = devfreq_cooling_gen_tables(dfc, num_opps); 387a76caf55SØrjan Eide if (err) 388a76caf55SØrjan Eide goto free_dfc; 389615510feSLukasz Luba } 390a76caf55SØrjan Eide 391615510feSLukasz Luba if (num_opps <= 0) { 392615510feSLukasz Luba err = -EINVAL; 393615510feSLukasz Luba goto free_dfc; 394615510feSLukasz Luba } 395615510feSLukasz Luba 396615510feSLukasz Luba /* max_state is an index, not a counter */ 397615510feSLukasz Luba dfc->max_state = num_opps - 1; 398615510feSLukasz Luba 399615510feSLukasz Luba err = dev_pm_qos_add_request(dev, &dfc->req_max_freq, 40004fa9c80SMatthias Kaehlcke DEV_PM_QOS_MAX_FREQUENCY, 40104fa9c80SMatthias Kaehlcke PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE); 4022f96c035SMatthew Wilcox if (err < 0) 403615510feSLukasz Luba goto free_table; 40404fa9c80SMatthias Kaehlcke 405*9aa80ab2SDaniel Lezcano err = -ENOMEM; 406f8d354e8SDaniel Lezcano name = kasprintf(GFP_KERNEL, "devfreq-%s", dev_name(dev)); 407f8d354e8SDaniel Lezcano if (!name) 40804fa9c80SMatthias Kaehlcke goto remove_qos_req; 409615510feSLukasz Luba 410f8d354e8SDaniel Lezcano cdev = thermal_of_cooling_device_register(np, name, dfc, 411a76caf55SØrjan Eide &devfreq_cooling_ops); 412f8d354e8SDaniel Lezcano kfree(name); 413f8d354e8SDaniel Lezcano 414a76caf55SØrjan Eide if (IS_ERR(cdev)) { 415a76caf55SØrjan Eide err = PTR_ERR(cdev); 416615510feSLukasz Luba dev_err(dev, 417a76caf55SØrjan Eide "Failed to register devfreq cooling device (%d)\n", 418a76caf55SØrjan Eide err); 419f8d354e8SDaniel Lezcano goto remove_qos_req; 420a76caf55SØrjan Eide } 421a76caf55SØrjan Eide 422a76caf55SØrjan Eide dfc->cdev = cdev; 423a76caf55SØrjan Eide 4243c99c2ceSJavi Merino return cdev; 425a76caf55SØrjan Eide 42604fa9c80SMatthias Kaehlcke remove_qos_req: 42704fa9c80SMatthias Kaehlcke dev_pm_qos_remove_request(&dfc->req_max_freq); 428615510feSLukasz Luba free_table: 429a76caf55SØrjan Eide kfree(dfc->freq_table); 430a76caf55SØrjan Eide free_dfc: 431a76caf55SØrjan Eide kfree(dfc); 432a76caf55SØrjan Eide 433a76caf55SØrjan Eide return ERR_PTR(err); 434a76caf55SØrjan Eide } 435a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(of_devfreq_cooling_register_power); 436a76caf55SØrjan Eide 437a76caf55SØrjan Eide /** 438a76caf55SØrjan Eide * of_devfreq_cooling_register() - Register devfreq cooling device, 439a76caf55SØrjan Eide * with OF information. 440a76caf55SØrjan Eide * @np: Pointer to OF device_node. 441a76caf55SØrjan Eide * @df: Pointer to devfreq device. 442a76caf55SØrjan Eide */ 4433c99c2ceSJavi Merino struct thermal_cooling_device * 444a76caf55SØrjan Eide of_devfreq_cooling_register(struct device_node *np, struct devfreq *df) 445a76caf55SØrjan Eide { 446a76caf55SØrjan Eide return of_devfreq_cooling_register_power(np, df, NULL); 447a76caf55SØrjan Eide } 448a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(of_devfreq_cooling_register); 449a76caf55SØrjan Eide 450a76caf55SØrjan Eide /** 451a76caf55SØrjan Eide * devfreq_cooling_register() - Register devfreq cooling device. 452a76caf55SØrjan Eide * @df: Pointer to devfreq device. 453a76caf55SØrjan Eide */ 4543c99c2ceSJavi Merino struct thermal_cooling_device *devfreq_cooling_register(struct devfreq *df) 455a76caf55SØrjan Eide { 456a76caf55SØrjan Eide return of_devfreq_cooling_register(NULL, df); 457a76caf55SØrjan Eide } 458a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(devfreq_cooling_register); 459a76caf55SØrjan Eide 460a76caf55SØrjan Eide /** 46184e0d87cSLukasz Luba * devfreq_cooling_em_register_power() - Register devfreq cooling device with 46284e0d87cSLukasz Luba * power information and automatically register Energy Model (EM) 46384e0d87cSLukasz Luba * @df: Pointer to devfreq device. 46484e0d87cSLukasz Luba * @dfc_power: Pointer to devfreq_cooling_power. 46584e0d87cSLukasz Luba * 46684e0d87cSLukasz Luba * Register a devfreq cooling device and automatically register EM. The 46784e0d87cSLukasz Luba * available OPPs must be registered for the device. 46884e0d87cSLukasz Luba * 46984e0d87cSLukasz Luba * If @dfc_power is provided, the cooling device is registered with the 47084e0d87cSLukasz Luba * power extensions. It is using the simple Energy Model which requires 47184e0d87cSLukasz Luba * "dynamic-power-coefficient" a devicetree property. To not break drivers 47284e0d87cSLukasz Luba * which miss that DT property, the function won't bail out when the EM 47384e0d87cSLukasz Luba * registration failed. The cooling device will be registered if everything 47484e0d87cSLukasz Luba * else is OK. 47584e0d87cSLukasz Luba */ 47684e0d87cSLukasz Luba struct thermal_cooling_device * 47784e0d87cSLukasz Luba devfreq_cooling_em_register(struct devfreq *df, 47884e0d87cSLukasz Luba struct devfreq_cooling_power *dfc_power) 47984e0d87cSLukasz Luba { 48084e0d87cSLukasz Luba struct thermal_cooling_device *cdev; 48184e0d87cSLukasz Luba struct device *dev; 48284e0d87cSLukasz Luba int ret; 48384e0d87cSLukasz Luba 48484e0d87cSLukasz Luba if (IS_ERR_OR_NULL(df)) 48584e0d87cSLukasz Luba return ERR_PTR(-EINVAL); 48684e0d87cSLukasz Luba 48784e0d87cSLukasz Luba dev = df->dev.parent; 48884e0d87cSLukasz Luba 48984e0d87cSLukasz Luba ret = dev_pm_opp_of_register_em(dev, NULL); 49084e0d87cSLukasz Luba if (ret) 49184e0d87cSLukasz Luba dev_dbg(dev, "Unable to register EM for devfreq cooling device (%d)\n", 49284e0d87cSLukasz Luba ret); 49384e0d87cSLukasz Luba 49484e0d87cSLukasz Luba cdev = of_devfreq_cooling_register_power(dev->of_node, df, dfc_power); 49584e0d87cSLukasz Luba 49684e0d87cSLukasz Luba if (IS_ERR_OR_NULL(cdev)) 49784e0d87cSLukasz Luba em_dev_unregister_perf_domain(dev); 49884e0d87cSLukasz Luba 49984e0d87cSLukasz Luba return cdev; 50084e0d87cSLukasz Luba } 50184e0d87cSLukasz Luba EXPORT_SYMBOL_GPL(devfreq_cooling_em_register); 50284e0d87cSLukasz Luba 50384e0d87cSLukasz Luba /** 504a76caf55SØrjan Eide * devfreq_cooling_unregister() - Unregister devfreq cooling device. 5051b5cb957SAmit Kucheria * @cdev: Pointer to devfreq cooling device to unregister. 50684e0d87cSLukasz Luba * 50784e0d87cSLukasz Luba * Unregisters devfreq cooling device and related Energy Model if it was 50884e0d87cSLukasz Luba * present. 509a76caf55SØrjan Eide */ 5103c99c2ceSJavi Merino void devfreq_cooling_unregister(struct thermal_cooling_device *cdev) 511a76caf55SØrjan Eide { 5123c99c2ceSJavi Merino struct devfreq_cooling_device *dfc; 51384e0d87cSLukasz Luba struct device *dev; 5143c99c2ceSJavi Merino 51584e0d87cSLukasz Luba if (IS_ERR_OR_NULL(cdev)) 516a76caf55SØrjan Eide return; 517a76caf55SØrjan Eide 5183c99c2ceSJavi Merino dfc = cdev->devdata; 51984e0d87cSLukasz Luba dev = dfc->devfreq->dev.parent; 5203c99c2ceSJavi Merino 521a76caf55SØrjan Eide thermal_cooling_device_unregister(dfc->cdev); 52204fa9c80SMatthias Kaehlcke dev_pm_qos_remove_request(&dfc->req_max_freq); 52384e0d87cSLukasz Luba 52484e0d87cSLukasz Luba em_dev_unregister_perf_domain(dev); 52584e0d87cSLukasz Luba 526a76caf55SØrjan Eide kfree(dfc->freq_table); 527a76caf55SØrjan Eide kfree(dfc); 528a76caf55SØrjan Eide } 529a76caf55SØrjan Eide EXPORT_SYMBOL_GPL(devfreq_cooling_unregister); 530