Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d6d7100f authored by Prakash Gupta's avatar Prakash Gupta
Browse files

iommu: arm-smmu: wait for writes to complete before power off



SMMU registers are mapped as nGnRE, so with early acknolwdgement from
intermediate buffer, there is a chance of power off to happen first before
writes complete. Subsequently when the write is committed to actual
peripheral register, we may observe failure due to dependent power off. So
wait for all writes to complete before initiating a power off.

Change-Id: If0e9f47075b2e95cc5bc997b5f17bce69576cebc
Signed-off-by: default avatarPrakash Gupta <guptap@codeaurora.org>
parent f1c106bc
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -699,6 +699,20 @@ static int arm_smmu_arch_device_group(struct device *dev,
	return smmu->arch_ops->device_group(dev, group);
}

static void arm_smmu_arch_write_sync(struct arm_smmu_device *smmu)
{
	u32 id;

	if (!smmu)
		return;

	/* Read to complete prior write transcations */
	id = readl_relaxed(ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_ID0);

	/* Wait for read to complete before off */
	rmb();
}

static struct device_node *dev_get_dev_node(struct device *dev)
{
	if (dev_is_pci(dev)) {
@@ -946,6 +960,9 @@ static int arm_smmu_power_on_atomic(struct arm_smmu_power_resources *pwr)
static void arm_smmu_power_off_atomic(struct arm_smmu_power_resources *pwr)
{
	unsigned long flags;
	struct arm_smmu_device *smmu = pwr->dev->driver_data;

	arm_smmu_arch_write_sync(smmu);

	spin_lock_irqsave(&pwr->clock_refs_lock, flags);
	if (pwr->clock_refs_count == 0) {
@@ -5377,6 +5394,12 @@ static phys_addr_t qsmmuv500_iova_to_phys(
	qsmmuv500_tbu_resume(tbu);

out_power_off:
	/* Read to complete prior write transcations */
	val = readl_relaxed(tbu->base + DEBUG_SR_HALT_ACK_REG);

	/* Wait for read to complete before off */
	rmb();

	arm_smmu_power_off(tbu->pwr);

	return phys;