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 #define X86_FAMILY_QUARK 0x5 68 #define X86_MODEL_QUARK_X1000 0x9 69 70 /* DTS reset is programmed via QRK_MBI_UNIT_SOC */ 71 #define QRK_DTS_REG_OFFSET_RESET 0x34 72 #define QRK_DTS_RESET_BIT BIT(0) 73 74 /* DTS enable is programmed via QRK_MBI_UNIT_RMU */ 75 #define QRK_DTS_REG_OFFSET_ENABLE 0xB0 76 #define QRK_DTS_ENABLE_BIT BIT(15) 77 78 /* Temperature Register is read via QRK_MBI_UNIT_RMU */ 79 #define QRK_DTS_REG_OFFSET_TEMP 0xB1 80 #define QRK_DTS_MASK_TEMP 0xFF 81 #define QRK_DTS_OFFSET_TEMP 0 82 #define QRK_DTS_OFFSET_REL_TEMP 16 83 #define QRK_DTS_TEMP_BASE 50 84 85 /* Programmable Trip Point Register is configured via QRK_MBI_UNIT_RMU */ 86 #define QRK_DTS_REG_OFFSET_PTPS 0xB2 87 #define QRK_DTS_MASK_TP_THRES 0xFF 88 #define QRK_DTS_SHIFT_TP 8 89 #define QRK_DTS_ID_TP_CRITICAL 0 90 #define QRK_DTS_SAFE_TP_THRES 105 91 92 /* Thermal Sensor Register Lock */ 93 #define QRK_DTS_REG_OFFSET_LOCK 0x71 94 #define QRK_DTS_LOCK_BIT BIT(5) 95 96 /* Quark DTS has 2 trip points: hot & catastrophic */ 97 #define QRK_MAX_DTS_TRIPS 2 98 /* If DTS not locked, all trip points are configurable */ 99 #define QRK_DTS_WR_MASK_SET 0x3 100 /* If DTS locked, all trip points are not configurable */ 101 #define QRK_DTS_WR_MASK_CLR 0 102 103 #define DEFAULT_POLL_DELAY 2000 104 105 struct soc_sensor_entry { 106 bool locked; 107 u32 store_ptps; 108 u32 store_dts_enable; 109 enum thermal_device_mode mode; 110 struct thermal_zone_device *tzone; 111 }; 112 113 static struct soc_sensor_entry *soc_dts; 114 115 static int polling_delay = DEFAULT_POLL_DELAY; 116 module_param(polling_delay, int, 0644); 117 MODULE_PARM_DESC(polling_delay, 118 "Polling interval for checking trip points (in milliseconds)"); 119 120 static DEFINE_MUTEX(dts_update_mutex); 121 122 static int soc_dts_enable(struct thermal_zone_device *tzd) 123 { 124 u32 out; 125 struct soc_sensor_entry *aux_entry = tzd->devdata; 126 int ret; 127 128 ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ, 129 QRK_DTS_REG_OFFSET_ENABLE, &out); 130 if (ret) 131 return ret; 132 133 if (out & QRK_DTS_ENABLE_BIT) { 134 aux_entry->mode = THERMAL_DEVICE_ENABLED; 135 return 0; 136 } 137 138 if (!aux_entry->locked) { 139 out |= QRK_DTS_ENABLE_BIT; 140 ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE, 141 QRK_DTS_REG_OFFSET_ENABLE, out); 142 if (ret) 143 return ret; 144 145 aux_entry->mode = THERMAL_DEVICE_ENABLED; 146 } else { 147 aux_entry->mode = THERMAL_DEVICE_DISABLED; 148 pr_info("DTS is locked. Cannot enable DTS\n"); 149 ret = -EPERM; 150 } 151 152 return ret; 153 } 154 155 static int soc_dts_disable(struct thermal_zone_device *tzd) 156 { 157 u32 out; 158 struct soc_sensor_entry *aux_entry = tzd->devdata; 159 int ret; 160 161 ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ, 162 QRK_DTS_REG_OFFSET_ENABLE, &out); 163 if (ret) 164 return ret; 165 166 if (!(out & QRK_DTS_ENABLE_BIT)) { 167 aux_entry->mode = THERMAL_DEVICE_DISABLED; 168 return 0; 169 } 170 171 if (!aux_entry->locked) { 172 out &= ~QRK_DTS_ENABLE_BIT; 173 ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE, 174 QRK_DTS_REG_OFFSET_ENABLE, out); 175 176 if (ret) 177 return ret; 178 179 aux_entry->mode = THERMAL_DEVICE_DISABLED; 180 } else { 181 aux_entry->mode = THERMAL_DEVICE_ENABLED; 182 pr_info("DTS is locked. Cannot disable DTS\n"); 183 ret = -EPERM; 184 } 185 186 return ret; 187 } 188 189 static int _get_trip_temp(int trip, int *temp) 190 { 191 int status; 192 u32 out; 193 194 mutex_lock(&dts_update_mutex); 195 status = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ, 196 QRK_DTS_REG_OFFSET_PTPS, &out); 197 mutex_unlock(&dts_update_mutex); 198 199 if (status) 200 return status; 201 202 /* 203 * Thermal Sensor Programmable Trip Point Register has 8-bit 204 * fields for critical (catastrophic) and hot set trip point 205 * thresholds. The threshold value is always offset by its 206 * temperature base (50 degree Celsius). 207 */ 208 *temp = (out >> (trip * QRK_DTS_SHIFT_TP)) & QRK_DTS_MASK_TP_THRES; 209 *temp -= QRK_DTS_TEMP_BASE; 210 211 return 0; 212 } 213 214 static inline int sys_get_trip_temp(struct thermal_zone_device *tzd, 215 int trip, int *temp) 216 { 217 return _get_trip_temp(trip, temp); 218 } 219 220 static inline int sys_get_crit_temp(struct thermal_zone_device *tzd, int *temp) 221 { 222 return _get_trip_temp(QRK_DTS_ID_TP_CRITICAL, temp); 223 } 224 225 static int update_trip_temp(struct soc_sensor_entry *aux_entry, 226 int trip, int temp) 227 { 228 u32 out; 229 u32 temp_out; 230 u32 store_ptps; 231 int ret; 232 233 mutex_lock(&dts_update_mutex); 234 if (aux_entry->locked) { 235 ret = -EPERM; 236 goto failed; 237 } 238 239 ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ, 240 QRK_DTS_REG_OFFSET_PTPS, &store_ptps); 241 if (ret) 242 goto failed; 243 244 /* 245 * Protection against unsafe trip point thresdhold value. 246 * As Quark X1000 data-sheet does not provide any recommendation 247 * regarding the safe trip point threshold value to use, we choose 248 * the safe value according to the threshold value set by UEFI BIOS. 249 */ 250 if (temp > QRK_DTS_SAFE_TP_THRES) 251 temp = QRK_DTS_SAFE_TP_THRES; 252 253 /* 254 * Thermal Sensor Programmable Trip Point Register has 8-bit 255 * fields for critical (catastrophic) and hot set trip point 256 * thresholds. The threshold value is always offset by its 257 * temperature base (50 degree Celsius). 258 */ 259 temp_out = temp + QRK_DTS_TEMP_BASE; 260 out = (store_ptps & ~(QRK_DTS_MASK_TP_THRES << 261 (trip * QRK_DTS_SHIFT_TP))); 262 out |= (temp_out & QRK_DTS_MASK_TP_THRES) << 263 (trip * QRK_DTS_SHIFT_TP); 264 265 ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE, 266 QRK_DTS_REG_OFFSET_PTPS, out); 267 268 failed: 269 mutex_unlock(&dts_update_mutex); 270 return ret; 271 } 272 273 static inline int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, 274 int temp) 275 { 276 return update_trip_temp(tzd->devdata, trip, temp); 277 } 278 279 static int sys_get_trip_type(struct thermal_zone_device *thermal, 280 int trip, enum thermal_trip_type *type) 281 { 282 if (trip) 283 *type = THERMAL_TRIP_HOT; 284 else 285 *type = THERMAL_TRIP_CRITICAL; 286 287 return 0; 288 } 289 290 static int sys_get_curr_temp(struct thermal_zone_device *tzd, 291 int *temp) 292 { 293 u32 out; 294 int ret; 295 296 mutex_lock(&dts_update_mutex); 297 ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ, 298 QRK_DTS_REG_OFFSET_TEMP, &out); 299 mutex_unlock(&dts_update_mutex); 300 301 if (ret) 302 return ret; 303 304 /* 305 * Thermal Sensor Temperature Register has 8-bit field 306 * for temperature value (offset by temperature base 307 * 50 degree Celsius). 308 */ 309 out = (out >> QRK_DTS_OFFSET_TEMP) & QRK_DTS_MASK_TEMP; 310 *temp = out - QRK_DTS_TEMP_BASE; 311 312 return 0; 313 } 314 315 static int sys_get_mode(struct thermal_zone_device *tzd, 316 enum thermal_device_mode *mode) 317 { 318 struct soc_sensor_entry *aux_entry = tzd->devdata; 319 *mode = aux_entry->mode; 320 return 0; 321 } 322 323 static int sys_set_mode(struct thermal_zone_device *tzd, 324 enum thermal_device_mode mode) 325 { 326 int ret; 327 328 mutex_lock(&dts_update_mutex); 329 if (mode == THERMAL_DEVICE_ENABLED) 330 ret = soc_dts_enable(tzd); 331 else 332 ret = soc_dts_disable(tzd); 333 mutex_unlock(&dts_update_mutex); 334 335 return ret; 336 } 337 338 static struct thermal_zone_device_ops tzone_ops = { 339 .get_temp = sys_get_curr_temp, 340 .get_trip_temp = sys_get_trip_temp, 341 .get_trip_type = sys_get_trip_type, 342 .set_trip_temp = sys_set_trip_temp, 343 .get_crit_temp = sys_get_crit_temp, 344 .get_mode = sys_get_mode, 345 .set_mode = sys_set_mode, 346 }; 347 348 static void free_soc_dts(struct soc_sensor_entry *aux_entry) 349 { 350 if (aux_entry) { 351 if (!aux_entry->locked) { 352 mutex_lock(&dts_update_mutex); 353 iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE, 354 QRK_DTS_REG_OFFSET_ENABLE, 355 aux_entry->store_dts_enable); 356 357 iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE, 358 QRK_DTS_REG_OFFSET_PTPS, 359 aux_entry->store_ptps); 360 mutex_unlock(&dts_update_mutex); 361 } 362 thermal_zone_device_unregister(aux_entry->tzone); 363 kfree(aux_entry); 364 } 365 } 366 367 static struct soc_sensor_entry *alloc_soc_dts(void) 368 { 369 struct soc_sensor_entry *aux_entry; 370 int err; 371 u32 out; 372 int wr_mask; 373 374 aux_entry = kzalloc(sizeof(*aux_entry), GFP_KERNEL); 375 if (!aux_entry) { 376 err = -ENOMEM; 377 return ERR_PTR(-ENOMEM); 378 } 379 380 /* Check if DTS register is locked */ 381 err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ, 382 QRK_DTS_REG_OFFSET_LOCK, &out); 383 if (err) 384 goto err_ret; 385 386 if (out & QRK_DTS_LOCK_BIT) { 387 aux_entry->locked = true; 388 wr_mask = QRK_DTS_WR_MASK_CLR; 389 } else { 390 aux_entry->locked = false; 391 wr_mask = QRK_DTS_WR_MASK_SET; 392 } 393 394 /* Store DTS default state if DTS registers are not locked */ 395 if (!aux_entry->locked) { 396 /* Store DTS default enable for restore on exit */ 397 err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ, 398 QRK_DTS_REG_OFFSET_ENABLE, 399 &aux_entry->store_dts_enable); 400 if (err) 401 goto err_ret; 402 403 /* Store DTS default PTPS register for restore on exit */ 404 err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ, 405 QRK_DTS_REG_OFFSET_PTPS, 406 &aux_entry->store_ptps); 407 if (err) 408 goto err_ret; 409 } 410 411 aux_entry->tzone = thermal_zone_device_register("quark_dts", 412 QRK_MAX_DTS_TRIPS, 413 wr_mask, 414 aux_entry, &tzone_ops, NULL, 0, polling_delay); 415 if (IS_ERR(aux_entry->tzone)) { 416 err = PTR_ERR(aux_entry->tzone); 417 goto err_ret; 418 } 419 420 mutex_lock(&dts_update_mutex); 421 err = soc_dts_enable(aux_entry->tzone); 422 mutex_unlock(&dts_update_mutex); 423 if (err) 424 goto err_aux_status; 425 426 return aux_entry; 427 428 err_aux_status: 429 thermal_zone_device_unregister(aux_entry->tzone); 430 err_ret: 431 kfree(aux_entry); 432 return ERR_PTR(err); 433 } 434 435 static const struct x86_cpu_id qrk_thermal_ids[] __initconst = { 436 { X86_VENDOR_INTEL, X86_FAMILY_QUARK, X86_MODEL_QUARK_X1000 }, 437 {} 438 }; 439 MODULE_DEVICE_TABLE(x86cpu, qrk_thermal_ids); 440 441 static int __init intel_quark_thermal_init(void) 442 { 443 int err = 0; 444 445 if (!x86_match_cpu(qrk_thermal_ids) || !iosf_mbi_available()) 446 return -ENODEV; 447 448 soc_dts = alloc_soc_dts(); 449 if (IS_ERR(soc_dts)) { 450 err = PTR_ERR(soc_dts); 451 goto err_free; 452 } 453 454 return 0; 455 456 err_free: 457 free_soc_dts(soc_dts); 458 return err; 459 } 460 461 static void __exit intel_quark_thermal_exit(void) 462 { 463 free_soc_dts(soc_dts); 464 } 465 466 module_init(intel_quark_thermal_init) 467 module_exit(intel_quark_thermal_exit) 468 469 MODULE_DESCRIPTION("Intel Quark DTS Thermal Driver"); 470 MODULE_AUTHOR("Ong Boon Leong <boon.leong.ong@intel.com>"); 471 MODULE_LICENSE("Dual BSD/GPL"); 472