Commit 088f16f3 authored by Srinivas Pandruvada's avatar Srinivas Pandruvada Committed by Rafael J. Wysocki
Browse files

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: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
[ rjw: Changelog edits ]
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 24e4c262
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ void proc_thermal_wt_req_remove(struct pci_dev *pdev);
#define MBOX_DATA_BIT_VALID		31

#define SOC_WT_RES_INT_STATUS_OFFSET	0x5B18
#define SOC_WT_RES_INT_STATUS_MASK	GENMASK_ULL(3, 2)

int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp);
int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data);
+13 −0
Original line number Diff line number Diff line
@@ -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;
}
+0 −2
Original line number Diff line number Diff line
@@ -215,8 +215,6 @@ void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_dev
	if (!(status & SOC_WT_PREDICTION_INT_ACTIVE))
		return;

	writeq(status & ~SOC_WT_PREDICTION_INT_ACTIVE,
		       proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);
	sysfs_notify(&pdev->dev.kobj, "workload_hint", "workload_type_index");
}
EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_intr_callback, INT340X_THERMAL);