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 18static bool use_msi; 19module_param(use_msi, bool, 0644); 20MODULE_PARM_DESC(use_msi, 21 "Use PCI MSI based interrupts for processor thermal device."); 22 23struct 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 32enum 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 46struct proc_thermal_mmio_info { 47 enum proc_thermal_mmio_type mmio_type; 48 u64 mmio_addr; 49 u64 shift; 50 u64 mask; 51}; 52 53static 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#define B0D4_THERMAL_NOTIFY_DELAY 1000 67static int notify_delay_ms = B0D4_THERMAL_NOTIFY_DELAY; 68 69static void proc_thermal_mmio_read(struct proc_thermal_pci *pci_info, 70 enum proc_thermal_mmio_type type, 71 u32 *value) 72{ 73 *value = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base + 74 proc_thermal_mmio_info[type].mmio_addr)); 75 *value >>= proc_thermal_mmio_info[type].shift; 76 *value &= proc_thermal_mmio_info[type].mask; 77} 78 79static void proc_thermal_mmio_write(struct proc_thermal_pci *pci_info, 80 enum proc_thermal_mmio_type type, 81 u32 value) 82{ 83 u32 current_val; 84 u32 mask; 85 86 current_val = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base + 87 proc_thermal_mmio_info[type].mmio_addr)); 88 mask = proc_thermal_mmio_info[type].mask << proc_thermal_mmio_info[type].shift; 89 current_val &= ~mask; 90 91 value &= proc_thermal_mmio_info[type].mask; 92 value <<= proc_thermal_mmio_info[type].shift; 93 94 current_val |= value; 95 iowrite32(current_val, ((u8 __iomem *)pci_info->proc_priv->mmio_base + 96 proc_thermal_mmio_info[type].mmio_addr)); 97} 98 99/* 100 * To avoid sending two many messages to user space, we have 1 second delay. 101 * On interrupt we are disabling interrupt and enabling after 1 second. 102 * This workload function is delayed by 1 second. 103 */ 104static void proc_thermal_threshold_work_fn(struct work_struct *work) 105{ 106 struct delayed_work *delayed_work = to_delayed_work(work); 107 struct proc_thermal_pci *pci_info = container_of(delayed_work, 108 struct proc_thermal_pci, work); 109 struct thermal_zone_device *tzone = pci_info->tzone; 110 111 if (tzone) 112 thermal_zone_device_update(tzone, THERMAL_TRIP_VIOLATED); 113 114 /* Enable interrupt flag */ 115 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); 116} 117 118static void pkg_thermal_schedule_work(struct delayed_work *work) 119{ 120 unsigned long ms = msecs_to_jiffies(notify_delay_ms); 121 122 schedule_delayed_work(work, ms); 123} 124 125static void proc_thermal_clear_soc_int_status(struct proc_thermal_device *proc_priv) 126{ 127 u64 status; 128 129 if (!(proc_priv->mmio_feature_mask & 130 (PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR))) 131 return; 132 133 status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 134 writeq(status & ~SOC_WT_RES_INT_STATUS_MASK, 135 proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 136} 137 138static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid) 139{ 140 struct proc_thermal_pci *pci_info = devid; 141 142 proc_thermal_wt_intr_callback(pci_info->pdev, pci_info->proc_priv); 143 proc_thermal_power_floor_intr_callback(pci_info->pdev, pci_info->proc_priv); 144 proc_thermal_clear_soc_int_status(pci_info->proc_priv); 145 146 return IRQ_HANDLED; 147} 148 149static irqreturn_t proc_thermal_irq_handler(int irq, void *devid) 150{ 151 struct proc_thermal_pci *pci_info = devid; 152 struct proc_thermal_device *proc_priv; 153 int ret = IRQ_HANDLED; 154 u32 status; 155 156 proc_priv = pci_info->proc_priv; 157 158 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) { 159 if (proc_thermal_check_wt_intr(pci_info->proc_priv)) 160 ret = IRQ_WAKE_THREAD; 161 } 162 163 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) { 164 if (proc_thermal_check_power_floor_intr(pci_info->proc_priv)) 165 ret = IRQ_WAKE_THREAD; 166 } 167 168 /* 169 * Since now there are two sources of interrupts: one from thermal threshold 170 * and another from workload hint, add a check if there was really a threshold 171 * interrupt before scheduling work function for thermal threshold. 172 */ 173 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); 174 if (status) { 175 /* Disable enable interrupt flag */ 176 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); 177 pkg_thermal_schedule_work(&pci_info->work); 178 } 179 180 pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); 181 182 return ret; 183} 184 185static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) 186{ 187 struct proc_thermal_pci *pci_info = thermal_zone_device_priv(tzd); 188 u32 _temp; 189 190 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_PKG_TEMP, &_temp); 191 *temp = (unsigned long)_temp * 1000; 192 193 return 0; 194} 195 196static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp) 197{ 198 struct proc_thermal_pci *pci_info = thermal_zone_device_priv(tzd); 199 int tjmax, _temp; 200 201 if (temp <= 0) { 202 cancel_delayed_work_sync(&pci_info->work); 203 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); 204 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0); 205 pci_info->stored_thres = 0; 206 return 0; 207 } 208 209 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax); 210 _temp = tjmax - (temp / 1000); 211 if (_temp < 0) 212 return -EINVAL; 213 214 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, _temp); 215 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); 216 217 pci_info->stored_thres = temp; 218 219 return 0; 220} 221 222static int get_trip_temp(struct proc_thermal_pci *pci_info) 223{ 224 int temp, tjmax; 225 226 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &temp); 227 if (!temp) 228 return THERMAL_TEMP_INVALID; 229 230 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax); 231 temp = (tjmax - temp) * 1000; 232 233 return temp; 234} 235 236static const struct thermal_zone_device_ops tzone_ops = { 237 .get_temp = sys_get_curr_temp, 238 .set_trip_temp = sys_set_trip_temp, 239}; 240 241static struct thermal_zone_params tzone_params = { 242 .governor_name = "user_space", 243 .no_hwmon = true, 244}; 245 246static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 247{ 248 struct proc_thermal_device *proc_priv; 249 struct proc_thermal_pci *pci_info; 250 struct thermal_trip psv_trip = { 251 .type = THERMAL_TRIP_PASSIVE, 252 .flags = THERMAL_TRIP_FLAG_RW_TEMP, 253 }; 254 int irq_flag = 0, irq, ret; 255 bool msi_irq = false; 256 257 proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL); 258 if (!proc_priv) 259 return -ENOMEM; 260 261 pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL); 262 if (!pci_info) 263 return -ENOMEM; 264 265 pci_info->pdev = pdev; 266 ret = pcim_enable_device(pdev); 267 if (ret < 0) { 268 dev_err(&pdev->dev, "error: could not enable device\n"); 269 return ret; 270 } 271 272 pci_set_master(pdev); 273 274 INIT_DELAYED_WORK(&pci_info->work, proc_thermal_threshold_work_fn); 275 276 proc_priv->priv_data = pci_info; 277 pci_info->proc_priv = proc_priv; 278 pci_set_drvdata(pdev, proc_priv); 279 280 ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data); 281 if (ret) 282 return ret; 283 284 ret = proc_thermal_add(&pdev->dev, proc_priv); 285 if (ret) { 286 dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n"); 287 pci_info->no_legacy = 1; 288 } 289 290 psv_trip.temperature = get_trip_temp(pci_info); 291 292 pci_info->tzone = thermal_zone_device_register_with_trips("TCPU_PCI", &psv_trip, 293 1, pci_info, 294 &tzone_ops, 295 &tzone_params, 0, 0); 296 if (IS_ERR(pci_info->tzone)) { 297 ret = PTR_ERR(pci_info->tzone); 298 goto err_del_legacy; 299 } 300 301 if (use_msi && (pdev->msi_enabled || pdev->msix_enabled)) { 302 /* request and enable interrupt */ 303 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 304 if (ret < 0) { 305 dev_err(&pdev->dev, "Failed to allocate vectors!\n"); 306 goto err_ret_tzone; 307 } 308 309 irq = pci_irq_vector(pdev, 0); 310 msi_irq = true; 311 } else { 312 irq_flag = IRQF_SHARED; 313 irq = pdev->irq; 314 } 315 316 ret = devm_request_threaded_irq(&pdev->dev, irq, 317 proc_thermal_irq_handler, proc_thermal_irq_thread_handler, 318 irq_flag, KBUILD_MODNAME, pci_info); 319 if (ret) { 320 dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq); 321 goto err_free_vectors; 322 } 323 324 ret = thermal_zone_device_enable(pci_info->tzone); 325 if (ret) 326 goto err_free_vectors; 327 328 return 0; 329 330err_free_vectors: 331 if (msi_irq) 332 pci_free_irq_vectors(pdev); 333err_ret_tzone: 334 thermal_zone_device_unregister(pci_info->tzone); 335err_del_legacy: 336 if (!pci_info->no_legacy) 337 proc_thermal_remove(proc_priv); 338 proc_thermal_mmio_remove(pdev, proc_priv); 339 pci_disable_device(pdev); 340 341 return ret; 342} 343 344static void proc_thermal_pci_remove(struct pci_dev *pdev) 345{ 346 struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); 347 struct proc_thermal_pci *pci_info = proc_priv->priv_data; 348 349 cancel_delayed_work_sync(&pci_info->work); 350 351 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0); 352 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); 353 354 devm_free_irq(&pdev->dev, pdev->irq, pci_info); 355 pci_free_irq_vectors(pdev); 356 357 thermal_zone_device_unregister(pci_info->tzone); 358 proc_thermal_mmio_remove(pdev, pci_info->proc_priv); 359 if (!pci_info->no_legacy) 360 proc_thermal_remove(proc_priv); 361 pci_disable_device(pdev); 362} 363 364#ifdef CONFIG_PM_SLEEP 365static int proc_thermal_pci_suspend(struct device *dev) 366{ 367 struct pci_dev *pdev = to_pci_dev(dev); 368 struct proc_thermal_device *proc_priv; 369 struct proc_thermal_pci *pci_info; 370 371 proc_priv = pci_get_drvdata(pdev); 372 pci_info = proc_priv->priv_data; 373 374 if (!pci_info->no_legacy) 375 return proc_thermal_suspend(dev); 376 377 return 0; 378} 379static int proc_thermal_pci_resume(struct device *dev) 380{ 381 struct pci_dev *pdev = to_pci_dev(dev); 382 struct proc_thermal_device *proc_priv; 383 struct proc_thermal_pci *pci_info; 384 385 proc_priv = pci_get_drvdata(pdev); 386 pci_info = proc_priv->priv_data; 387 388 if (pci_info->stored_thres) { 389 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 390 pci_info->stored_thres / 1000); 391 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); 392 } 393 394 if (!pci_info->no_legacy) 395 return proc_thermal_resume(dev); 396 397 return 0; 398} 399#else 400#define proc_thermal_pci_suspend NULL 401#define proc_thermal_pci_resume NULL 402#endif 403 404static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend, 405 proc_thermal_pci_resume); 406 407static const struct pci_device_id proc_thermal_pci_ids[] = { 408 { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | 409 PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, 410 { PCI_DEVICE_DATA(INTEL, LNLM_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, 411 { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | 412 PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | 413 PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) }, 414 { PCI_DEVICE_DATA(INTEL, ARL_S_THERMAL, PROC_THERMAL_FEATURE_RAPL | 415 PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT) }, 416 { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | 417 PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, 418 { }, 419}; 420 421MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids); 422 423static struct pci_driver proc_thermal_pci_driver = { 424 .name = DRV_NAME, 425 .probe = proc_thermal_pci_probe, 426 .remove = proc_thermal_pci_remove, 427 .id_table = proc_thermal_pci_ids, 428 .driver.pm = &proc_thermal_pci_pm, 429}; 430 431module_pci_driver(proc_thermal_pci_driver); 432 433MODULE_IMPORT_NS(INT340X_THERMAL); 434 435MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 436MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); 437MODULE_LICENSE("GPL v2"); 438