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