module: Convert symbol namespace to string literal
[linux.git] / drivers / thermal / intel / int340x_thermal / processor_thermal_device_pci.c
blob145d471546d50cecf2fa8934a5e1286d686d8744
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Processor thermal device for newer processors
4 * Copyright (c) 2020, Intel Corporation.
5 */
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"
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.");
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;
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
46 struct proc_thermal_mmio_info {
47 enum proc_thermal_mmio_type mmio_type;
48 u64 mmio_addr;
49 u64 shift;
50 u64 mask;
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 {
68 PKG_THERMAL,
69 DDR_THERMAL,
70 THERM_POWER_FLOOR,
71 WORKLOAD_CHANGE,
72 MSI_THERMAL_MAX
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,
83 u32 *value)
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,
93 u32 value)
95 u32 current_val;
96 u32 mask;
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;
123 if (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)
139 u64 status;
141 if (!(proc_priv->mmio_feature_mask &
142 (PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR)))
143 return;
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);
158 return IRQ_HANDLED;
161 static int proc_thermal_match_msi_irq(int irq)
163 int i;
165 if (!use_msi)
166 goto msi_fail;
168 for (i = 0; i < MSI_THERMAL_MAX; i++) {
169 if (proc_thermal_msi_map[i] == irq)
170 return i;
173 msi_fail:
174 return -EOPNOTSUPP;
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;
182 u32 status;
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);
209 ret = IRQ_HANDLED;
212 pci_write_config_byte(pci_info->pdev, 0xdc, 0x01);
214 return ret;
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);
220 u32 _temp;
222 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_PKG_TEMP, &_temp);
223 *temp = (unsigned long)_temp * 1000;
225 return 0;
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);
232 int tjmax, _temp;
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;
242 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
243 _temp = tjmax - (temp / 1000);
244 if (_temp < 0)
245 return -EINVAL;
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;
252 return 0;
255 static int get_trip_temp(struct proc_thermal_pci *pci_info)
257 int temp, tjmax;
259 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &temp);
260 if (!temp)
261 return THERMAL_TEMP_INVALID;
263 proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
264 temp = (tjmax - temp) * 1000;
266 return temp;
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",
276 .no_hwmon = true,
279 static bool msi_irq;
281 static void proc_thermal_free_msi(struct pci_dev *pdev, struct proc_thermal_pci *pci_info)
283 int i;
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);
298 if (count < 0) {
299 dev_err(&pdev->dev, "Failed to allocate vectors!\n");
300 return count;
303 dev_info(&pdev->dev, "msi enabled:%d msix enabled:%d\n", pdev->msi_enabled,
304 pdev->msix_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);
312 if (ret) {
313 dev_err(&pdev->dev, "Request IRQ %d failed\n", irq);
314 goto err_free_msi_vectors;
317 proc_thermal_msi_map[i] = irq;
320 msi_irq = true;
322 return 0;
324 err_free_msi_vectors:
325 proc_thermal_free_msi(pdev, pci_info);
327 return ret;
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);
341 if (!proc_priv)
342 return -ENOMEM;
344 pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL);
345 if (!pci_info)
346 return -ENOMEM;
348 pci_info->pdev = pdev;
349 ret = pcim_enable_device(pdev);
350 if (ret < 0) {
351 dev_err(&pdev->dev, "error: could not enable device\n");
352 return ret;
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);
364 if (ret)
365 return ret;
367 ret = proc_thermal_add(&pdev->dev, proc_priv);
368 if (ret) {
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,
376 1, pci_info,
377 &tzone_ops,
378 &tzone_params, 0, 0);
379 if (IS_ERR(pci_info->tzone)) {
380 ret = PTR_ERR(pci_info->tzone);
381 goto err_del_legacy;
384 if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MSI_SUPPORT)
385 use_msi = true;
387 if (use_msi) {
388 ret = proc_thermal_setup_msi(pdev, pci_info);
389 if (ret)
390 goto err_ret_tzone;
391 } else {
392 irq_flag = IRQF_SHARED;
393 irq = pdev->irq;
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);
398 if (ret) {
399 dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq);
400 goto err_ret_tzone;
404 ret = thermal_zone_device_enable(pci_info->tzone);
405 if (ret)
406 goto err_free_vectors;
408 return 0;
410 err_free_vectors:
411 if (msi_irq)
412 proc_thermal_free_msi(pdev, pci_info);
413 err_ret_tzone:
414 thermal_zone_device_unregister(pci_info->tzone);
415 err_del_legacy:
416 if (!pci_info->no_legacy)
417 proc_thermal_remove(proc_priv);
418 proc_thermal_mmio_remove(pdev, proc_priv);
420 return ret;
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);
433 if (msi_irq)
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);
455 return 0;
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);
475 return 0;
477 #else
478 #define proc_thermal_pci_suspend NULL
479 #define proc_thermal_pci_resume NULL
480 #endif
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) },
498 { },
501 MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids);
503 static struct pci_driver proc_thermal_pci_driver = {
504 .name = DRV_NAME,
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");