1 /*
2  * intel_quark_dts_thermal.c
3  *
4  * This file is provided under a dual BSD/GPLv2 license.  When using or
5  * redistributing this file, you may do so under either license.
6  *
7  * GPL LICENSE SUMMARY
8  *
9  * Copyright(c) 2015 Intel Corporation.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of version 2 of the GNU General Public License as
13  * published by the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  *  WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * Contact Information:
21  *  Ong Boon Leong <boon.leong.ong@intel.com>
22  *  Intel Malaysia, Penang
23  *
24  * BSD LICENSE
25  *
26  * Copyright(c) 2015 Intel Corporation.
27  *
28  * Redistribution and use in source and binary forms, with or without
29  * modification, are permitted provided that the following conditions
30  * are met:
31  *
32  *   * Redistributions of source code must retain the above copyright
33  *     notice, this list of conditions and the following disclaimer.
34  *   * Redistributions in binary form must reproduce the above copyright
35  *     notice, this list of conditions and the following disclaimer in
36  *     the documentation and/or other materials provided with the
37  *     distribution.
38  *   * Neither the name of Intel Corporation nor the names of its
39  *     contributors may be used to endorse or promote products derived
40  *     from this software without specific prior written permission.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53  *
54  * Quark DTS thermal driver is implemented by referencing
55  * intel_soc_dts_thermal.c.
56  */
57 
58 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
59 
60 #include <linux/module.h>
61 #include <linux/slab.h>
62 #include <linux/interrupt.h>
63 #include <linux/thermal.h>
64 #include <asm/cpu_device_id.h>
65 #include <asm/iosf_mbi.h>
66 
67 /* DTS reset is programmed via QRK_MBI_UNIT_SOC */
68 #define QRK_DTS_REG_OFFSET_RESET	0x34
69 #define QRK_DTS_RESET_BIT		BIT(0)
70 
71 /* DTS enable is programmed via QRK_MBI_UNIT_RMU */
72 #define QRK_DTS_REG_OFFSET_ENABLE	0xB0
73 #define QRK_DTS_ENABLE_BIT		BIT(15)
74 
75 /* Temperature Register is read via QRK_MBI_UNIT_RMU */
76 #define QRK_DTS_REG_OFFSET_TEMP		0xB1
77 #define QRK_DTS_MASK_TEMP		0xFF
78 #define QRK_DTS_OFFSET_TEMP		0
79 #define QRK_DTS_OFFSET_REL_TEMP		16
80 #define QRK_DTS_TEMP_BASE		50
81 
82 /* Programmable Trip Point Register is configured via QRK_MBI_UNIT_RMU */
83 #define QRK_DTS_REG_OFFSET_PTPS		0xB2
84 #define QRK_DTS_MASK_TP_THRES		0xFF
85 #define QRK_DTS_SHIFT_TP		8
86 #define QRK_DTS_ID_TP_CRITICAL		0
87 #define QRK_DTS_SAFE_TP_THRES		105
88 
89 /* Thermal Sensor Register Lock */
90 #define QRK_DTS_REG_OFFSET_LOCK		0x71
91 #define QRK_DTS_LOCK_BIT		BIT(5)
92 
93 /* Quark DTS has 2 trip points: hot & catastrophic */
94 #define QRK_MAX_DTS_TRIPS	2
95 /* If DTS not locked, all trip points are configurable */
96 #define QRK_DTS_WR_MASK_SET	0x3
97 /* If DTS locked, all trip points are not configurable */
98 #define QRK_DTS_WR_MASK_CLR	0
99 
100 #define DEFAULT_POLL_DELAY	2000
101 
102 struct soc_sensor_entry {
103 	bool locked;
104 	u32 store_ptps;
105 	u32 store_dts_enable;
106 	enum thermal_device_mode mode;
107 	struct thermal_zone_device *tzone;
108 };
109 
110 static struct soc_sensor_entry *soc_dts;
111 
112 static int polling_delay = DEFAULT_POLL_DELAY;
113 module_param(polling_delay, int, 0644);
114 MODULE_PARM_DESC(polling_delay,
115 	"Polling interval for checking trip points (in milliseconds)");
116 
117 static DEFINE_MUTEX(dts_update_mutex);
118 
119 static int soc_dts_enable(struct thermal_zone_device *tzd)
120 {
121 	u32 out;
122 	struct soc_sensor_entry *aux_entry = tzd->devdata;
123 	int ret;
124 
125 	ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
126 			    QRK_DTS_REG_OFFSET_ENABLE, &out);
127 	if (ret)
128 		return ret;
129 
130 	if (out & QRK_DTS_ENABLE_BIT) {
131 		aux_entry->mode = THERMAL_DEVICE_ENABLED;
132 		return 0;
133 	}
134 
135 	if (!aux_entry->locked) {
136 		out |= QRK_DTS_ENABLE_BIT;
137 		ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
138 				     QRK_DTS_REG_OFFSET_ENABLE, out);
139 		if (ret)
140 			return ret;
141 
142 		aux_entry->mode = THERMAL_DEVICE_ENABLED;
143 	} else {
144 		aux_entry->mode = THERMAL_DEVICE_DISABLED;
145 		pr_info("DTS is locked. Cannot enable DTS\n");
146 		ret = -EPERM;
147 	}
148 
149 	return ret;
150 }
151 
152 static int soc_dts_disable(struct thermal_zone_device *tzd)
153 {
154 	u32 out;
155 	struct soc_sensor_entry *aux_entry = tzd->devdata;
156 	int ret;
157 
158 	ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
159 			    QRK_DTS_REG_OFFSET_ENABLE, &out);
160 	if (ret)
161 		return ret;
162 
163 	if (!(out & QRK_DTS_ENABLE_BIT)) {
164 		aux_entry->mode = THERMAL_DEVICE_DISABLED;
165 		return 0;
166 	}
167 
168 	if (!aux_entry->locked) {
169 		out &= ~QRK_DTS_ENABLE_BIT;
170 		ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
171 				     QRK_DTS_REG_OFFSET_ENABLE, out);
172 
173 		if (ret)
174 			return ret;
175 
176 		aux_entry->mode = THERMAL_DEVICE_DISABLED;
177 	} else {
178 		aux_entry->mode = THERMAL_DEVICE_ENABLED;
179 		pr_info("DTS is locked. Cannot disable DTS\n");
180 		ret = -EPERM;
181 	}
182 
183 	return ret;
184 }
185 
186 static int _get_trip_temp(int trip, int *temp)
187 {
188 	int status;
189 	u32 out;
190 
191 	mutex_lock(&dts_update_mutex);
192 	status = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
193 			       QRK_DTS_REG_OFFSET_PTPS, &out);
194 	mutex_unlock(&dts_update_mutex);
195 
196 	if (status)
197 		return status;
198 
199 	/*
200 	 * Thermal Sensor Programmable Trip Point Register has 8-bit
201 	 * fields for critical (catastrophic) and hot set trip point
202 	 * thresholds. The threshold value is always offset by its
203 	 * temperature base (50 degree Celsius).
204 	 */
205 	*temp = (out >> (trip * QRK_DTS_SHIFT_TP)) & QRK_DTS_MASK_TP_THRES;
206 	*temp -= QRK_DTS_TEMP_BASE;
207 
208 	return 0;
209 }
210 
211 static inline int sys_get_trip_temp(struct thermal_zone_device *tzd,
212 				int trip, int *temp)
213 {
214 	return _get_trip_temp(trip, temp);
215 }
216 
217 static inline int sys_get_crit_temp(struct thermal_zone_device *tzd, int *temp)
218 {
219 	return _get_trip_temp(QRK_DTS_ID_TP_CRITICAL, temp);
220 }
221 
222 static int update_trip_temp(struct soc_sensor_entry *aux_entry,
223 				int trip, int temp)
224 {
225 	u32 out;
226 	u32 temp_out;
227 	u32 store_ptps;
228 	int ret;
229 
230 	mutex_lock(&dts_update_mutex);
231 	if (aux_entry->locked) {
232 		ret = -EPERM;
233 		goto failed;
234 	}
235 
236 	ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
237 			    QRK_DTS_REG_OFFSET_PTPS, &store_ptps);
238 	if (ret)
239 		goto failed;
240 
241 	/*
242 	 * Protection against unsafe trip point thresdhold value.
243 	 * As Quark X1000 data-sheet does not provide any recommendation
244 	 * regarding the safe trip point threshold value to use, we choose
245 	 * the safe value according to the threshold value set by UEFI BIOS.
246 	 */
247 	if (temp > QRK_DTS_SAFE_TP_THRES)
248 		temp = QRK_DTS_SAFE_TP_THRES;
249 
250 	/*
251 	 * Thermal Sensor Programmable Trip Point Register has 8-bit
252 	 * fields for critical (catastrophic) and hot set trip point
253 	 * thresholds. The threshold value is always offset by its
254 	 * temperature base (50 degree Celsius).
255 	 */
256 	temp_out = temp + QRK_DTS_TEMP_BASE;
257 	out = (store_ptps & ~(QRK_DTS_MASK_TP_THRES <<
258 		(trip * QRK_DTS_SHIFT_TP)));
259 	out |= (temp_out & QRK_DTS_MASK_TP_THRES) <<
260 		(trip * QRK_DTS_SHIFT_TP);
261 
262 	ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
263 			     QRK_DTS_REG_OFFSET_PTPS, out);
264 
265 failed:
266 	mutex_unlock(&dts_update_mutex);
267 	return ret;
268 }
269 
270 static inline int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
271 				int temp)
272 {
273 	return update_trip_temp(tzd->devdata, trip, temp);
274 }
275 
276 static int sys_get_trip_type(struct thermal_zone_device *thermal,
277 		int trip, enum thermal_trip_type *type)
278 {
279 	if (trip)
280 		*type = THERMAL_TRIP_HOT;
281 	else
282 		*type = THERMAL_TRIP_CRITICAL;
283 
284 	return 0;
285 }
286 
287 static int sys_get_curr_temp(struct thermal_zone_device *tzd,
288 				int *temp)
289 {
290 	u32 out;
291 	int ret;
292 
293 	mutex_lock(&dts_update_mutex);
294 	ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
295 			    QRK_DTS_REG_OFFSET_TEMP, &out);
296 	mutex_unlock(&dts_update_mutex);
297 
298 	if (ret)
299 		return ret;
300 
301 	/*
302 	 * Thermal Sensor Temperature Register has 8-bit field
303 	 * for temperature value (offset by temperature base
304 	 * 50 degree Celsius).
305 	 */
306 	out = (out >> QRK_DTS_OFFSET_TEMP) & QRK_DTS_MASK_TEMP;
307 	*temp = out - QRK_DTS_TEMP_BASE;
308 
309 	return 0;
310 }
311 
312 static int sys_get_mode(struct thermal_zone_device *tzd,
313 				enum thermal_device_mode *mode)
314 {
315 	struct soc_sensor_entry *aux_entry = tzd->devdata;
316 	*mode = aux_entry->mode;
317 	return 0;
318 }
319 
320 static int sys_set_mode(struct thermal_zone_device *tzd,
321 				enum thermal_device_mode mode)
322 {
323 	int ret;
324 
325 	mutex_lock(&dts_update_mutex);
326 	if (mode == THERMAL_DEVICE_ENABLED)
327 		ret = soc_dts_enable(tzd);
328 	else
329 		ret = soc_dts_disable(tzd);
330 	mutex_unlock(&dts_update_mutex);
331 
332 	return ret;
333 }
334 
335 static struct thermal_zone_device_ops tzone_ops = {
336 	.get_temp = sys_get_curr_temp,
337 	.get_trip_temp = sys_get_trip_temp,
338 	.get_trip_type = sys_get_trip_type,
339 	.set_trip_temp = sys_set_trip_temp,
340 	.get_crit_temp = sys_get_crit_temp,
341 	.get_mode = sys_get_mode,
342 	.set_mode = sys_set_mode,
343 };
344 
345 static void free_soc_dts(struct soc_sensor_entry *aux_entry)
346 {
347 	if (aux_entry) {
348 		if (!aux_entry->locked) {
349 			mutex_lock(&dts_update_mutex);
350 			iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
351 				       QRK_DTS_REG_OFFSET_ENABLE,
352 				       aux_entry->store_dts_enable);
353 
354 			iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
355 				       QRK_DTS_REG_OFFSET_PTPS,
356 				       aux_entry->store_ptps);
357 			mutex_unlock(&dts_update_mutex);
358 		}
359 		thermal_zone_device_unregister(aux_entry->tzone);
360 		kfree(aux_entry);
361 	}
362 }
363 
364 static struct soc_sensor_entry *alloc_soc_dts(void)
365 {
366 	struct soc_sensor_entry *aux_entry;
367 	int err;
368 	u32 out;
369 	int wr_mask;
370 
371 	aux_entry = kzalloc(sizeof(*aux_entry), GFP_KERNEL);
372 	if (!aux_entry) {
373 		err = -ENOMEM;
374 		return ERR_PTR(-ENOMEM);
375 	}
376 
377 	/* Check if DTS register is locked */
378 	err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
379 			    QRK_DTS_REG_OFFSET_LOCK, &out);
380 	if (err)
381 		goto err_ret;
382 
383 	if (out & QRK_DTS_LOCK_BIT) {
384 		aux_entry->locked = true;
385 		wr_mask = QRK_DTS_WR_MASK_CLR;
386 	} else {
387 		aux_entry->locked = false;
388 		wr_mask = QRK_DTS_WR_MASK_SET;
389 	}
390 
391 	/* Store DTS default state if DTS registers are not locked */
392 	if (!aux_entry->locked) {
393 		/* Store DTS default enable for restore on exit */
394 		err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
395 				    QRK_DTS_REG_OFFSET_ENABLE,
396 				    &aux_entry->store_dts_enable);
397 		if (err)
398 			goto err_ret;
399 
400 		/* Store DTS default PTPS register for restore on exit */
401 		err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
402 				    QRK_DTS_REG_OFFSET_PTPS,
403 				    &aux_entry->store_ptps);
404 		if (err)
405 			goto err_ret;
406 	}
407 
408 	aux_entry->tzone = thermal_zone_device_register("quark_dts",
409 			QRK_MAX_DTS_TRIPS,
410 			wr_mask,
411 			aux_entry, &tzone_ops, NULL, 0, polling_delay);
412 	if (IS_ERR(aux_entry->tzone)) {
413 		err = PTR_ERR(aux_entry->tzone);
414 		goto err_ret;
415 	}
416 
417 	mutex_lock(&dts_update_mutex);
418 	err = soc_dts_enable(aux_entry->tzone);
419 	mutex_unlock(&dts_update_mutex);
420 	if (err)
421 		goto err_aux_status;
422 
423 	return aux_entry;
424 
425 err_aux_status:
426 	thermal_zone_device_unregister(aux_entry->tzone);
427 err_ret:
428 	kfree(aux_entry);
429 	return ERR_PTR(err);
430 }
431 
432 static const struct x86_cpu_id qrk_thermal_ids[] __initconst  = {
433 	X86_MATCH_VENDOR_FAM_MODEL(INTEL, 5, INTEL_FAM5_QUARK_X1000, NULL),
434 	{}
435 };
436 MODULE_DEVICE_TABLE(x86cpu, qrk_thermal_ids);
437 
438 static int __init intel_quark_thermal_init(void)
439 {
440 	int err = 0;
441 
442 	if (!x86_match_cpu(qrk_thermal_ids) || !iosf_mbi_available())
443 		return -ENODEV;
444 
445 	soc_dts = alloc_soc_dts();
446 	if (IS_ERR(soc_dts)) {
447 		err = PTR_ERR(soc_dts);
448 		goto err_free;
449 	}
450 
451 	return 0;
452 
453 err_free:
454 	free_soc_dts(soc_dts);
455 	return err;
456 }
457 
458 static void __exit intel_quark_thermal_exit(void)
459 {
460 	free_soc_dts(soc_dts);
461 }
462 
463 module_init(intel_quark_thermal_init)
464 module_exit(intel_quark_thermal_exit)
465 
466 MODULE_DESCRIPTION("Intel Quark DTS Thermal Driver");
467 MODULE_AUTHOR("Ong Boon Leong <boon.leong.ong@intel.com>");
468 MODULE_LICENSE("Dual BSD/GPL");
469