1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * processor_thermal_device.c 4 * Copyright (c) 2014, Intel Corporation. 5 */ 6 #include <linux/acpi.h> 7 #include <linux/intel_tcc.h> 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/pci.h> 11 #include <linux/sysfs.h> 12 #include <linux/thermal.h> 13 #include <asm/msr.h> 14 #include "int340x_thermal_zone.h" 15 #include "processor_thermal_device.h" 16 #include "../intel_soc_dts_iosf.h" 17 18 #define DRV_NAME "proc_thermal" 19 20 #define POWER_LIMIT_SHOW(index, suffix) \ 21 static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \ 22 struct device_attribute *attr, \ 23 char *buf) \ 24 { \ 25 struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); \ 26 \ 27 return sysfs_emit(buf, "%lu\n",\ 28 (unsigned long)proc_dev->power_limits[index].suffix * 1000); \ 29 } 30 31 static ssize_t power_floor_status_show(struct device *dev, 32 struct device_attribute *attr, 33 char *buf) 34 { 35 struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); 36 int ret; 37 38 ret = proc_thermal_read_power_floor_status(proc_dev); 39 40 return sysfs_emit(buf, "%d\n", ret); 41 } 42 43 static ssize_t power_floor_enable_show(struct device *dev, 44 struct device_attribute *attr, 45 char *buf) 46 { 47 struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); 48 bool ret; 49 50 ret = proc_thermal_power_floor_get_state(proc_dev); 51 52 return sysfs_emit(buf, "%d\n", ret); 53 } 54 55 static ssize_t power_floor_enable_store(struct device *dev, 56 struct device_attribute *attr, 57 const char *buf, size_t count) 58 { 59 struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); 60 u8 state; 61 int ret; 62 63 if (kstrtou8(buf, 0, &state)) 64 return -EINVAL; 65 66 ret = proc_thermal_power_floor_set_state(proc_dev, !!state); 67 if (ret) 68 return ret; 69 70 return count; 71 } 72 73 POWER_LIMIT_SHOW(0, min_uw) 74 POWER_LIMIT_SHOW(0, max_uw) 75 POWER_LIMIT_SHOW(0, step_uw) 76 POWER_LIMIT_SHOW(0, tmin_us) 77 POWER_LIMIT_SHOW(0, tmax_us) 78 79 POWER_LIMIT_SHOW(1, min_uw) 80 POWER_LIMIT_SHOW(1, max_uw) 81 POWER_LIMIT_SHOW(1, step_uw) 82 POWER_LIMIT_SHOW(1, tmin_us) 83 POWER_LIMIT_SHOW(1, tmax_us) 84 85 static DEVICE_ATTR_RO(power_limit_0_min_uw); 86 static DEVICE_ATTR_RO(power_limit_0_max_uw); 87 static DEVICE_ATTR_RO(power_limit_0_step_uw); 88 static DEVICE_ATTR_RO(power_limit_0_tmin_us); 89 static DEVICE_ATTR_RO(power_limit_0_tmax_us); 90 91 static DEVICE_ATTR_RO(power_limit_1_min_uw); 92 static DEVICE_ATTR_RO(power_limit_1_max_uw); 93 static DEVICE_ATTR_RO(power_limit_1_step_uw); 94 static DEVICE_ATTR_RO(power_limit_1_tmin_us); 95 static DEVICE_ATTR_RO(power_limit_1_tmax_us); 96 97 static DEVICE_ATTR_RO(power_floor_status); 98 static DEVICE_ATTR_RW(power_floor_enable); 99 100 static struct attribute *power_limit_attrs[] = { 101 &dev_attr_power_limit_0_min_uw.attr, 102 &dev_attr_power_limit_1_min_uw.attr, 103 &dev_attr_power_limit_0_max_uw.attr, 104 &dev_attr_power_limit_1_max_uw.attr, 105 &dev_attr_power_limit_0_step_uw.attr, 106 &dev_attr_power_limit_1_step_uw.attr, 107 &dev_attr_power_limit_0_tmin_us.attr, 108 &dev_attr_power_limit_1_tmin_us.attr, 109 &dev_attr_power_limit_0_tmax_us.attr, 110 &dev_attr_power_limit_1_tmax_us.attr, 111 &dev_attr_power_floor_status.attr, 112 &dev_attr_power_floor_enable.attr, 113 NULL 114 }; 115 116 static umode_t power_limit_attr_visible(struct kobject *kobj, struct attribute *attr, int unused) 117 { 118 struct device *dev = kobj_to_dev(kobj); 119 struct proc_thermal_device *proc_dev; 120 121 if (attr != &dev_attr_power_floor_status.attr && attr != &dev_attr_power_floor_enable.attr) 122 return attr->mode; 123 124 proc_dev = dev_get_drvdata(dev); 125 if (!proc_dev || !(proc_dev->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR)) 126 return 0; 127 128 return attr->mode; 129 } 130 131 static const struct attribute_group power_limit_attribute_group = { 132 .attrs = power_limit_attrs, 133 .name = "power_limits", 134 .is_visible = power_limit_attr_visible, 135 }; 136 137 static ssize_t tcc_offset_degree_celsius_show(struct device *dev, 138 struct device_attribute *attr, 139 char *buf) 140 { 141 int offset; 142 143 offset = intel_tcc_get_offset(-1); 144 if (offset < 0) 145 return offset; 146 147 return sysfs_emit(buf, "%d\n", offset); 148 } 149 150 static ssize_t tcc_offset_degree_celsius_store(struct device *dev, 151 struct device_attribute *attr, const char *buf, 152 size_t count) 153 { 154 unsigned int tcc; 155 u64 val; 156 int err; 157 158 err = rdmsrq_safe(MSR_PLATFORM_INFO, &val); 159 if (err) 160 return err; 161 162 if (!(val & BIT(30))) 163 return -EACCES; 164 165 if (kstrtouint(buf, 0, &tcc)) 166 return -EINVAL; 167 168 err = intel_tcc_set_offset(-1, tcc); 169 if (err) 170 return err; 171 172 return count; 173 } 174 175 static DEVICE_ATTR_RW(tcc_offset_degree_celsius); 176 177 static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone, 178 int *temp) 179 { 180 int cpu; 181 int curr_temp, ret; 182 bool temp_valid = false; 183 184 for_each_online_cpu(cpu) { 185 ret = intel_tcc_get_temp(cpu, &curr_temp, false); 186 if (ret < 0) 187 return ret; 188 if (!temp_valid || curr_temp > *temp) { 189 *temp = curr_temp; 190 temp_valid = true; 191 } 192 } 193 194 if (!temp_valid) 195 return -ENODATA; 196 197 *temp *= 1000; 198 199 return 0; 200 } 201 202 static int proc_thermal_read_ppcc(struct proc_thermal_device *proc_priv) 203 { 204 int i; 205 acpi_status status; 206 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; 207 union acpi_object *elements, *ppcc; 208 union acpi_object *p; 209 int ret = 0; 210 211 status = acpi_evaluate_object(proc_priv->adev->handle, "PPCC", 212 NULL, &buf); 213 if (ACPI_FAILURE(status)) 214 return -ENODEV; 215 216 p = buf.pointer; 217 if (!p || (p->type != ACPI_TYPE_PACKAGE)) { 218 dev_err(proc_priv->dev, "Invalid PPCC data\n"); 219 ret = -EFAULT; 220 goto free_buffer; 221 } 222 223 if (!p->package.count) { 224 dev_err(proc_priv->dev, "Invalid PPCC package size\n"); 225 ret = -EFAULT; 226 goto free_buffer; 227 } 228 229 for (i = 0; i < min((int)p->package.count - 1, 2); ++i) { 230 elements = &(p->package.elements[i+1]); 231 if (elements->type != ACPI_TYPE_PACKAGE || 232 elements->package.count != 6) { 233 ret = -EFAULT; 234 goto free_buffer; 235 } 236 ppcc = elements->package.elements; 237 proc_priv->power_limits[i].index = ppcc[0].integer.value; 238 proc_priv->power_limits[i].min_uw = ppcc[1].integer.value; 239 proc_priv->power_limits[i].max_uw = ppcc[2].integer.value; 240 proc_priv->power_limits[i].tmin_us = ppcc[3].integer.value; 241 proc_priv->power_limits[i].tmax_us = ppcc[4].integer.value; 242 proc_priv->power_limits[i].step_uw = ppcc[5].integer.value; 243 } 244 245 free_buffer: 246 kfree(buf.pointer); 247 248 return ret; 249 } 250 251 #define PROC_POWER_CAPABILITY_CHANGED 0x83 252 static void proc_thermal_notify(acpi_handle handle, u32 event, void *data) 253 { 254 struct proc_thermal_device *proc_priv = data; 255 256 if (!proc_priv) 257 return; 258 259 switch (event) { 260 case PROC_POWER_CAPABILITY_CHANGED: 261 proc_thermal_read_ppcc(proc_priv); 262 int340x_thermal_zone_device_update(proc_priv->int340x_zone, 263 THERMAL_DEVICE_POWER_CAPABILITY_CHANGED); 264 break; 265 default: 266 dev_dbg(proc_priv->dev, "Unsupported event [0x%x]\n", event); 267 break; 268 } 269 } 270 271 int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv) 272 { 273 struct acpi_device *adev; 274 acpi_status status; 275 unsigned long long tmp; 276 int (*get_temp) (struct thermal_zone_device *, int *) = NULL; 277 int ret; 278 279 adev = ACPI_COMPANION(dev); 280 if (!adev) 281 return -ENODEV; 282 283 proc_priv->dev = dev; 284 proc_priv->adev = adev; 285 286 ret = proc_thermal_read_ppcc(proc_priv); 287 if (ret) 288 return ret; 289 290 status = acpi_evaluate_integer(adev->handle, "_TMP", NULL, &tmp); 291 if (ACPI_FAILURE(status)) { 292 /* there is no _TMP method, add local method */ 293 if (intel_tcc_get_tjmax(-1) > 0) 294 get_temp = proc_thermal_get_zone_temp; 295 } 296 297 proc_priv->int340x_zone = int340x_thermal_zone_add(adev, get_temp); 298 if (IS_ERR(proc_priv->int340x_zone)) 299 return PTR_ERR(proc_priv->int340x_zone); 300 301 ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, 302 proc_thermal_notify, 303 (void *)proc_priv); 304 if (ret) 305 goto remove_zone; 306 307 ret = sysfs_create_file(&dev->kobj, &dev_attr_tcc_offset_degree_celsius.attr); 308 if (ret) 309 goto remove_notify; 310 311 ret = sysfs_create_group(&dev->kobj, &power_limit_attribute_group); 312 if (ret) { 313 sysfs_remove_file(&dev->kobj, &dev_attr_tcc_offset_degree_celsius.attr); 314 goto remove_notify; 315 } 316 317 return 0; 318 319 remove_notify: 320 acpi_remove_notify_handler(adev->handle, 321 ACPI_DEVICE_NOTIFY, proc_thermal_notify); 322 remove_zone: 323 int340x_thermal_zone_remove(proc_priv->int340x_zone); 324 325 return ret; 326 } 327 EXPORT_SYMBOL_GPL(proc_thermal_add); 328 329 void proc_thermal_remove(struct proc_thermal_device *proc_priv) 330 { 331 acpi_remove_notify_handler(proc_priv->adev->handle, 332 ACPI_DEVICE_NOTIFY, proc_thermal_notify); 333 int340x_thermal_zone_remove(proc_priv->int340x_zone); 334 sysfs_remove_file(&proc_priv->dev->kobj, &dev_attr_tcc_offset_degree_celsius.attr); 335 sysfs_remove_group(&proc_priv->dev->kobj, 336 &power_limit_attribute_group); 337 } 338 EXPORT_SYMBOL_GPL(proc_thermal_remove); 339 340 static int tcc_offset_save = -1; 341 342 int proc_thermal_suspend(struct device *dev) 343 { 344 struct proc_thermal_device *proc_dev; 345 346 tcc_offset_save = intel_tcc_get_offset(-1); 347 if (tcc_offset_save < 0) 348 dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save); 349 350 proc_dev = dev_get_drvdata(dev); 351 352 if (proc_dev->mmio_feature_mask & PROC_THERMAL_FEATURE_SOC_POWER_SLIDER) 353 proc_thermal_soc_power_slider_suspend(proc_dev); 354 355 return 0; 356 } 357 EXPORT_SYMBOL_GPL(proc_thermal_suspend); 358 359 int proc_thermal_resume(struct device *dev) 360 { 361 struct proc_thermal_device *proc_dev; 362 363 proc_dev = dev_get_drvdata(dev); 364 proc_thermal_read_ppcc(proc_dev); 365 366 /* Do not update if saving failed */ 367 if (tcc_offset_save >= 0) 368 intel_tcc_set_offset(-1, tcc_offset_save); 369 370 if (proc_dev->mmio_feature_mask & PROC_THERMAL_FEATURE_SOC_POWER_SLIDER) 371 proc_thermal_soc_power_slider_resume(proc_dev); 372 373 return 0; 374 } 375 EXPORT_SYMBOL_GPL(proc_thermal_resume); 376 377 #define MCHBAR 0 378 379 static int proc_thermal_set_mmio_base(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 380 { 381 int ret; 382 383 ret = pcim_iomap_regions(pdev, 1 << MCHBAR, DRV_NAME); 384 if (ret) { 385 dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); 386 return -ENOMEM; 387 } 388 389 proc_priv->mmio_base = pcim_iomap_table(pdev)[MCHBAR]; 390 391 return 0; 392 } 393 394 int proc_thermal_mmio_add(struct pci_dev *pdev, 395 struct proc_thermal_device *proc_priv, 396 kernel_ulong_t feature_mask) 397 { 398 int ret; 399 400 proc_priv->mmio_feature_mask = feature_mask; 401 402 if (feature_mask) { 403 ret = proc_thermal_set_mmio_base(pdev, proc_priv); 404 if (ret) 405 return ret; 406 } 407 408 if (feature_mask & PROC_THERMAL_FEATURE_RAPL) { 409 ret = proc_thermal_rapl_add(pdev, proc_priv); 410 if (ret) { 411 dev_err(&pdev->dev, "failed to add RAPL MMIO interface\n"); 412 return ret; 413 } 414 } 415 416 if (feature_mask & PROC_THERMAL_FEATURE_PTC) { 417 ret = proc_thermal_ptc_add(pdev, proc_priv); 418 if (ret) { 419 dev_err(&pdev->dev, "failed to add PTC MMIO interface\n"); 420 goto err_rem_rapl; 421 } 422 } 423 424 if (feature_mask & PROC_THERMAL_FEATURE_FIVR || 425 feature_mask & PROC_THERMAL_FEATURE_DVFS || 426 feature_mask & PROC_THERMAL_FEATURE_DLVR) { 427 ret = proc_thermal_rfim_add(pdev, proc_priv); 428 if (ret) { 429 dev_err(&pdev->dev, "failed to add RFIM interface\n"); 430 goto err_rem_ptc; 431 } 432 } 433 434 if (feature_mask & PROC_THERMAL_FEATURE_WT_REQ) { 435 ret = proc_thermal_wt_req_add(pdev, proc_priv); 436 if (ret) { 437 dev_err(&pdev->dev, "failed to add MBOX interface\n"); 438 goto err_rem_rfim; 439 } 440 } else if (feature_mask & PROC_THERMAL_FEATURE_WT_HINT) { 441 ret = proc_thermal_wt_hint_add(pdev, proc_priv); 442 if (ret) { 443 dev_err(&pdev->dev, "failed to add WT Hint\n"); 444 goto err_rem_rfim; 445 } 446 } 447 448 if (feature_mask & PROC_THERMAL_FEATURE_SOC_POWER_SLIDER) { 449 ret = proc_thermal_soc_power_slider_add(pdev, proc_priv); 450 if (ret) { 451 dev_info(&pdev->dev, "failed to add soc power efficiency slider\n"); 452 goto err_rem_wlt; 453 } 454 } 455 456 return 0; 457 458 err_rem_wlt: 459 proc_thermal_wt_hint_remove(pdev); 460 err_rem_rfim: 461 proc_thermal_rfim_remove(pdev); 462 err_rem_ptc: 463 proc_thermal_ptc_remove(pdev); 464 err_rem_rapl: 465 proc_thermal_rapl_remove(); 466 467 return ret; 468 } 469 EXPORT_SYMBOL_GPL(proc_thermal_mmio_add); 470 471 void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 472 { 473 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_RAPL) 474 proc_thermal_rapl_remove(); 475 476 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_PTC) 477 proc_thermal_ptc_remove(pdev); 478 479 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR || 480 proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS || 481 proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR) 482 proc_thermal_rfim_remove(pdev); 483 484 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) 485 proc_thermal_power_floor_set_state(proc_priv, false); 486 487 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_REQ) 488 proc_thermal_wt_req_remove(pdev); 489 else if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) 490 proc_thermal_wt_hint_remove(pdev); 491 } 492 EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove); 493 494 MODULE_IMPORT_NS("INTEL_TCC"); 495 MODULE_IMPORT_NS("INT340X_THERMAL"); 496 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 497 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); 498 MODULE_LICENSE("GPL v2"); 499