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