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 struct proc_thermal_pci { 19 struct pci_dev *pdev; 20 struct proc_thermal_device *proc_priv; 21 struct thermal_zone_device *tzone; 22 struct delayed_work work; 23 int stored_thres; 24 int no_legacy; 25 }; 26 27 enum proc_thermal_mmio_type { 28 PROC_THERMAL_MMIO_TJMAX, 29 PROC_THERMAL_MMIO_PP0_TEMP, 30 PROC_THERMAL_MMIO_PP1_TEMP, 31 PROC_THERMAL_MMIO_PKG_TEMP, 32 PROC_THERMAL_MMIO_THRES_0, 33 PROC_THERMAL_MMIO_THRES_1, 34 PROC_THERMAL_MMIO_INT_ENABLE_0, 35 PROC_THERMAL_MMIO_INT_ENABLE_1, 36 PROC_THERMAL_MMIO_INT_STATUS_0, 37 PROC_THERMAL_MMIO_INT_STATUS_1, 38 PROC_THERMAL_MMIO_MAX 39 }; 40 41 struct proc_thermal_mmio_info { 42 enum proc_thermal_mmio_type mmio_type; 43 u64 mmio_addr; 44 u64 shift; 45 u64 mask; 46 }; 47 48 static struct proc_thermal_mmio_info proc_thermal_mmio_info[] = { 49 { PROC_THERMAL_MMIO_TJMAX, 0x599c, 16, 0xff }, 50 { PROC_THERMAL_MMIO_PP0_TEMP, 0x597c, 0, 0xff }, 51 { PROC_THERMAL_MMIO_PP1_TEMP, 0x5980, 0, 0xff }, 52 { PROC_THERMAL_MMIO_PKG_TEMP, 0x5978, 0, 0xff }, 53 { PROC_THERMAL_MMIO_THRES_0, 0x5820, 8, 0x7F }, 54 { PROC_THERMAL_MMIO_THRES_1, 0x5820, 16, 0x7F }, 55 { PROC_THERMAL_MMIO_INT_ENABLE_0, 0x5820, 15, 0x01 }, 56 { PROC_THERMAL_MMIO_INT_ENABLE_1, 0x5820, 23, 0x01 }, 57 { PROC_THERMAL_MMIO_INT_STATUS_0, 0x7200, 6, 0x01 }, 58 { PROC_THERMAL_MMIO_INT_STATUS_1, 0x7200, 8, 0x01 }, 59 }; 60 61 #define B0D4_THERMAL_NOTIFY_DELAY 1000 62 static int notify_delay_ms = B0D4_THERMAL_NOTIFY_DELAY; 63 64 static void proc_thermal_mmio_read(struct proc_thermal_pci *pci_info, 65 enum proc_thermal_mmio_type type, 66 u32 *value) 67 { 68 *value = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base + 69 proc_thermal_mmio_info[type].mmio_addr)); 70 *value >>= proc_thermal_mmio_info[type].shift; 71 *value &= proc_thermal_mmio_info[type].mask; 72 } 73 74 static void proc_thermal_mmio_write(struct proc_thermal_pci *pci_info, 75 enum proc_thermal_mmio_type type, 76 u32 value) 77 { 78 u32 current_val; 79 u32 mask; 80 81 current_val = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base + 82 proc_thermal_mmio_info[type].mmio_addr)); 83 mask = proc_thermal_mmio_info[type].mask << proc_thermal_mmio_info[type].shift; 84 current_val &= ~mask; 85 86 value &= proc_thermal_mmio_info[type].mask; 87 value <<= proc_thermal_mmio_info[type].shift; 88 89 current_val |= value; 90 iowrite32(current_val, ((u8 __iomem *)pci_info->proc_priv->mmio_base + 91 proc_thermal_mmio_info[type].mmio_addr)); 92 } 93 94 /* 95 * To avoid sending two many messages to user space, we have 1 second delay. 96 * On interrupt we are disabling interrupt and enabling after 1 second. 97 * This workload function is delayed by 1 second. 98 */ 99 static void proc_thermal_threshold_work_fn(struct work_struct *work) 100 { 101 struct delayed_work *delayed_work = to_delayed_work(work); 102 struct proc_thermal_pci *pci_info = container_of(delayed_work, 103 struct proc_thermal_pci, work); 104 struct thermal_zone_device *tzone = pci_info->tzone; 105 106 if (tzone) 107 thermal_zone_device_update(tzone, THERMAL_TRIP_VIOLATED); 108 109 /* Enable interrupt flag */ 110 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); 111 } 112 113 static void pkg_thermal_schedule_work(struct delayed_work *work) 114 { 115 unsigned long ms = msecs_to_jiffies(notify_delay_ms); 116 117 schedule_delayed_work(work, ms); 118 } 119 120 static irqreturn_t proc_thermal_irq_handler(int irq, void *devid) 121 { 122 struct proc_thermal_pci *pci_info = devid; 123 u32 status; 124 125 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); 126 127 /* Disable enable interrupt flag */ 128 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); 129 pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); 130 131 pkg_thermal_schedule_work(&pci_info->work); 132 133 return IRQ_HANDLED; 134 } 135 136 static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) 137 { 138 struct proc_thermal_pci *pci_info = tzd->devdata; 139 u32 _temp; 140 141 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_PKG_TEMP, &_temp); 142 *temp = (unsigned long)_temp * 1000; 143 144 return 0; 145 } 146 147 static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp) 148 { 149 struct proc_thermal_pci *pci_info = tzd->devdata; 150 int tjmax, _temp; 151 152 if (temp <= 0) { 153 cancel_delayed_work_sync(&pci_info->work); 154 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); 155 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0); 156 pci_info->stored_thres = 0; 157 return 0; 158 } 159 160 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax); 161 _temp = tjmax - (temp / 1000); 162 if (_temp < 0) 163 return -EINVAL; 164 165 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, _temp); 166 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); 167 168 pci_info->stored_thres = temp; 169 170 return 0; 171 } 172 173 static int get_trip_temp(struct proc_thermal_pci *pci_info) 174 { 175 int temp, tjmax; 176 177 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &temp); 178 if (!temp) 179 return THERMAL_TEMP_INVALID; 180 181 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax); 182 temp = (tjmax - temp) * 1000; 183 184 return temp; 185 } 186 187 static struct thermal_trip psv_trip = { 188 .type = THERMAL_TRIP_PASSIVE, 189 }; 190 191 static struct thermal_zone_device_ops tzone_ops = { 192 .get_temp = sys_get_curr_temp, 193 .set_trip_temp = sys_set_trip_temp, 194 }; 195 196 static struct thermal_zone_params tzone_params = { 197 .governor_name = "user_space", 198 .no_hwmon = true, 199 }; 200 201 static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 202 { 203 struct proc_thermal_device *proc_priv; 204 struct proc_thermal_pci *pci_info; 205 int irq_flag = 0, irq, ret; 206 207 proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL); 208 if (!proc_priv) 209 return -ENOMEM; 210 211 pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL); 212 if (!pci_info) 213 return -ENOMEM; 214 215 pci_info->pdev = pdev; 216 ret = pcim_enable_device(pdev); 217 if (ret < 0) { 218 dev_err(&pdev->dev, "error: could not enable device\n"); 219 return ret; 220 } 221 222 pci_set_master(pdev); 223 224 INIT_DELAYED_WORK(&pci_info->work, proc_thermal_threshold_work_fn); 225 226 ret = proc_thermal_add(&pdev->dev, proc_priv); 227 if (ret) { 228 dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n"); 229 pci_info->no_legacy = 1; 230 } 231 232 proc_priv->priv_data = pci_info; 233 pci_info->proc_priv = proc_priv; 234 pci_set_drvdata(pdev, proc_priv); 235 236 ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data); 237 if (ret) 238 goto err_ret_thermal; 239 240 psv_trip.temperature = get_trip_temp(pci_info); 241 242 pci_info->tzone = thermal_zone_device_register_with_trips("TCPU_PCI", &psv_trip, 243 1, 1, pci_info, 244 &tzone_ops, 245 &tzone_params, 0, 0); 246 if (IS_ERR(pci_info->tzone)) { 247 ret = PTR_ERR(pci_info->tzone); 248 goto err_ret_mmio; 249 } 250 251 /* request and enable interrupt */ 252 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 253 if (ret < 0) { 254 dev_err(&pdev->dev, "Failed to allocate vectors!\n"); 255 goto err_ret_tzone; 256 } 257 if (!pdev->msi_enabled && !pdev->msix_enabled) 258 irq_flag = IRQF_SHARED; 259 260 irq = pci_irq_vector(pdev, 0); 261 ret = devm_request_threaded_irq(&pdev->dev, irq, 262 proc_thermal_irq_handler, NULL, 263 irq_flag, KBUILD_MODNAME, pci_info); 264 if (ret) { 265 dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq); 266 goto err_free_vectors; 267 } 268 269 ret = thermal_zone_device_enable(pci_info->tzone); 270 if (ret) 271 goto err_free_vectors; 272 273 return 0; 274 275 err_free_vectors: 276 pci_free_irq_vectors(pdev); 277 err_ret_tzone: 278 thermal_zone_device_unregister(pci_info->tzone); 279 err_ret_mmio: 280 proc_thermal_mmio_remove(pdev, proc_priv); 281 err_ret_thermal: 282 if (!pci_info->no_legacy) 283 proc_thermal_remove(proc_priv); 284 pci_disable_device(pdev); 285 286 return ret; 287 } 288 289 static void proc_thermal_pci_remove(struct pci_dev *pdev) 290 { 291 struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev); 292 struct proc_thermal_pci *pci_info = proc_priv->priv_data; 293 294 cancel_delayed_work_sync(&pci_info->work); 295 296 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0); 297 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); 298 299 devm_free_irq(&pdev->dev, pdev->irq, pci_info); 300 pci_free_irq_vectors(pdev); 301 302 thermal_zone_device_unregister(pci_info->tzone); 303 proc_thermal_mmio_remove(pdev, pci_info->proc_priv); 304 if (!pci_info->no_legacy) 305 proc_thermal_remove(proc_priv); 306 pci_disable_device(pdev); 307 } 308 309 #ifdef CONFIG_PM_SLEEP 310 static int proc_thermal_pci_suspend(struct device *dev) 311 { 312 struct pci_dev *pdev = to_pci_dev(dev); 313 struct proc_thermal_device *proc_priv; 314 struct proc_thermal_pci *pci_info; 315 316 proc_priv = pci_get_drvdata(pdev); 317 pci_info = proc_priv->priv_data; 318 319 if (!pci_info->no_legacy) 320 return proc_thermal_suspend(dev); 321 322 return 0; 323 } 324 static int proc_thermal_pci_resume(struct device *dev) 325 { 326 struct pci_dev *pdev = to_pci_dev(dev); 327 struct proc_thermal_device *proc_priv; 328 struct proc_thermal_pci *pci_info; 329 330 proc_priv = pci_get_drvdata(pdev); 331 pci_info = proc_priv->priv_data; 332 333 if (pci_info->stored_thres) { 334 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 335 pci_info->stored_thres / 1000); 336 proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1); 337 } 338 339 if (!pci_info->no_legacy) 340 return proc_thermal_resume(dev); 341 342 return 0; 343 } 344 #else 345 #define proc_thermal_pci_suspend NULL 346 #define proc_thermal_pci_resume NULL 347 #endif 348 349 static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend, 350 proc_thermal_pci_resume); 351 352 static const struct pci_device_id proc_thermal_pci_ids[] = { 353 { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, 354 { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, 355 { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, 356 { }, 357 }; 358 359 MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids); 360 361 static struct pci_driver proc_thermal_pci_driver = { 362 .name = DRV_NAME, 363 .probe = proc_thermal_pci_probe, 364 .remove = proc_thermal_pci_remove, 365 .id_table = proc_thermal_pci_ids, 366 .driver.pm = &proc_thermal_pci_pm, 367 }; 368 369 module_pci_driver(proc_thermal_pci_driver); 370 371 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 372 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); 373 MODULE_LICENSE("GPL v2"); 374