Lines Matching +full:cooling +full:- +full:device

1 // SPDX-License-Identifier: GPL-2.0
3 * devfreq_cooling: Thermal cooling device implementation for devices using
6 * Copyright (C) 2014-2015 ARM Limited
9 * - If OPPs are added or removed after devfreq cooling has
10 * registered, the devfreq cooling won't react to it.
28 * struct devfreq_cooling_device - Devfreq cooling device
30 * @cdev: Pointer to associated thermal cooling device.
31 * @cooling_ops: devfreq callbacks to thermal cooling device ops
32 * @devfreq: Pointer to associated devfreq device.
33 * @cooling_state: Current cooling state.
35 * order. You can index the table by cooling device state
45 * @capped_state: index to cooling state with in dynamic power budget
47 * of the devfreq device.
48 * @em_pd: Energy Model for the associated Devfreq device
67 struct devfreq_cooling_device *dfc = cdev->devdata; in devfreq_cooling_get_max_state()
69 *state = dfc->max_state; in devfreq_cooling_get_max_state()
77 struct devfreq_cooling_device *dfc = cdev->devdata; in devfreq_cooling_get_cur_state()
79 *state = dfc->cooling_state; in devfreq_cooling_get_cur_state()
87 struct devfreq_cooling_device *dfc = cdev->devdata; in devfreq_cooling_set_cur_state()
88 struct devfreq *df = dfc->devfreq; in devfreq_cooling_set_cur_state()
89 struct device *dev = df->dev.parent; in devfreq_cooling_set_cur_state()
94 if (state == dfc->cooling_state) in devfreq_cooling_set_cur_state()
97 dev_dbg(dev, "Setting cooling state %lu\n", state); in devfreq_cooling_set_cur_state()
99 if (state > dfc->max_state) in devfreq_cooling_set_cur_state()
100 return -EINVAL; in devfreq_cooling_set_cur_state()
102 if (dfc->em_pd) { in devfreq_cooling_set_cur_state()
103 perf_idx = dfc->max_state - state; in devfreq_cooling_set_cur_state()
106 table = em_perf_state_from_pd(dfc->em_pd); in devfreq_cooling_set_cur_state()
110 freq = dfc->freq_table[state]; in devfreq_cooling_set_cur_state()
113 dev_pm_qos_update_request(&dfc->req_max_freq, in devfreq_cooling_set_cur_state()
116 dfc->cooling_state = state; in devfreq_cooling_set_cur_state()
122 * get_perf_idx() - get the performance index corresponding to a frequency
123 * @em_pd: Pointer to device's Energy Model
127 * -EINVAL if it wasn't found.
132 int i, idx = -EINVAL; in get_perf_idx()
136 for (i = 0; i < em_pd->nr_perf_states; i++) { in get_perf_idx()
150 struct device *dev = df->dev.parent; in get_voltage()
155 if (PTR_ERR(opp) == -ERANGE) in get_voltage()
178 if (status->total_time > 0xfffff) { in _normalize_load()
179 status->total_time >>= 10; in _normalize_load()
180 status->busy_time >>= 10; in _normalize_load()
183 status->busy_time <<= 10; in _normalize_load()
184 status->busy_time /= status->total_time ? : 1; in _normalize_load()
186 status->busy_time = status->busy_time ? : 1; in _normalize_load()
187 status->total_time = 1024; in _normalize_load()
193 struct devfreq_cooling_device *dfc = cdev->devdata; in devfreq_cooling_get_requested_power()
194 struct devfreq *df = dfc->devfreq; in devfreq_cooling_get_requested_power()
202 mutex_lock(&df->lock); in devfreq_cooling_get_requested_power()
203 status = df->last_status; in devfreq_cooling_get_requested_power()
204 mutex_unlock(&df->lock); in devfreq_cooling_get_requested_power()
208 if (dfc->power_ops && dfc->power_ops->get_real_power) { in devfreq_cooling_get_requested_power()
211 res = -EINVAL; in devfreq_cooling_get_requested_power()
215 res = dfc->power_ops->get_real_power(df, power, freq, voltage); in devfreq_cooling_get_requested_power()
217 state = dfc->max_state - dfc->capped_state; in devfreq_cooling_get_requested_power()
219 /* Convert EM power into milli-Watts first */ in devfreq_cooling_get_requested_power()
221 table = em_perf_state_from_pd(dfc->em_pd); in devfreq_cooling_get_requested_power()
222 dfc->res_util = table[state].power; in devfreq_cooling_get_requested_power()
225 dfc->res_util /= MICROWATT_PER_MILLIWATT; in devfreq_cooling_get_requested_power()
227 dfc->res_util *= SCALE_ERROR_MITIGATION; in devfreq_cooling_get_requested_power()
230 dfc->res_util /= *power; in devfreq_cooling_get_requested_power()
236 perf_idx = get_perf_idx(dfc->em_pd, freq / 1000); in devfreq_cooling_get_requested_power()
238 res = -EAGAIN; in devfreq_cooling_get_requested_power()
244 /* Convert EM power into milli-Watts first */ in devfreq_cooling_get_requested_power()
246 table = em_perf_state_from_pd(dfc->em_pd); in devfreq_cooling_get_requested_power()
261 dfc->res_util = SCALE_ERROR_MITIGATION; in devfreq_cooling_get_requested_power()
268 struct devfreq_cooling_device *dfc = cdev->devdata; in devfreq_cooling_state2power()
272 if (state > dfc->max_state) in devfreq_cooling_state2power()
273 return -EINVAL; in devfreq_cooling_state2power()
275 perf_idx = dfc->max_state - state; in devfreq_cooling_state2power()
278 table = em_perf_state_from_pd(dfc->em_pd); in devfreq_cooling_state2power()
290 struct devfreq_cooling_device *dfc = cdev->devdata; in devfreq_cooling_power2state()
291 struct devfreq *df = dfc->devfreq; in devfreq_cooling_power2state()
298 mutex_lock(&df->lock); in devfreq_cooling_power2state()
299 status = df->last_status; in devfreq_cooling_power2state()
300 mutex_unlock(&df->lock); in devfreq_cooling_power2state()
304 if (dfc->power_ops && dfc->power_ops->get_real_power) { in devfreq_cooling_power2state()
306 est_power = power * dfc->res_util; in devfreq_cooling_power2state()
316 * Find the first cooling state that is within the power in devfreq_cooling_power2state()
320 table = em_perf_state_from_pd(dfc->em_pd); in devfreq_cooling_power2state()
321 for (i = dfc->max_state; i > 0; i--) { in devfreq_cooling_power2state()
322 /* Convert EM power to milli-Watts to make safe comparison */ in devfreq_cooling_power2state()
330 *state = dfc->max_state - i; in devfreq_cooling_power2state()
331 dfc->capped_state = *state; in devfreq_cooling_power2state()
338 * devfreq_cooling_gen_tables() - Generate frequency table.
339 * @dfc: Pointer to devfreq cooling device.
343 * order. That way its indexed by cooling device state. This is for
351 struct devfreq *df = dfc->devfreq; in devfreq_cooling_gen_tables()
352 struct device *dev = df->dev.parent; in devfreq_cooling_gen_tables()
356 dfc->freq_table = kcalloc(num_opps, sizeof(*dfc->freq_table), in devfreq_cooling_gen_tables()
358 if (!dfc->freq_table) in devfreq_cooling_gen_tables()
359 return -ENOMEM; in devfreq_cooling_gen_tables()
361 for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) { in devfreq_cooling_gen_tables()
366 kfree(dfc->freq_table); in devfreq_cooling_gen_tables()
371 dfc->freq_table[i] = freq; in devfreq_cooling_gen_tables()
378 * of_devfreq_cooling_register_power() - Register devfreq cooling device,
381 * @df: Pointer to devfreq device.
384 * Register a devfreq cooling device. The available OPPs must be
385 * registered on the device.
387 * If @dfc_power is provided, the cooling device is registered with the
397 struct device *dev = df->dev.parent; in of_devfreq_cooling_register_power()
407 return ERR_PTR(-ENOMEM); in of_devfreq_cooling_register_power()
409 dfc->devfreq = df; in of_devfreq_cooling_register_power()
411 ops = &dfc->cooling_ops; in of_devfreq_cooling_register_power()
412 ops->get_max_state = devfreq_cooling_get_max_state; in of_devfreq_cooling_register_power()
413 ops->get_cur_state = devfreq_cooling_get_cur_state; in of_devfreq_cooling_register_power()
414 ops->set_cur_state = devfreq_cooling_set_cur_state; in of_devfreq_cooling_register_power()
418 dfc->em_pd = em; in of_devfreq_cooling_register_power()
419 ops->get_requested_power = in of_devfreq_cooling_register_power()
421 ops->state2power = devfreq_cooling_state2power; in of_devfreq_cooling_register_power()
422 ops->power2state = devfreq_cooling_power2state; in of_devfreq_cooling_register_power()
424 dfc->power_ops = dfc_power; in of_devfreq_cooling_register_power()
426 num_opps = em_pd_nr_perf_states(dfc->em_pd); in of_devfreq_cooling_register_power()
429 dev_dbg(dev, "missing proper EM for cooling device\n"); in of_devfreq_cooling_register_power()
439 err = -EINVAL; in of_devfreq_cooling_register_power()
444 dfc->max_state = num_opps - 1; in of_devfreq_cooling_register_power()
446 err = dev_pm_qos_add_request(dev, &dfc->req_max_freq, in of_devfreq_cooling_register_power()
452 err = -ENOMEM; in of_devfreq_cooling_register_power()
453 name = kasprintf(GFP_KERNEL, "devfreq-%s", dev_name(dev)); in of_devfreq_cooling_register_power()
463 "Failed to register devfreq cooling device (%d)\n", in of_devfreq_cooling_register_power()
468 dfc->cdev = cdev; in of_devfreq_cooling_register_power()
473 dev_pm_qos_remove_request(&dfc->req_max_freq); in of_devfreq_cooling_register_power()
475 kfree(dfc->freq_table); in of_devfreq_cooling_register_power()
484 * of_devfreq_cooling_register() - Register devfreq cooling device,
487 * @df: Pointer to devfreq device.
497 * devfreq_cooling_register() - Register devfreq cooling device.
498 * @df: Pointer to devfreq device.
507 * devfreq_cooling_em_register() - Register devfreq cooling device with
509 * @df: Pointer to devfreq device.
512 * Register a devfreq cooling device and automatically register EM. The
513 * available OPPs must be registered for the device.
515 * If @dfc_power is provided, the cooling device is registered with the
517 * "dynamic-power-coefficient" a devicetree property. To not break drivers
519 * registration failed. The cooling device will be registered if everything
527 struct device *dev; in devfreq_cooling_em_register()
531 return ERR_PTR(-EINVAL); in devfreq_cooling_em_register()
533 dev = df->dev.parent; in devfreq_cooling_em_register()
537 dev_dbg(dev, "Unable to register EM for devfreq cooling device (%d)\n", in devfreq_cooling_em_register()
540 cdev = of_devfreq_cooling_register_power(dev->of_node, df, dfc_power); in devfreq_cooling_em_register()
550 * devfreq_cooling_unregister() - Unregister devfreq cooling device.
551 * @cdev: Pointer to devfreq cooling device to unregister.
553 * Unregisters devfreq cooling device and related Energy Model if it was
559 struct device *dev; in devfreq_cooling_unregister()
564 dfc = cdev->devdata; in devfreq_cooling_unregister()
565 dev = dfc->devfreq->dev.parent; in devfreq_cooling_unregister()
567 thermal_cooling_device_unregister(dfc->cdev); in devfreq_cooling_unregister()
568 dev_pm_qos_remove_request(&dfc->req_max_freq); in devfreq_cooling_unregister()
572 kfree(dfc->freq_table); in devfreq_cooling_unregister()