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 {
26061c8e8aaSJavi Merino 	u64 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)
400ce5ee161SDan Carpenter 			return -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