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