1 // SPDX-License-Identifier: GPL-2.0-only
3 * Processor thermal device for newer processors
4 * Copyright (c) 2020, Intel Corporation.
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>
13 #include "int340x_thermal_zone.h"
14 #include "processor_thermal_device.h"
16 #define DRV_NAME "proc_thermal_pci"
19 module_param(use_msi
, bool, 0644);
20 MODULE_PARM_DESC(use_msi
,
21 "Use PCI MSI based interrupts for processor thermal device.");
23 struct proc_thermal_pci
{
25 struct proc_thermal_device
*proc_priv
;
26 struct thermal_zone_device
*tzone
;
27 struct delayed_work work
;
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
,
46 struct proc_thermal_mmio_info
{
47 enum proc_thermal_mmio_type mmio_type
;
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 },
66 /* List of supported MSI IDs (sources) */
67 enum proc_thermal_msi_ids
{
75 /* Stores IRQ associated with a MSI ID */
76 static int proc_thermal_msi_map
[MSI_THERMAL_MAX
];
78 #define B0D4_THERMAL_NOTIFY_DELAY 1000
79 static int notify_delay_ms
= B0D4_THERMAL_NOTIFY_DELAY
;
81 static void proc_thermal_mmio_read(struct proc_thermal_pci
*pci_info
,
82 enum proc_thermal_mmio_type type
,
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
;
91 static void proc_thermal_mmio_write(struct proc_thermal_pci
*pci_info
,
92 enum proc_thermal_mmio_type type
,
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
;
103 value
&= proc_thermal_mmio_info
[type
].mask
;
104 value
<<= proc_thermal_mmio_info
[type
].shift
;
106 current_val
|= value
;
107 iowrite32(current_val
, ((u8 __iomem
*)pci_info
->proc_priv
->mmio_base
+
108 proc_thermal_mmio_info
[type
].mmio_addr
));
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.
116 static void proc_thermal_threshold_work_fn(struct work_struct
*work
)
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
;
124 thermal_zone_device_update(tzone
, THERMAL_TRIP_VIOLATED
);
126 /* Enable interrupt flag */
127 proc_thermal_mmio_write(pci_info
, PROC_THERMAL_MMIO_INT_ENABLE_0
, 1);
130 static void pkg_thermal_schedule_work(struct delayed_work
*work
)
132 unsigned long ms
= msecs_to_jiffies(notify_delay_ms
);
134 schedule_delayed_work(work
, ms
);
137 static void proc_thermal_clear_soc_int_status(struct proc_thermal_device
*proc_priv
)
141 if (!(proc_priv
->mmio_feature_mask
&
142 (PROC_THERMAL_FEATURE_WT_HINT
| PROC_THERMAL_FEATURE_POWER_FLOOR
)))
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
);
150 static irqreturn_t
proc_thermal_irq_thread_handler(int irq
, void *devid
)
152 struct proc_thermal_pci
*pci_info
= devid
;
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
);
161 static int proc_thermal_match_msi_irq(int irq
)
168 for (i
= 0; i
< MSI_THERMAL_MAX
; i
++) {
169 if (proc_thermal_msi_map
[i
] == irq
)
177 static irqreturn_t
proc_thermal_irq_handler(int irq
, void *devid
)
179 struct proc_thermal_pci
*pci_info
= devid
;
180 struct proc_thermal_device
*proc_priv
;
181 int ret
= IRQ_NONE
, msi_id
;
184 proc_priv
= pci_info
->proc_priv
;
186 msi_id
= proc_thermal_match_msi_irq(irq
);
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
;
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
;
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.
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
);
212 pci_write_config_byte(pci_info
->pdev
, 0xdc, 0x01);
217 static int sys_get_curr_temp(struct thermal_zone_device
*tzd
, int *temp
)
219 struct proc_thermal_pci
*pci_info
= thermal_zone_device_priv(tzd
);
222 proc_thermal_mmio_read(pci_info
, PROC_THERMAL_MMIO_PKG_TEMP
, &_temp
);
223 *temp
= (unsigned long)_temp
* 1000;
228 static int sys_set_trip_temp(struct thermal_zone_device
*tzd
,
229 const struct thermal_trip
*trip
, int temp
)
231 struct proc_thermal_pci
*pci_info
= thermal_zone_device_priv(tzd
);
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;
242 proc_thermal_mmio_read(pci_info
, PROC_THERMAL_MMIO_TJMAX
, &tjmax
);
243 _temp
= tjmax
- (temp
/ 1000);
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);
250 pci_info
->stored_thres
= temp
;
255 static int get_trip_temp(struct proc_thermal_pci
*pci_info
)
259 proc_thermal_mmio_read(pci_info
, PROC_THERMAL_MMIO_THRES_0
, &temp
);
261 return THERMAL_TEMP_INVALID
;
263 proc_thermal_mmio_read(pci_info
, PROC_THERMAL_MMIO_TJMAX
, &tjmax
);
264 temp
= (tjmax
- temp
) * 1000;
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
,
274 static struct thermal_zone_params tzone_params
= {
275 .governor_name
= "user_space",
281 static void proc_thermal_free_msi(struct pci_dev
*pdev
, struct proc_thermal_pci
*pci_info
)
285 for (i
= 0; i
< MSI_THERMAL_MAX
; i
++) {
286 if (proc_thermal_msi_map
[i
])
287 devm_free_irq(&pdev
->dev
, proc_thermal_msi_map
[i
], pci_info
);
290 pci_free_irq_vectors(pdev
);
293 static int proc_thermal_setup_msi(struct pci_dev
*pdev
, struct proc_thermal_pci
*pci_info
)
295 int ret
, i
, irq
, count
;
297 count
= pci_alloc_irq_vectors(pdev
, 1, MSI_THERMAL_MAX
, PCI_IRQ_MSI
| PCI_IRQ_MSIX
);
299 dev_err(&pdev
->dev
, "Failed to allocate vectors!\n");
303 dev_info(&pdev
->dev
, "msi enabled:%d msix enabled:%d\n", pdev
->msi_enabled
,
306 for (i
= 0; i
< count
; i
++) {
307 irq
= pci_irq_vector(pdev
, i
);
309 ret
= devm_request_threaded_irq(&pdev
->dev
, irq
, proc_thermal_irq_handler
,
310 proc_thermal_irq_thread_handler
,
311 0, KBUILD_MODNAME
, pci_info
);
313 dev_err(&pdev
->dev
, "Request IRQ %d failed\n", irq
);
314 goto err_free_msi_vectors
;
317 proc_thermal_msi_map
[i
] = irq
;
324 err_free_msi_vectors
:
325 proc_thermal_free_msi(pdev
, pci_info
);
330 static int proc_thermal_pci_probe(struct pci_dev
*pdev
, const struct pci_device_id
*id
)
332 struct proc_thermal_device
*proc_priv
;
333 struct proc_thermal_pci
*pci_info
;
334 struct thermal_trip psv_trip
= {
335 .type
= THERMAL_TRIP_PASSIVE
,
336 .flags
= THERMAL_TRIP_FLAG_RW_TEMP
,
338 int irq_flag
= 0, irq
, ret
;
340 proc_priv
= devm_kzalloc(&pdev
->dev
, sizeof(*proc_priv
), GFP_KERNEL
);
344 pci_info
= devm_kzalloc(&pdev
->dev
, sizeof(*pci_info
), GFP_KERNEL
);
348 pci_info
->pdev
= pdev
;
349 ret
= pcim_enable_device(pdev
);
351 dev_err(&pdev
->dev
, "error: could not enable device\n");
355 pci_set_master(pdev
);
357 INIT_DELAYED_WORK(&pci_info
->work
, proc_thermal_threshold_work_fn
);
359 proc_priv
->priv_data
= pci_info
;
360 pci_info
->proc_priv
= proc_priv
;
361 pci_set_drvdata(pdev
, proc_priv
);
363 ret
= proc_thermal_mmio_add(pdev
, proc_priv
, id
->driver_data
);
367 ret
= proc_thermal_add(&pdev
->dev
, proc_priv
);
369 dev_err(&pdev
->dev
, "error: proc_thermal_add, will continue\n");
370 pci_info
->no_legacy
= 1;
373 psv_trip
.temperature
= get_trip_temp(pci_info
);
375 pci_info
->tzone
= thermal_zone_device_register_with_trips("TCPU_PCI", &psv_trip
,
378 &tzone_params
, 0, 0);
379 if (IS_ERR(pci_info
->tzone
)) {
380 ret
= PTR_ERR(pci_info
->tzone
);
384 if (proc_priv
->mmio_feature_mask
& PROC_THERMAL_FEATURE_MSI_SUPPORT
)
388 ret
= proc_thermal_setup_msi(pdev
, pci_info
);
392 irq_flag
= IRQF_SHARED
;
395 ret
= devm_request_threaded_irq(&pdev
->dev
, irq
, proc_thermal_irq_handler
,
396 proc_thermal_irq_thread_handler
, irq_flag
,
397 KBUILD_MODNAME
, pci_info
);
399 dev_err(&pdev
->dev
, "Request IRQ %d failed\n", pdev
->irq
);
404 ret
= thermal_zone_device_enable(pci_info
->tzone
);
406 goto err_free_vectors
;
412 proc_thermal_free_msi(pdev
, pci_info
);
414 thermal_zone_device_unregister(pci_info
->tzone
);
416 if (!pci_info
->no_legacy
)
417 proc_thermal_remove(proc_priv
);
418 proc_thermal_mmio_remove(pdev
, proc_priv
);
423 static void proc_thermal_pci_remove(struct pci_dev
*pdev
)
425 struct proc_thermal_device
*proc_priv
= pci_get_drvdata(pdev
);
426 struct proc_thermal_pci
*pci_info
= proc_priv
->priv_data
;
428 cancel_delayed_work_sync(&pci_info
->work
);
430 proc_thermal_mmio_write(pci_info
, PROC_THERMAL_MMIO_THRES_0
, 0);
431 proc_thermal_mmio_write(pci_info
, PROC_THERMAL_MMIO_INT_ENABLE_0
, 0);
434 proc_thermal_free_msi(pdev
, pci_info
);
436 thermal_zone_device_unregister(pci_info
->tzone
);
437 proc_thermal_mmio_remove(pdev
, pci_info
->proc_priv
);
438 if (!pci_info
->no_legacy
)
439 proc_thermal_remove(proc_priv
);
442 #ifdef CONFIG_PM_SLEEP
443 static int proc_thermal_pci_suspend(struct device
*dev
)
445 struct pci_dev
*pdev
= to_pci_dev(dev
);
446 struct proc_thermal_device
*proc_priv
;
447 struct proc_thermal_pci
*pci_info
;
449 proc_priv
= pci_get_drvdata(pdev
);
450 pci_info
= proc_priv
->priv_data
;
452 if (!pci_info
->no_legacy
)
453 return proc_thermal_suspend(dev
);
457 static int proc_thermal_pci_resume(struct device
*dev
)
459 struct pci_dev
*pdev
= to_pci_dev(dev
);
460 struct proc_thermal_device
*proc_priv
;
461 struct proc_thermal_pci
*pci_info
;
463 proc_priv
= pci_get_drvdata(pdev
);
464 pci_info
= proc_priv
->priv_data
;
466 if (pci_info
->stored_thres
) {
467 proc_thermal_mmio_write(pci_info
, PROC_THERMAL_MMIO_THRES_0
,
468 pci_info
->stored_thres
/ 1000);
469 proc_thermal_mmio_write(pci_info
, PROC_THERMAL_MMIO_INT_ENABLE_0
, 1);
472 if (!pci_info
->no_legacy
)
473 return proc_thermal_resume(dev
);
478 #define proc_thermal_pci_suspend NULL
479 #define proc_thermal_pci_resume NULL
482 static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm
, proc_thermal_pci_suspend
,
483 proc_thermal_pci_resume
);
485 static const struct pci_device_id proc_thermal_pci_ids
[] = {
486 { PCI_DEVICE_DATA(INTEL
, ADL_THERMAL
, PROC_THERMAL_FEATURE_RAPL
|
487 PROC_THERMAL_FEATURE_FIVR
| PROC_THERMAL_FEATURE_DVFS
| PROC_THERMAL_FEATURE_WT_REQ
) },
488 { PCI_DEVICE_DATA(INTEL
, LNLM_THERMAL
, PROC_THERMAL_FEATURE_MSI_SUPPORT
|
489 PROC_THERMAL_FEATURE_RAPL
| PROC_THERMAL_FEATURE_DLVR
|
490 PROC_THERMAL_FEATURE_WT_HINT
| PROC_THERMAL_FEATURE_POWER_FLOOR
) },
491 { PCI_DEVICE_DATA(INTEL
, MTLP_THERMAL
, PROC_THERMAL_FEATURE_RAPL
|
492 PROC_THERMAL_FEATURE_FIVR
| PROC_THERMAL_FEATURE_DVFS
| PROC_THERMAL_FEATURE_DLVR
|
493 PROC_THERMAL_FEATURE_WT_HINT
| PROC_THERMAL_FEATURE_POWER_FLOOR
) },
494 { PCI_DEVICE_DATA(INTEL
, ARL_S_THERMAL
, PROC_THERMAL_FEATURE_RAPL
|
495 PROC_THERMAL_FEATURE_DVFS
| PROC_THERMAL_FEATURE_DLVR
| PROC_THERMAL_FEATURE_WT_HINT
) },
496 { PCI_DEVICE_DATA(INTEL
, RPL_THERMAL
, PROC_THERMAL_FEATURE_RAPL
|
497 PROC_THERMAL_FEATURE_FIVR
| PROC_THERMAL_FEATURE_DVFS
| PROC_THERMAL_FEATURE_WT_REQ
) },
501 MODULE_DEVICE_TABLE(pci
, proc_thermal_pci_ids
);
503 static struct pci_driver proc_thermal_pci_driver
= {
505 .probe
= proc_thermal_pci_probe
,
506 .remove
= proc_thermal_pci_remove
,
507 .id_table
= proc_thermal_pci_ids
,
508 .driver
.pm
= &proc_thermal_pci_pm
,
511 module_pci_driver(proc_thermal_pci_driver
);
513 MODULE_IMPORT_NS("INT340X_THERMAL");
515 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
516 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
517 MODULE_LICENSE("GPL v2");