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_suspend(struct device *dev) 111 { 112 return proc_thermal_suspend(dev); 113 } 114 static int proc_thermal_pci_resume(struct device *dev) 115 { 116 return proc_thermal_resume(dev); 117 } 118 #else 119 #define proc_thermal_pci_suspend NULL 120 #define proc_thermal_pci_resume NULL 121 #endif 122 123 static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend, 124 proc_thermal_pci_resume); 125 126 static const struct pci_device_id proc_thermal_pci_ids[] = { 127 { PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) }, 128 { PCI_DEVICE_DATA(INTEL, BSW_THERMAL, 0) }, 129 { PCI_DEVICE_DATA(INTEL, BXT0_THERMAL, 0) }, 130 { PCI_DEVICE_DATA(INTEL, BXT1_THERMAL, 0) }, 131 { PCI_DEVICE_DATA(INTEL, BXTX_THERMAL, 0) }, 132 { PCI_DEVICE_DATA(INTEL, BXTP_THERMAL, 0) }, 133 { PCI_DEVICE_DATA(INTEL, CNL_THERMAL, 0) }, 134 { PCI_DEVICE_DATA(INTEL, CFL_THERMAL, 0) }, 135 { PCI_DEVICE_DATA(INTEL, GLK_THERMAL, 0) }, 136 { PCI_DEVICE_DATA(INTEL, HSB_THERMAL, 0) }, 137 { PCI_DEVICE_DATA(INTEL, ICL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, 138 { PCI_DEVICE_DATA(INTEL, JSL_THERMAL, 0) }, 139 { PCI_DEVICE_DATA(INTEL, SKL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, 140 { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_MBOX) }, 141 { }, 142 }; 143 144 MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids); 145 146 static struct pci_driver proc_thermal_pci_driver = { 147 .name = DRV_NAME, 148 .probe = proc_thermal_pci_probe, 149 .remove = proc_thermal_pci_remove, 150 .id_table = proc_thermal_pci_ids, 151 .driver.pm = &proc_thermal_pci_pm, 152 }; 153 154 module_pci_driver(proc_thermal_pci_driver); 155 156 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 157 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); 158 MODULE_LICENSE("GPL v2"); 159