1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Processor thermal device for newer processors 4 * Copyright (c) 2020, Intel Corporation. 5 */ 6 7 #include <linux/acpi.h> 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/pci.h> 11 #include <linux/thermal.h> 12 13 #include "int340x_thermal_zone.h" 14 #include "processor_thermal_device.h" 15 16 #define DRV_NAME "proc_thermal_pci" 17 18 static bool use_msi; 19 module_param(use_msi, bool, 0644); 20 MODULE_PARM_DESC(use_msi, 21 "Use PCI MSI based interrupts for processor thermal device."); 22 23 struct proc_thermal_pci { 24 struct pci_dev *pdev; 25 struct proc_thermal_device *proc_priv; 26 struct thermal_zone_device *tzone; 27 struct delayed_work work; 28 int stored_thres; 29 int no_legacy; 30 }; 31 32 enum proc_thermal_mmio_type { 33 PROC_THERMAL_MMIO_TJMAX, 34 PROC_THERMAL_MMIO_PP0_TEMP, 35 PROC_THERMAL_MMIO_PP1_TEMP, 36 PROC_THERMAL_MMIO_PKG_TEMP, 37 PROC_THERMAL_MMIO_THRES_0, 38 PROC_THERMAL_MMIO_THRES_1, 39 PROC_THERMAL_MMIO_INT_ENABLE_0, 40 PROC_THERMAL_MMIO_INT_ENABLE_1, 41 PROC_THERMAL_MMIO_INT_STATUS_0, 42 PROC_THERMAL_MMIO_INT_STATUS_1, 43 PROC_THERMAL_MMIO_MAX 44 }; 45 46 struct proc_thermal_mmio_info { 47 enum proc_thermal_mmio_type mmio_type; 48 u64 mmio_addr; 49 u64 shift; 50 u64 mask; 51 }; 52 53 static struct proc_thermal_mmio_info proc_thermal_mmio_info[] = { 54 { PROC_THERMAL_MMIO_TJMAX, 0x599c, 16, 0xff }, 55 { PROC_THERMAL_MMIO_PP0_TEMP, 0x597c, 0, 0xff }, 56 { PROC_THERMAL_MMIO_PP1_TEMP, 0x5980, 0, 0xff }, 57 { PROC_THERMAL_MMIO_PKG_TEMP, 0x5978, 0, 0xff }, 58 { PROC_THERMAL_MMIO_THRES_0, 0x5820, 8, 0x7F }, 59 { PROC_THERMAL_MMIO_THRES_1, 0x5820, 16, 0x7F }, 60 { PROC_THERMAL_MMIO_INT_ENABLE_0, 0x5820, 15, 0x01 }, 61 { PROC_THERMAL_MMIO_INT_ENABLE_1, 0x5820, 23, 0x01 }, 62 { PROC_THERMAL_MMIO_INT_STATUS_0, 0x7200, 6, 0x01 }, 63 { PROC_THERMAL_MMIO_INT_STATUS_1, 0x7200, 8, 0x01 }, 64 }; 65 66 /* List of supported MSI IDs (sources) */ 67 enum proc_thermal_msi_ids { 68 PKG_THERMAL, 69 DDR_THERMAL, 70 THERM_POWER_FLOOR, 71 WORKLOAD_CHANGE, 72 MSI_THERMAL_MAX 73 }; 74 75 /* Stores IRQ associated with a MSI ID */ 76 static int proc_thermal_msi_map[MSI_THERMAL_MAX]; 77 78 #define B0D4_THERMAL_NOTIFY_DELAY 1000 79 static int notify_delay_ms = B0D4_THERMAL_NOTIFY_DELAY; 80 81 static void proc_thermal_mmio_read(struct proc_thermal_pci *pci_info, 82 enum proc_thermal_mmio_type type, 83 u32 *value) 84 { 85 *value = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base + 86 proc_thermal_mmio_info[type].mmio_addr)); 87 *value >>= proc_thermal_mmio_info[type].shift; 88 *value &= proc_thermal_mmio_info[type].mask; 89 } 90 91 static void proc_thermal_mmio_write(struct proc_thermal_pci *pci_info, 92 enum proc_thermal_mmio_type type, 93 u32 value) 94 { 95 u32 current_val; 96 u32 mask; 97 98 current_val = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base + 99 proc_thermal_mmio_info[type].mmio_addr)); 100 mask = proc_thermal_mmio_info[type].mask << proc_thermal_mmio_info[type].shift; 101 current_val &= ~mask; 102 103 value &= proc_thermal_mmio_info[type].mask; 104 value <<= proc_thermal_mmio_info[type].shift; 105 106 current_val |= value; 107 iowrite32(current_val, ((u8 __iomem *)pci_info->proc_priv->mmio_base + 108 proc_thermal_mmio_info[type].mmio_addr)); 109 } 110 111 /* 112 * To avoid sending two many messages to user space, we have 1 second delay. 113 * On interrupt we are disabling interrupt and enabling after 1 second. 114 * This workload function is delayed by 1 second. 115 */ 116 static void proc_thermal_threshold_work_fn(struct work_struct *work) 117 { 118 struct delayed_work *delayed_work = to_delayed_work(work); 119 struct proc_thermal_pci *pci_info = container_of(delayed_work, 120 struct proc_thermal_pci, work); 121 struct thermal_zone_device *tzone = pci_info->tzone; 122 123 if (tzone) 124 thermal_zone_device_update(tzone, THERMAL_TRIP_VIOLATED); 125 126 /* Enable interrupt flag */ 127 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); 128 } 129 130 static void pkg_thermal_schedule_work(struct delayed_work *work) 131 { 132 unsigned long ms = msecs_to_jiffies(notify_delay_ms); 133 134 schedule_delayed_work(work, ms); 135 } 136 137 static void proc_thermal_clear_soc_int_status(struct proc_thermal_device *proc_priv) 138 { 139 u64 status; 140 141 if (!(proc_priv->mmio_feature_mask & 142 (PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR))) 143 return; 144 145 status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 146 writeq(status & ~SOC_WT_RES_INT_STATUS_MASK, 147 proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 148 } 149 150 static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid) 151 { 152 struct proc_thermal_pci *pci_info = devid; 153 154 proc_thermal_wt_intr_callback(pci_info->pdev, pci_info->proc_priv); 155 proc_thermal_power_floor_intr_callback(pci_info->pdev, pci_info->proc_priv); 156 proc_thermal_clear_soc_int_status(pci_info->proc_priv); 157 158 return IRQ_HANDLED; 159 } 160 161 static int proc_thermal_match_msi_irq(int irq) 162 { 163 int i; 164 165 if (!use_msi) 166 goto msi_fail; 167 168 for (i = 0; i < MSI_THERMAL_MAX; i++) { 169 if (proc_thermal_msi_map[i] == irq) 170 return i; 171 } 172 173 msi_fail: 174 return -EOPNOTSUPP; 175 } 176 177 static irqreturn_t proc_thermal_irq_handler(int irq, void *devid) 178 { 179 struct proc_thermal_pci *pci_info = devid; 180 struct proc_thermal_device *proc_priv; 181 int ret = IRQ_NONE, msi_id; 182 u32 status; 183 184 proc_priv = pci_info->proc_priv; 185 186 msi_id = proc_thermal_match_msi_irq(irq); 187 188 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) { 189 if (msi_id == WORKLOAD_CHANGE || proc_thermal_check_wt_intr(pci_info->proc_priv)) 190 ret = IRQ_WAKE_THREAD; 191 } 192 193 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) { 194 if (msi_id == THERM_POWER_FLOOR || 195 proc_thermal_check_power_floor_intr(pci_info->proc_priv)) 196 ret = IRQ_WAKE_THREAD; 197 } 198 199 /* 200 * Since now there are two sources of interrupts: one from thermal threshold 201 * and another from workload hint, add a check if there was really a threshold 202 * interrupt before scheduling work function for thermal threshold. 203 */ 204 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); 205 if (msi_id == PKG_THERMAL || status) { 206 /* Disable enable interrupt flag */ 207 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); 208 pkg_thermal_schedule_work(&pci_info->work); 209 ret = IRQ_HANDLED; 210 } 211 212 pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); 213 214 return ret; 215 } 216 217 static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) 218 { 219 struct proc_thermal_pci *pci_info = thermal_zone_device_priv(tzd); 220 u32 _temp; 221 222 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_PKG_TEMP, &_temp); 223 *temp = (unsigned long)_temp * 1000; 224 225 return 0; 226 } 227 228 static int sys_set_trip_temp(struct thermal_zone_device *tzd, 229 const struct thermal_trip *trip, int temp) 230 { 231 struct proc_thermal_pci *pci_info = thermal_zone_device_priv(tzd); 232 int tjmax, _temp; 233 234 if (temp <= 0) { 235 cancel_delayed_work_sync(&pci_info->work); 236 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); 237 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0); 238 pci_info->stored_thres = 0; 239 return 0; 240 } 241 242 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax); 243 _temp = tjmax - (temp / 1000); 244 if (_temp < 0) 245 return -EINVAL; 246 247 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, _temp); 248 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); 249 250 pci_info->stored_thres = temp; 251 252 return 0; 253 } 254 255 static int get_trip_temp(struct proc_thermal_pci *pci_info) 256 { 257 int temp, tjmax; 258 259 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &temp); 260 if (!temp) 261 return THERMAL_TEMP_INVALID; 262 263 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax); 264 temp = (tjmax - temp) * 1000; 265 266 return temp; 267 } 268 269 static const struct thermal_zone_device_ops tzone_ops = { 270 .get_temp = sys_get_curr_temp, 271 .set_trip_temp = sys_set_trip_temp, 272 }; 273 274 static struct thermal_zone_params tzone_params = { 275 .no_hwmon = true, 276 }; 277 278 static bool msi_irq; 279 280 static void proc_thermal_free_msi(struct pci_dev *pdev, struct proc_thermal_pci *pci_info) 281 { 282 int i; 283 284 for (i = 0; i < MSI_THERMAL_MAX; i++) { 285 if (proc_thermal_msi_map[i]) 286 devm_free_irq(&pdev->dev, proc_thermal_msi_map[i], pci_info); 287 } 288 289 pci_free_irq_vectors(pdev); 290 } 291 292 static int proc_thermal_setup_msi(struct pci_dev *pdev, struct proc_thermal_pci *pci_info) 293 { 294 int ret, i, irq, count; 295 296 count = pci_alloc_irq_vectors(pdev, 1, MSI_THERMAL_MAX, PCI_IRQ_MSI | PCI_IRQ_MSIX); 297 if (count < 0) { 298 dev_err(&pdev->dev, "Failed to allocate vectors!\n"); 299 return count; 300 } 301 302 dev_info(&pdev->dev, "msi enabled:%d msix enabled:%d\n", pdev->msi_enabled, 303 pdev->msix_enabled); 304 305 for (i = 0; i < count; i++) { 306 irq = pci_irq_vector(pdev, i); 307 308 ret = devm_request_threaded_irq(&pdev->dev, irq, proc_thermal_irq_handler, 309 proc_thermal_irq_thread_handler, 310 0, KBUILD_MODNAME, pci_info); 311 if (ret) { 312 dev_err(&pdev->dev, "Request IRQ %d failed\n", irq); 313 goto err_free_msi_vectors; 314 } 315 316 proc_thermal_msi_map[i] = irq; 317 } 318 319 msi_irq = true; 320 321 return 0; 322 323 err_free_msi_vectors: 324 proc_thermal_free_msi(pdev, pci_info); 325 326 return ret; 327 } 328 329 static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 330 { 331 struct proc_thermal_device *proc_priv; 332 struct proc_thermal_pci *pci_info; 333 struct thermal_trip psv_trip = { 334 .type = THERMAL_TRIP_PASSIVE, 335 .flags = THERMAL_TRIP_FLAG_RW_TEMP, 336 }; 337 int irq_flag = 0, irq, ret; 338 339 proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL); 340 if (!proc_priv) 341 return -ENOMEM; 342 343 pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL); 344 if (!pci_info) 345 return -ENOMEM; 346 347 pci_info->pdev = pdev; 348 ret = pcim_enable_device(pdev); 349 if (ret < 0) { 350 dev_err(&pdev->dev, "error: could not enable device\n"); 351 return ret; 352 } 353 354 pci_set_master(pdev); 355 356 INIT_DELAYED_WORK(&pci_info->work, proc_thermal_threshold_work_fn); 357 358 proc_priv->priv_data = pci_info; 359 pci_info->proc_priv = proc_priv; 360 pci_set_drvdata(pdev, proc_priv); 361 362 ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data); 363 if (ret) 364 return ret; 365 366 ret = proc_thermal_add(&pdev->dev, proc_priv); 367 if (ret) { 368 dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n"); 369 pci_info->no_legacy = 1; 370 } 371 372 psv_trip.temperature = get_trip_temp(pci_info); 373 374 pci_info->tzone = thermal_zone_device_register_with_trips("TCPU_PCI", &psv_trip, 375 1, pci_info, 376 &tzone_ops, 377 &tzone_params, 0, 0); 378 if (IS_ERR(pci_info->tzone)) { 379 ret = PTR_ERR(pci_info->tzone); 380 goto err_del_legacy; 381 } 382 383 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MSI_SUPPORT) 384 use_msi = true; 385 386 if (use_msi) { 387 ret = proc_thermal_setup_msi(pdev, pci_info); 388 if (ret) 389 goto err_ret_tzone; 390 } else { 391 irq_flag = IRQF_SHARED; 392 irq = pdev->irq; 393 394 ret = devm_request_threaded_irq(&pdev->dev, irq, proc_thermal_irq_handler, 395 proc_thermal_irq_thread_handler, irq_flag, 396 KBUILD_MODNAME, pci_info); 397 if (ret) { 398 dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq); 399 goto err_ret_tzone; 400 } 401 } 402 403 ret = thermal_zone_device_enable(pci_info->tzone); 404 if (ret) 405 goto err_free_vectors; 406 407 return 0; 408 409 err_free_vectors: 410 if (msi_irq) 411 proc_thermal_free_msi(pdev, pci_info); 412 err_ret_tzone: 413 thermal_zone_device_unregister(pci_info->tzone); 414 err_del_legacy: 415 if (!pci_info->no_legacy) 416 proc_thermal_remove(proc_priv); 417 proc_thermal_mmio_remove(pdev, proc_priv); 418 419 return ret; 420 } 421 422 static void proc_thermal_pci_remove(struct pci_dev *pdev) 423 { 424 struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); 425 struct proc_thermal_pci *pci_info = proc_priv->priv_data; 426 427 cancel_delayed_work_sync(&pci_info->work); 428 429 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0); 430 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); 431 432 if (msi_irq) 433 proc_thermal_free_msi(pdev, pci_info); 434 435 thermal_zone_device_unregister(pci_info->tzone); 436 proc_thermal_mmio_remove(pdev, pci_info->proc_priv); 437 if (!pci_info->no_legacy) 438 proc_thermal_remove(proc_priv); 439 } 440 441 #ifdef CONFIG_PM_SLEEP 442 static int proc_thermal_pci_suspend(struct device *dev) 443 { 444 struct pci_dev *pdev = to_pci_dev(dev); 445 struct proc_thermal_device *proc_priv; 446 struct proc_thermal_pci *pci_info; 447 448 proc_priv = pci_get_drvdata(pdev); 449 pci_info = proc_priv->priv_data; 450 451 if (!pci_info->no_legacy) 452 return proc_thermal_suspend(dev); 453 454 return 0; 455 } 456 static int proc_thermal_pci_resume(struct device *dev) 457 { 458 struct pci_dev *pdev = to_pci_dev(dev); 459 struct proc_thermal_device *proc_priv; 460 struct proc_thermal_pci *pci_info; 461 462 proc_priv = pci_get_drvdata(pdev); 463 pci_info = proc_priv->priv_data; 464 465 if (pci_info->stored_thres) { 466 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 467 pci_info->stored_thres / 1000); 468 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); 469 } 470 471 if (!pci_info->no_legacy) 472 return proc_thermal_resume(dev); 473 474 return 0; 475 } 476 #else 477 #define proc_thermal_pci_suspend NULL 478 #define proc_thermal_pci_resume NULL 479 #endif 480 481 static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend, 482 proc_thermal_pci_resume); 483 484 static const struct pci_device_id proc_thermal_pci_ids[] = { 485 { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | 486 PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, 487 { PCI_DEVICE_DATA(INTEL, LNLM_THERMAL, PROC_THERMAL_FEATURE_MSI_SUPPORT | 488 PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS | 489 PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) }, 490 { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | 491 PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | 492 PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) }, 493 { PCI_DEVICE_DATA(INTEL, ARL_S_THERMAL, PROC_THERMAL_FEATURE_RAPL | 494 PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT) }, 495 { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | 496 PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, 497 { PCI_DEVICE_DATA(INTEL, PTL_THERMAL, PROC_THERMAL_FEATURE_RAPL | 498 PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS | 499 PROC_THERMAL_FEATURE_MSI_SUPPORT | PROC_THERMAL_FEATURE_WT_HINT | 500 PROC_THERMAL_FEATURE_POWER_FLOOR) }, 501 { }, 502 }; 503 504 MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids); 505 506 static struct pci_driver proc_thermal_pci_driver = { 507 .name = DRV_NAME, 508 .probe = proc_thermal_pci_probe, 509 .remove = proc_thermal_pci_remove, 510 .id_table = proc_thermal_pci_ids, 511 .driver.pm = &proc_thermal_pci_pm, 512 }; 513 514 module_pci_driver(proc_thermal_pci_driver); 515 516 MODULE_IMPORT_NS("INT340X_THERMAL"); 517 518 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 519 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); 520 MODULE_LICENSE("GPL v2"); 521