]> Git Repo - J-linux.git/blob - drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / thermal / intel / int340x_thermal / processor_thermal_device_pci.c
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         .governor_name = "user_space",
276         .no_hwmon = true,
277 };
278
279 static bool msi_irq;
280
281 static void proc_thermal_free_msi(struct pci_dev *pdev, struct proc_thermal_pci *pci_info)
282 {
283         int i;
284
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);
288         }
289
290         pci_free_irq_vectors(pdev);
291 }
292
293 static int proc_thermal_setup_msi(struct pci_dev *pdev, struct proc_thermal_pci *pci_info)
294 {
295         int ret, i, irq, count;
296
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;
301         }
302
303         dev_info(&pdev->dev, "msi enabled:%d msix enabled:%d\n", pdev->msi_enabled,
304                  pdev->msix_enabled);
305
306         for (i = 0; i < count; i++) {
307                 irq =  pci_irq_vector(pdev, i);
308
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;
315                 }
316
317                 proc_thermal_msi_map[i] = irq;
318         }
319
320         msi_irq = true;
321
322         return 0;
323
324 err_free_msi_vectors:
325         proc_thermal_free_msi(pdev, pci_info);
326
327         return ret;
328 }
329
330 static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
331 {
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,
337         };
338         int irq_flag = 0, irq, ret;
339
340         proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL);
341         if (!proc_priv)
342                 return -ENOMEM;
343
344         pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL);
345         if (!pci_info)
346                 return -ENOMEM;
347
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;
353         }
354
355         pci_set_master(pdev);
356
357         INIT_DELAYED_WORK(&pci_info->work, proc_thermal_threshold_work_fn);
358
359         proc_priv->priv_data = pci_info;
360         pci_info->proc_priv = proc_priv;
361         pci_set_drvdata(pdev, proc_priv);
362
363         ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data);
364         if (ret)
365                 return ret;
366
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;
371         }
372
373         psv_trip.temperature = get_trip_temp(pci_info);
374
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;
382         }
383
384         if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MSI_SUPPORT)
385                 use_msi = true;
386
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;
394
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;
401                 }
402         }
403
404         ret = thermal_zone_device_enable(pci_info->tzone);
405         if (ret)
406                 goto err_free_vectors;
407
408         return 0;
409
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);
419
420         return ret;
421 }
422
423 static void proc_thermal_pci_remove(struct pci_dev *pdev)
424 {
425         struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
426         struct proc_thermal_pci *pci_info = proc_priv->priv_data;
427
428         cancel_delayed_work_sync(&pci_info->work);
429
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);
432
433         if (msi_irq)
434                 proc_thermal_free_msi(pdev, pci_info);
435
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);
440 }
441
442 #ifdef CONFIG_PM_SLEEP
443 static int proc_thermal_pci_suspend(struct device *dev)
444 {
445         struct pci_dev *pdev = to_pci_dev(dev);
446         struct proc_thermal_device *proc_priv;
447         struct proc_thermal_pci *pci_info;
448
449         proc_priv = pci_get_drvdata(pdev);
450         pci_info = proc_priv->priv_data;
451
452         if (!pci_info->no_legacy)
453                 return proc_thermal_suspend(dev);
454
455         return 0;
456 }
457 static int proc_thermal_pci_resume(struct device *dev)
458 {
459         struct pci_dev *pdev = to_pci_dev(dev);
460         struct proc_thermal_device *proc_priv;
461         struct proc_thermal_pci *pci_info;
462
463         proc_priv = pci_get_drvdata(pdev);
464         pci_info = proc_priv->priv_data;
465
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);
470         }
471
472         if (!pci_info->no_legacy)
473                 return proc_thermal_resume(dev);
474
475         return 0;
476 }
477 #else
478 #define proc_thermal_pci_suspend NULL
479 #define proc_thermal_pci_resume NULL
480 #endif
481
482 static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
483                          proc_thermal_pci_resume);
484
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         { },
499 };
500
501 MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids);
502
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,
509 };
510
511 module_pci_driver(proc_thermal_pci_driver);
512
513 MODULE_IMPORT_NS("INT340X_THERMAL");
514
515 MODULE_AUTHOR("Srinivas Pandruvada <[email protected]>");
516 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
517 MODULE_LICENSE("GPL v2");
This page took 0.057895 seconds and 4 git commands to generate.