1 /*
2  * OMAP thermal driver interface
3  *
4  * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
5  * Contact:
6  *   Eduardo Valentin <eduardo.valentin@ti.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23 
24 #include <linux/device.h>
25 #include <linux/err.h>
26 #include <linux/mutex.h>
27 #include <linux/gfp.h>
28 #include <linux/kernel.h>
29 #include <linux/workqueue.h>
30 #include <linux/thermal.h>
31 #include <linux/cpufreq.h>
32 #include <linux/cpumask.h>
33 #include <linux/cpu_cooling.h>
34 #include <linux/of.h>
35 
36 #include "ti-thermal.h"
37 #include "ti-bandgap.h"
38 
39 /* common data structures */
40 struct ti_thermal_data {
41 	struct thermal_zone_device *ti_thermal;
42 	struct thermal_zone_device *pcb_tz;
43 	struct thermal_cooling_device *cool_dev;
44 	struct ti_bandgap *bgp;
45 	enum thermal_device_mode mode;
46 	struct work_struct thermal_wq;
47 	int sensor_id;
48 	bool our_zone;
49 };
50 
51 static void ti_thermal_work(struct work_struct *work)
52 {
53 	struct ti_thermal_data *data = container_of(work,
54 					struct ti_thermal_data, thermal_wq);
55 
56 	thermal_zone_device_update(data->ti_thermal);
57 
58 	dev_dbg(&data->ti_thermal->device, "updated thermal zone %s\n",
59 		data->ti_thermal->type);
60 }
61 
62 /**
63  * ti_thermal_hotspot_temperature - returns sensor extrapolated temperature
64  * @t:	omap sensor temperature
65  * @s:	omap sensor slope value
66  * @c:	omap sensor const value
67  */
68 static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
69 {
70 	int delta = t * s / 1000 + c;
71 
72 	if (delta < 0)
73 		delta = 0;
74 
75 	return t + delta;
76 }
77 
78 /* thermal zone ops */
79 /* Get temperature callback function for thermal zone*/
80 static inline int __ti_thermal_get_temp(void *devdata, long *temp)
81 {
82 	struct thermal_zone_device *pcb_tz = NULL;
83 	struct ti_thermal_data *data = devdata;
84 	struct ti_bandgap *bgp;
85 	const struct ti_temp_sensor *s;
86 	int ret, tmp, slope, constant;
87 	unsigned long pcb_temp;
88 
89 	if (!data)
90 		return 0;
91 
92 	bgp = data->bgp;
93 	s = &bgp->conf->sensors[data->sensor_id];
94 
95 	ret = ti_bandgap_read_temperature(bgp, data->sensor_id, &tmp);
96 	if (ret)
97 		return ret;
98 
99 	/* Default constants */
100 	slope = s->slope;
101 	constant = s->constant;
102 
103 	pcb_tz = data->pcb_tz;
104 	/* In case pcb zone is available, use the extrapolation rule with it */
105 	if (!IS_ERR(pcb_tz)) {
106 		ret = thermal_zone_get_temp(pcb_tz, &pcb_temp);
107 		if (!ret) {
108 			tmp -= pcb_temp; /* got a valid PCB temp */
109 			slope = s->slope_pcb;
110 			constant = s->constant_pcb;
111 		} else {
112 			dev_err(bgp->dev,
113 				"Failed to read PCB state. Using defaults\n");
114 			ret = 0;
115 		}
116 	}
117 	*temp = ti_thermal_hotspot_temperature(tmp, slope, constant);
118 
119 	return ret;
120 }
121 
122 static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
123 				      unsigned long *temp)
124 {
125 	struct ti_thermal_data *data = thermal->devdata;
126 
127 	return __ti_thermal_get_temp(data, temp);
128 }
129 
130 /* Bind callback functions for thermal zone */
131 static int ti_thermal_bind(struct thermal_zone_device *thermal,
132 			   struct thermal_cooling_device *cdev)
133 {
134 	struct ti_thermal_data *data = thermal->devdata;
135 	int id;
136 
137 	if (!data || IS_ERR(data))
138 		return -ENODEV;
139 
140 	/* check if this is the cooling device we registered */
141 	if (data->cool_dev != cdev)
142 		return 0;
143 
144 	id = data->sensor_id;
145 
146 	/* Simple thing, two trips, one passive another critical */
147 	return thermal_zone_bind_cooling_device(thermal, 0, cdev,
148 	/* bind with min and max states defined by cpu_cooling */
149 						THERMAL_NO_LIMIT,
150 						THERMAL_NO_LIMIT);
151 }
152 
153 /* Unbind callback functions for thermal zone */
154 static int ti_thermal_unbind(struct thermal_zone_device *thermal,
155 			     struct thermal_cooling_device *cdev)
156 {
157 	struct ti_thermal_data *data = thermal->devdata;
158 
159 	if (!data || IS_ERR(data))
160 		return -ENODEV;
161 
162 	/* check if this is the cooling device we registered */
163 	if (data->cool_dev != cdev)
164 		return 0;
165 
166 	/* Simple thing, two trips, one passive another critical */
167 	return thermal_zone_unbind_cooling_device(thermal, 0, cdev);
168 }
169 
170 /* Get mode callback functions for thermal zone */
171 static int ti_thermal_get_mode(struct thermal_zone_device *thermal,
172 			       enum thermal_device_mode *mode)
173 {
174 	struct ti_thermal_data *data = thermal->devdata;
175 
176 	if (data)
177 		*mode = data->mode;
178 
179 	return 0;
180 }
181 
182 /* Set mode callback functions for thermal zone */
183 static int ti_thermal_set_mode(struct thermal_zone_device *thermal,
184 			       enum thermal_device_mode mode)
185 {
186 	struct ti_thermal_data *data = thermal->devdata;
187 	struct ti_bandgap *bgp;
188 
189 	bgp = data->bgp;
190 
191 	if (!data->ti_thermal) {
192 		dev_notice(&thermal->device, "thermal zone not registered\n");
193 		return 0;
194 	}
195 
196 	mutex_lock(&data->ti_thermal->lock);
197 
198 	if (mode == THERMAL_DEVICE_ENABLED)
199 		data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
200 	else
201 		data->ti_thermal->polling_delay = 0;
202 
203 	mutex_unlock(&data->ti_thermal->lock);
204 
205 	data->mode = mode;
206 	ti_bandgap_write_update_interval(bgp, data->sensor_id,
207 					data->ti_thermal->polling_delay);
208 	thermal_zone_device_update(data->ti_thermal);
209 	dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n",
210 		data->ti_thermal->polling_delay);
211 
212 	return 0;
213 }
214 
215 /* Get trip type callback functions for thermal zone */
216 static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal,
217 				    int trip, enum thermal_trip_type *type)
218 {
219 	if (!ti_thermal_is_valid_trip(trip))
220 		return -EINVAL;
221 
222 	if (trip + 1 == OMAP_TRIP_NUMBER)
223 		*type = THERMAL_TRIP_CRITICAL;
224 	else
225 		*type = THERMAL_TRIP_PASSIVE;
226 
227 	return 0;
228 }
229 
230 /* Get trip temperature callback functions for thermal zone */
231 static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
232 				    int trip, unsigned long *temp)
233 {
234 	if (!ti_thermal_is_valid_trip(trip))
235 		return -EINVAL;
236 
237 	*temp = ti_thermal_get_trip_value(trip);
238 
239 	return 0;
240 }
241 
242 static int __ti_thermal_get_trend(void *p, long *trend)
243 {
244 	struct ti_thermal_data *data = p;
245 	struct ti_bandgap *bgp;
246 	int id, tr, ret = 0;
247 
248 	bgp = data->bgp;
249 	id = data->sensor_id;
250 
251 	ret = ti_bandgap_get_trend(bgp, id, &tr);
252 	if (ret)
253 		return ret;
254 
255 	*trend = tr;
256 
257 	return 0;
258 }
259 
260 /* Get the temperature trend callback functions for thermal zone */
261 static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
262 				int trip, enum thermal_trend *trend)
263 {
264 	int ret;
265 	long tr;
266 
267 	ret = __ti_thermal_get_trend(thermal->devdata, &tr);
268 	if (ret)
269 		return ret;
270 
271 	if (tr > 0)
272 		*trend = THERMAL_TREND_RAISING;
273 	else if (tr < 0)
274 		*trend = THERMAL_TREND_DROPPING;
275 	else
276 		*trend = THERMAL_TREND_STABLE;
277 
278 	return 0;
279 }
280 
281 /* Get critical temperature callback functions for thermal zone */
282 static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
283 				    unsigned long *temp)
284 {
285 	/* shutdown zone */
286 	return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
287 }
288 
289 static struct thermal_zone_device_ops ti_thermal_ops = {
290 	.get_temp = ti_thermal_get_temp,
291 	.get_trend = ti_thermal_get_trend,
292 	.bind = ti_thermal_bind,
293 	.unbind = ti_thermal_unbind,
294 	.get_mode = ti_thermal_get_mode,
295 	.set_mode = ti_thermal_set_mode,
296 	.get_trip_type = ti_thermal_get_trip_type,
297 	.get_trip_temp = ti_thermal_get_trip_temp,
298 	.get_crit_temp = ti_thermal_get_crit_temp,
299 };
300 
301 static struct ti_thermal_data
302 *ti_thermal_build_data(struct ti_bandgap *bgp, int id)
303 {
304 	struct ti_thermal_data *data;
305 
306 	data = devm_kzalloc(bgp->dev, sizeof(*data), GFP_KERNEL);
307 	if (!data) {
308 		dev_err(bgp->dev, "kzalloc fail\n");
309 		return NULL;
310 	}
311 	data->sensor_id = id;
312 	data->bgp = bgp;
313 	data->mode = THERMAL_DEVICE_ENABLED;
314 	/* pcb_tz will be either valid or PTR_ERR() */
315 	data->pcb_tz = thermal_zone_get_zone_by_name("pcb");
316 	INIT_WORK(&data->thermal_wq, ti_thermal_work);
317 
318 	return data;
319 }
320 
321 int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
322 			     char *domain)
323 {
324 	struct ti_thermal_data *data;
325 
326 	data = ti_bandgap_get_sensor_data(bgp, id);
327 
328 	if (!data || IS_ERR(data))
329 		data = ti_thermal_build_data(bgp, id);
330 
331 	if (!data)
332 		return -EINVAL;
333 
334 	/* in case this is specified by DT */
335 	data->ti_thermal = thermal_zone_of_sensor_register(bgp->dev, id,
336 					data, __ti_thermal_get_temp,
337 					__ti_thermal_get_trend);
338 	if (IS_ERR(data->ti_thermal)) {
339 		/* Create thermal zone */
340 		data->ti_thermal = thermal_zone_device_register(domain,
341 				OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
342 				NULL, FAST_TEMP_MONITORING_RATE,
343 				FAST_TEMP_MONITORING_RATE);
344 		if (IS_ERR(data->ti_thermal)) {
345 			dev_err(bgp->dev, "thermal zone device is NULL\n");
346 			return PTR_ERR(data->ti_thermal);
347 		}
348 		data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
349 		data->our_zone = true;
350 	}
351 	ti_bandgap_set_sensor_data(bgp, id, data);
352 	ti_bandgap_write_update_interval(bgp, data->sensor_id,
353 					data->ti_thermal->polling_delay);
354 
355 	return 0;
356 }
357 
358 int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
359 {
360 	struct ti_thermal_data *data;
361 
362 	data = ti_bandgap_get_sensor_data(bgp, id);
363 
364 	if (data && data->ti_thermal) {
365 		if (data->our_zone)
366 			thermal_zone_device_unregister(data->ti_thermal);
367 		else
368 			thermal_zone_of_sensor_unregister(bgp->dev,
369 							  data->ti_thermal);
370 	}
371 
372 	return 0;
373 }
374 
375 int ti_thermal_report_sensor_temperature(struct ti_bandgap *bgp, int id)
376 {
377 	struct ti_thermal_data *data;
378 
379 	data = ti_bandgap_get_sensor_data(bgp, id);
380 
381 	schedule_work(&data->thermal_wq);
382 
383 	return 0;
384 }
385 
386 int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id)
387 {
388 	struct ti_thermal_data *data;
389 	struct device_node *np = bgp->dev->of_node;
390 
391 	/*
392 	 * We are assuming here that if one deploys the zone
393 	 * using DT, then it must be aware that the cooling device
394 	 * loading has to happen via cpufreq driver.
395 	 */
396 	if (of_find_property(np, "#thermal-sensor-cells", NULL))
397 		return 0;
398 
399 	data = ti_bandgap_get_sensor_data(bgp, id);
400 	if (!data || IS_ERR(data))
401 		data = ti_thermal_build_data(bgp, id);
402 
403 	if (!data)
404 		return -EINVAL;
405 
406 	if (!cpufreq_get_current_driver()) {
407 		dev_dbg(bgp->dev, "no cpufreq driver yet\n");
408 		return -EPROBE_DEFER;
409 	}
410 
411 	/* Register cooling device */
412 	data->cool_dev = cpufreq_cooling_register(cpu_present_mask);
413 	if (IS_ERR(data->cool_dev)) {
414 		dev_err(bgp->dev,
415 			"Failed to register cpufreq cooling device\n");
416 		return PTR_ERR(data->cool_dev);
417 	}
418 	ti_bandgap_set_sensor_data(bgp, id, data);
419 
420 	return 0;
421 }
422 
423 int ti_thermal_unregister_cpu_cooling(struct ti_bandgap *bgp, int id)
424 {
425 	struct ti_thermal_data *data;
426 
427 	data = ti_bandgap_get_sensor_data(bgp, id);
428 
429 	if (data && data->cool_dev)
430 		cpufreq_cooling_unregister(data->cool_dev);
431 
432 	return 0;
433 }
434