thermal/drivers/int340x/processor_thermal: Add PCI MMIO based thermal driver
[linux-2.6-microblaze.git] / drivers / thermal / intel / int340x_thermal / processor_thermal_device_pci_legacy.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * B0D4 processor thermal device
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 #include "../intel_soc_dts_iosf.h"
16
17 #define DRV_NAME "proc_thermal"
18
19 static irqreturn_t proc_thermal_pci_msi_irq(int irq, void *devid)
20 {
21         struct proc_thermal_device *proc_priv;
22         struct pci_dev *pdev = devid;
23
24         proc_priv = pci_get_drvdata(pdev);
25
26         intel_soc_dts_iosf_interrupt_handler(proc_priv->soc_dts);
27
28         return IRQ_HANDLED;
29 }
30
31 static int proc_thermal_pci_probe(struct pci_dev *pdev,
32                                   const struct pci_device_id *id)
33 {
34         struct proc_thermal_device *proc_priv;
35         int ret;
36
37         ret = pcim_enable_device(pdev);
38         if (ret < 0) {
39                 dev_err(&pdev->dev, "error: could not enable device\n");
40                 return ret;
41         }
42
43         proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL);
44         if (!proc_priv)
45                 return -ENOMEM;
46
47         ret = proc_thermal_add(&pdev->dev, proc_priv);
48         if (ret)
49                 return ret;
50
51         pci_set_drvdata(pdev, proc_priv);
52
53         if (pdev->device == PCI_DEVICE_ID_INTEL_BSW_THERMAL) {
54                 /*
55                  * Enumerate additional DTS sensors available via IOSF.
56                  * But we are not treating as a failure condition, if
57                  * there are no aux DTSs enabled or fails. This driver
58                  * already exposes sensors, which can be accessed via
59                  * ACPI/MSR. So we don't want to fail for auxiliary DTSs.
60                  */
61                 proc_priv->soc_dts = intel_soc_dts_iosf_init(
62                                         INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0);
63
64                 if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) {
65                         ret = pci_enable_msi(pdev);
66                         if (!ret) {
67                                 ret = request_threaded_irq(pdev->irq, NULL,
68                                                 proc_thermal_pci_msi_irq,
69                                                 IRQF_ONESHOT, "proc_thermal",
70                                                 pdev);
71                                 if (ret) {
72                                         intel_soc_dts_iosf_exit(
73                                                         proc_priv->soc_dts);
74                                         pci_disable_msi(pdev);
75                                         proc_priv->soc_dts = NULL;
76                                 }
77                         }
78                 } else
79                         dev_err(&pdev->dev, "No auxiliary DTSs enabled\n");
80         } else {
81
82         }
83
84         ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data);
85         if (ret) {
86                 proc_thermal_remove(proc_priv);
87                 return ret;
88         }
89
90         return 0;
91 }
92
93 static void proc_thermal_pci_remove(struct pci_dev *pdev)
94 {
95         struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
96
97         if (proc_priv->soc_dts) {
98                 intel_soc_dts_iosf_exit(proc_priv->soc_dts);
99                 if (pdev->irq) {
100                         free_irq(pdev->irq, pdev);
101                         pci_disable_msi(pdev);
102                 }
103         }
104
105         proc_thermal_mmio_remove(pdev, proc_priv);
106         proc_thermal_remove(proc_priv);
107 }
108
109 #ifdef CONFIG_PM_SLEEP
110 static int proc_thermal_pci_resume(struct device *dev)
111 {
112         return proc_thermal_resume(dev);
113 }
114 #else
115 #define proc_thermal_pci_resume NULL
116 #endif
117
118 static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume);
119
120 static const struct pci_device_id proc_thermal_pci_ids[] = {
121         { PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) },
122         { PCI_DEVICE_DATA(INTEL, BSW_THERMAL, 0) },
123         { PCI_DEVICE_DATA(INTEL, BXT0_THERMAL, 0) },
124         { PCI_DEVICE_DATA(INTEL, BXT1_THERMAL, 0) },
125         { PCI_DEVICE_DATA(INTEL, BXTX_THERMAL, 0) },
126         { PCI_DEVICE_DATA(INTEL, BXTP_THERMAL, 0) },
127         { PCI_DEVICE_DATA(INTEL, CNL_THERMAL, 0) },
128         { PCI_DEVICE_DATA(INTEL, CFL_THERMAL, 0) },
129         { PCI_DEVICE_DATA(INTEL, GLK_THERMAL, 0) },
130         { PCI_DEVICE_DATA(INTEL, HSB_THERMAL, 0) },
131         { PCI_DEVICE_DATA(INTEL, ICL_THERMAL, PROC_THERMAL_FEATURE_RAPL) },
132         { PCI_DEVICE_DATA(INTEL, JSL_THERMAL, 0) },
133         { PCI_DEVICE_DATA(INTEL, SKL_THERMAL, PROC_THERMAL_FEATURE_RAPL) },
134         { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_MBOX) },
135         { },
136 };
137
138 MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids);
139
140 static struct pci_driver proc_thermal_pci_driver = {
141         .name           = DRV_NAME,
142         .probe          = proc_thermal_pci_probe,
143         .remove         = proc_thermal_pci_remove,
144         .id_table       = proc_thermal_pci_ids,
145         .driver.pm      = &proc_thermal_pci_pm,
146 };
147
148 static int __init proc_thermal_init(void)
149 {
150         return pci_register_driver(&proc_thermal_pci_driver);
151 }
152
153 static void __exit proc_thermal_exit(void)
154 {
155         pci_unregister_driver(&proc_thermal_pci_driver);
156 }
157
158 module_init(proc_thermal_init);
159 module_exit(proc_thermal_exit);
160
161 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
162 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
163 MODULE_LICENSE("GPL v2");