summaryrefslogtreecommitdiff
path: root/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
diff options
context:
space:
mode:
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>2023-10-09 22:05:33 +0300
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2023-10-12 22:09:48 +0300
commit088f16f35257becaed1c3deececda6080bc77ee3 (patch)
treecf8ebd94ca2e3bf83c27ce90530794c12ea30104 /drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
parent24e4c26202801f31392a04965b539e70223d9026 (diff)
downloadlinux-088f16f35257becaed1c3deececda6080bc77ee3.tar.xz
thermal: int340x: processor_thermal: Common function to clear SOC interrupt
The SOC interrupt status register contains multiple interrupt sources (workload hint interrupt and power floor interrupt). It is not possible to clear individual interrupt source with read-modify-write, as it may clear the new interrupt from the firmware after a read operation. It is also not possible to set the interrupt status bit to 1 for the other interrupt source, which is not part of clearing. Hence, create a common function, to clear all status bits at once. Call this function after processing all interrupt sources. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c')
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
index 3c5ced79ead0..d353a190ce44 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
@@ -122,11 +122,24 @@ static void pkg_thermal_schedule_work(struct delayed_work *work)
schedule_delayed_work(work, ms);
}
+static void proc_thermal_clear_soc_int_status(struct proc_thermal_device *proc_priv)
+{
+ u64 status;
+
+ if (!(proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT))
+ return;
+
+ status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);
+ writeq(status & ~SOC_WT_RES_INT_STATUS_MASK,
+ proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);
+}
+
static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid)
{
struct proc_thermal_pci *pci_info = devid;
proc_thermal_wt_intr_callback(pci_info->pdev, pci_info->proc_priv);
+ proc_thermal_clear_soc_int_status(pci_info->proc_priv);
return IRQ_HANDLED;
}