1 /* 2 * intel_soc_dts_iosf.c 3 * Copyright (c) 2015, Intel Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 */ 15 16 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 17 18 #include <linux/module.h> 19 #include <linux/slab.h> 20 #include <linux/interrupt.h> 21 #include <asm/iosf_mbi.h> 22 #include "intel_soc_dts_iosf.h" 23 24 #define SOC_DTS_OFFSET_ENABLE 0xB0 25 #define SOC_DTS_OFFSET_TEMP 0xB1 26 27 #define SOC_DTS_OFFSET_PTPS 0xB2 28 #define SOC_DTS_OFFSET_PTTS 0xB3 29 #define SOC_DTS_OFFSET_PTTSS 0xB4 30 #define SOC_DTS_OFFSET_PTMC 0x80 31 #define SOC_DTS_TE_AUX0 0xB5 32 #define SOC_DTS_TE_AUX1 0xB6 33 34 #define SOC_DTS_AUX0_ENABLE_BIT BIT(0) 35 #define SOC_DTS_AUX1_ENABLE_BIT BIT(1) 36 #define SOC_DTS_CPU_MODULE0_ENABLE_BIT BIT(16) 37 #define SOC_DTS_CPU_MODULE1_ENABLE_BIT BIT(17) 38 #define SOC_DTS_TE_SCI_ENABLE BIT(9) 39 #define SOC_DTS_TE_SMI_ENABLE BIT(10) 40 #define SOC_DTS_TE_MSI_ENABLE BIT(11) 41 #define SOC_DTS_TE_APICA_ENABLE BIT(14) 42 #define SOC_DTS_PTMC_APIC_DEASSERT_BIT BIT(4) 43 44 /* DTS encoding for TJ MAX temperature */ 45 #define SOC_DTS_TJMAX_ENCODING 0x7F 46 47 /* Only 2 out of 4 is allowed for OSPM */ 48 #define SOC_MAX_DTS_TRIPS 2 49 50 /* Mask for two trips in status bits */ 51 #define SOC_DTS_TRIP_MASK 0x03 52 53 /* DTS0 and DTS 1 */ 54 #define SOC_MAX_DTS_SENSORS 2 55 56 static int get_tj_max(u32 *tj_max) 57 { 58 u32 eax, edx; 59 u32 val; 60 int err; 61 62 err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); 63 if (err) 64 goto err_ret; 65 else { 66 val = (eax >> 16) & 0xff; 67 if (val) 68 *tj_max = val * 1000; 69 else { 70 err = -EINVAL; 71 goto err_ret; 72 } 73 } 74 75 return 0; 76 err_ret: 77 *tj_max = 0; 78 79 return err; 80 } 81 82 static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip, 83 int *temp) 84 { 85 int status; 86 u32 out; 87 struct intel_soc_dts_sensor_entry *dts; 88 struct intel_soc_dts_sensors *sensors; 89 90 dts = tzd->devdata; 91 sensors = dts->sensors; 92 mutex_lock(&sensors->dts_update_lock); 93 status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, 94 SOC_DTS_OFFSET_PTPS, &out); 95 mutex_unlock(&sensors->dts_update_lock); 96 if (status) 97 return status; 98 99 out = (out >> (trip * 8)) & SOC_DTS_TJMAX_ENCODING; 100 if (!out) 101 *temp = 0; 102 else 103 *temp = sensors->tj_max - out * 1000; 104 105 return 0; 106 } 107 108 static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts, 109 int thres_index, int temp, 110 enum thermal_trip_type trip_type) 111 { 112 int status; 113 u32 temp_out; 114 u32 out; 115 u32 store_ptps; 116 u32 store_ptmc; 117 u32 store_te_out; 118 u32 te_out; 119 u32 int_enable_bit = SOC_DTS_TE_APICA_ENABLE; 120 struct intel_soc_dts_sensors *sensors = dts->sensors; 121 122 if (sensors->intr_type == INTEL_SOC_DTS_INTERRUPT_MSI) 123 int_enable_bit |= SOC_DTS_TE_MSI_ENABLE; 124 125 temp_out = (sensors->tj_max - temp) / 1000; 126 127 status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, 128 SOC_DTS_OFFSET_PTPS, &store_ptps); 129 if (status) 130 return status; 131 132 out = (store_ptps & ~(0xFF << (thres_index * 8))); 133 out |= (temp_out & 0xFF) << (thres_index * 8); 134 status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, 135 SOC_DTS_OFFSET_PTPS, out); 136 if (status) 137 return status; 138 139 pr_debug("update_trip_temp PTPS = %x\n", out); 140 status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, 141 SOC_DTS_OFFSET_PTMC, &out); 142 if (status) 143 goto err_restore_ptps; 144 145 store_ptmc = out; 146 147 status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, 148 SOC_DTS_TE_AUX0 + thres_index, 149 &te_out); 150 if (status) 151 goto err_restore_ptmc; 152 153 store_te_out = te_out; 154 /* Enable for CPU module 0 and module 1 */ 155 out |= (SOC_DTS_CPU_MODULE0_ENABLE_BIT | 156 SOC_DTS_CPU_MODULE1_ENABLE_BIT); 157 if (temp) { 158 if (thres_index) 159 out |= SOC_DTS_AUX1_ENABLE_BIT; 160 else 161 out |= SOC_DTS_AUX0_ENABLE_BIT; 162 te_out |= int_enable_bit; 163 } else { 164 if (thres_index) 165 out &= ~SOC_DTS_AUX1_ENABLE_BIT; 166 else 167 out &= ~SOC_DTS_AUX0_ENABLE_BIT; 168 te_out &= ~int_enable_bit; 169 } 170 status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, 171 SOC_DTS_OFFSET_PTMC, out); 172 if (status) 173 goto err_restore_te_out; 174 175 status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, 176 SOC_DTS_TE_AUX0 + thres_index, 177 te_out); 178 if (status) 179 goto err_restore_te_out; 180 181 dts->trip_types[thres_index] = trip_type; 182 183 return 0; 184 err_restore_te_out: 185 iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, 186 SOC_DTS_OFFSET_PTMC, store_te_out); 187 err_restore_ptmc: 188 iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, 189 SOC_DTS_OFFSET_PTMC, store_ptmc); 190 err_restore_ptps: 191 iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, 192 SOC_DTS_OFFSET_PTPS, store_ptps); 193 /* Nothing we can do if restore fails */ 194 195 return status; 196 } 197 198 static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, 199 int temp) 200 { 201 struct intel_soc_dts_sensor_entry *dts = tzd->devdata; 202 struct intel_soc_dts_sensors *sensors = dts->sensors; 203 int status; 204 205 if (temp > sensors->tj_max) 206 return -EINVAL; 207 208 mutex_lock(&sensors->dts_update_lock); 209 status = update_trip_temp(tzd->devdata, trip, temp, 210 dts->trip_types[trip]); 211 mutex_unlock(&sensors->dts_update_lock); 212 213 return status; 214 } 215 216 static int sys_get_trip_type(struct thermal_zone_device *tzd, 217 int trip, enum thermal_trip_type *type) 218 { 219 struct intel_soc_dts_sensor_entry *dts; 220 221 dts = tzd->devdata; 222 223 *type = dts->trip_types[trip]; 224 225 return 0; 226 } 227 228 static int sys_get_curr_temp(struct thermal_zone_device *tzd, 229 int *temp) 230 { 231 int status; 232 u32 out; 233 struct intel_soc_dts_sensor_entry *dts; 234 struct intel_soc_dts_sensors *sensors; 235 236 dts = tzd->devdata; 237 sensors = dts->sensors; 238 status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, 239 SOC_DTS_OFFSET_TEMP, &out); 240 if (status) 241 return status; 242 243 out = (out & dts->temp_mask) >> dts->temp_shift; 244 out -= SOC_DTS_TJMAX_ENCODING; 245 *temp = sensors->tj_max - out * 1000; 246 247 return 0; 248 } 249 250 static struct thermal_zone_device_ops tzone_ops = { 251 .get_temp = sys_get_curr_temp, 252 .get_trip_temp = sys_get_trip_temp, 253 .get_trip_type = sys_get_trip_type, 254 .set_trip_temp = sys_set_trip_temp, 255 }; 256 257 static int soc_dts_enable(int id) 258 { 259 u32 out; 260 int ret; 261 262 ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, 263 SOC_DTS_OFFSET_ENABLE, &out); 264 if (ret) 265 return ret; 266 267 if (!(out & BIT(id))) { 268 out |= BIT(id); 269 ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, 270 SOC_DTS_OFFSET_ENABLE, out); 271 if (ret) 272 return ret; 273 } 274 275 return ret; 276 } 277 278 static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts) 279 { 280 if (dts) { 281 iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, 282 SOC_DTS_OFFSET_ENABLE, dts->store_status); 283 thermal_zone_device_unregister(dts->tzone); 284 } 285 } 286 287 static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts, 288 bool notification_support, int trip_cnt, 289 int read_only_trip_cnt) 290 { 291 char name[10]; 292 int trip_count = 0; 293 int trip_mask = 0; 294 u32 store_ptps; 295 int ret; 296 int i; 297 298 /* Store status to restor on exit */ 299 ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, 300 SOC_DTS_OFFSET_ENABLE, &dts->store_status); 301 if (ret) 302 goto err_ret; 303 304 dts->id = id; 305 dts->temp_mask = 0x00FF << (id * 8); 306 dts->temp_shift = id * 8; 307 if (notification_support) { 308 trip_count = min(SOC_MAX_DTS_TRIPS, trip_cnt); 309 trip_mask = BIT(trip_count - read_only_trip_cnt) - 1; 310 } 311 312 /* Check if the writable trip we provide is not used by BIOS */ 313 ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, 314 SOC_DTS_OFFSET_PTPS, &store_ptps); 315 if (ret) 316 trip_mask = 0; 317 else { 318 for (i = 0; i < trip_count; ++i) { 319 if (trip_mask & BIT(i)) 320 if (store_ptps & (0xff << (i * 8))) 321 trip_mask &= ~BIT(i); 322 } 323 } 324 dts->trip_mask = trip_mask; 325 dts->trip_count = trip_count; 326 snprintf(name, sizeof(name), "soc_dts%d", id); 327 dts->tzone = thermal_zone_device_register(name, 328 trip_count, 329 trip_mask, 330 dts, &tzone_ops, 331 NULL, 0, 0); 332 if (IS_ERR(dts->tzone)) { 333 ret = PTR_ERR(dts->tzone); 334 goto err_ret; 335 } 336 337 ret = soc_dts_enable(id); 338 if (ret) 339 goto err_enable; 340 341 return 0; 342 err_enable: 343 thermal_zone_device_unregister(dts->tzone); 344 err_ret: 345 return ret; 346 } 347 348 int intel_soc_dts_iosf_add_read_only_critical_trip( 349 struct intel_soc_dts_sensors *sensors, int critical_offset) 350 { 351 int i, j; 352 353 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { 354 for (j = 0; j < sensors->soc_dts[i].trip_count; ++j) { 355 if (!(sensors->soc_dts[i].trip_mask & BIT(j))) { 356 return update_trip_temp(&sensors->soc_dts[i], j, 357 sensors->tj_max - critical_offset, 358 THERMAL_TRIP_CRITICAL); 359 } 360 } 361 } 362 363 return -EINVAL; 364 } 365 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_add_read_only_critical_trip); 366 367 void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors) 368 { 369 u32 sticky_out; 370 int status; 371 u32 ptmc_out; 372 unsigned long flags; 373 374 spin_lock_irqsave(&sensors->intr_notify_lock, flags); 375 376 status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, 377 SOC_DTS_OFFSET_PTMC, &ptmc_out); 378 ptmc_out |= SOC_DTS_PTMC_APIC_DEASSERT_BIT; 379 status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, 380 SOC_DTS_OFFSET_PTMC, ptmc_out); 381 382 status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, 383 SOC_DTS_OFFSET_PTTSS, &sticky_out); 384 pr_debug("status %d PTTSS %x\n", status, sticky_out); 385 if (sticky_out & SOC_DTS_TRIP_MASK) { 386 int i; 387 /* reset sticky bit */ 388 status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, 389 SOC_DTS_OFFSET_PTTSS, sticky_out); 390 spin_unlock_irqrestore(&sensors->intr_notify_lock, flags); 391 392 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { 393 pr_debug("TZD update for zone %d\n", i); 394 thermal_zone_device_update(sensors->soc_dts[i].tzone, 395 THERMAL_EVENT_UNSPECIFIED); 396 } 397 } else 398 spin_unlock_irqrestore(&sensors->intr_notify_lock, flags); 399 } 400 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_interrupt_handler); 401 402 struct intel_soc_dts_sensors *intel_soc_dts_iosf_init( 403 enum intel_soc_dts_interrupt_type intr_type, int trip_count, 404 int read_only_trip_count) 405 { 406 struct intel_soc_dts_sensors *sensors; 407 bool notification; 408 u32 tj_max; 409 int ret; 410 int i; 411 412 if (!iosf_mbi_available()) 413 return ERR_PTR(-ENODEV); 414 415 if (!trip_count || read_only_trip_count > trip_count) 416 return ERR_PTR(-EINVAL); 417 418 if (get_tj_max(&tj_max)) 419 return ERR_PTR(-EINVAL); 420 421 sensors = kzalloc(sizeof(*sensors), GFP_KERNEL); 422 if (!sensors) 423 return ERR_PTR(-ENOMEM); 424 425 spin_lock_init(&sensors->intr_notify_lock); 426 mutex_init(&sensors->dts_update_lock); 427 sensors->intr_type = intr_type; 428 sensors->tj_max = tj_max; 429 if (intr_type == INTEL_SOC_DTS_INTERRUPT_NONE) 430 notification = false; 431 else 432 notification = true; 433 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { 434 sensors->soc_dts[i].sensors = sensors; 435 ret = add_dts_thermal_zone(i, &sensors->soc_dts[i], 436 notification, trip_count, 437 read_only_trip_count); 438 if (ret) 439 goto err_free; 440 } 441 442 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { 443 ret = update_trip_temp(&sensors->soc_dts[i], 0, 0, 444 THERMAL_TRIP_PASSIVE); 445 if (ret) 446 goto err_remove_zone; 447 448 ret = update_trip_temp(&sensors->soc_dts[i], 1, 0, 449 THERMAL_TRIP_PASSIVE); 450 if (ret) 451 goto err_remove_zone; 452 } 453 454 return sensors; 455 err_remove_zone: 456 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) 457 remove_dts_thermal_zone(&sensors->soc_dts[i]); 458 459 err_free: 460 kfree(sensors); 461 return ERR_PTR(ret); 462 } 463 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_init); 464 465 void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors) 466 { 467 int i; 468 469 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { 470 update_trip_temp(&sensors->soc_dts[i], 0, 0, 0); 471 update_trip_temp(&sensors->soc_dts[i], 1, 0, 0); 472 remove_dts_thermal_zone(&sensors->soc_dts[i]); 473 } 474 kfree(sensors); 475 } 476 EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit); 477 478 MODULE_LICENSE("GPL v2"); 479