All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yong Wu <yong.wu@mediatek.com>
To: Joerg Roedel <joro@8bytes.org>, Rob Herring <robh+dt@kernel.org>,
	Matthias Brugger <matthias.bgg@gmail.com>,
	Will Deacon <will@kernel.org>,
	Robin Murphy <robin.murphy@arm.com>
Cc: Krzysztof Kozlowski <krzk@kernel.org>,
	Evan Green <evgreen@chromium.org>, Tomasz Figa <tfiga@google.com>,
	<linux-mediatek@lists.infradead.org>,
	<srv_heupstream@mediatek.com>, <devicetree@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<iommu@lists.linux-foundation.org>, <yong.wu@mediatek.com>,
	<youlin.pei@mediatek.com>,
	Nicolas Boichat <drinkcat@chromium.org>, <anan.sun@mediatek.com>,
	<chao.hao@mediatek.com>
Subject: [PATCH v6 20/33] iommu/mediatek: Add power-domain operation
Date: Mon, 11 Jan 2021 19:19:01 +0800	[thread overview]
Message-ID: <20210111111914.22211-21-yong.wu@mediatek.com> (raw)
In-Reply-To: <20210111111914.22211-1-yong.wu@mediatek.com>

In the previous SoC, the M4U HW is in the EMI power domain which is
always on. the latest M4U is in the display power domain which may be
turned on/off, thus we have to add pm_runtime interface for it.

When the engine work, the engine always enable the power and clocks for
smi-larb/smi-common, then the M4U's power will always be powered on
automatically via the device link with smi-common.

Note: we don't enable the M4U power in iommu_map/unmap for tlb flush.
If its power already is on, of course it is ok. if the power is off,
the main tlb will be reset while M4U power on, thus the tlb flush while
m4u power off is unnecessary, just skip it.
Therefore, we increase the ref_count for pm when pm status is ACTIVE,
otherwise, skip it. Meanwhile, the tlb_flush_range is called so often,
thus, update pm ref_count while the SoC has power-domain to avoid touch the
dev->power.lock. and the tlb_flush_all only is called when boot, so no
need check if the SoC has power-domain to keep code clean.

There will be one case that pm runctime status is not expected when tlb
flush. After boot, the display may call dma_alloc_attrs before it call
pm_runtime_get(disp-dev), then the m4u's pm status is not active inside
the dma_alloc_attrs. Since it only happens after boot, the tlb is clean
at that time, I also think this is ok.

Signed-off-by: Yong Wu <yong.wu@mediatek.com>
---
 drivers/iommu/mtk_iommu.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 3682137b789a..b9c63c8de33e 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -182,10 +182,15 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
 static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
 {
 	for_each_m4u(data) {
+		if (pm_runtime_get_if_in_use(data->dev) <= 0)
+			continue;
+
 		writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
 			       data->base + data->plat_data->inv_sel_reg);
 		writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
 		wmb(); /* Make sure the tlb flush all done */
+
+		pm_runtime_put(data->dev);
 	}
 }
 
@@ -193,11 +198,17 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
 					   size_t granule,
 					   struct mtk_iommu_data *data)
 {
+	bool has_pm = !!data->dev->pm_domain;
 	unsigned long flags;
 	int ret;
 	u32 tmp;
 
 	for_each_m4u(data) {
+		if (has_pm) {
+			if (pm_runtime_get_if_in_use(data->dev) <= 0)
+				continue;
+		}
+
 		spin_lock_irqsave(&data->tlb_lock, flags);
 		writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
 			       data->base + data->plat_data->inv_sel_reg);
@@ -219,6 +230,9 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
 		/* Clear the CPE status */
 		writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
 		spin_unlock_irqrestore(&data->tlb_lock, flags);
+
+		if (has_pm)
+			pm_runtime_put(data->dev);
 	}
 }
 
@@ -367,18 +381,27 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
 {
 	struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
 	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct device *m4udev = data->dev;
 	int ret;
 
 	if (!data)
 		return -ENODEV;
 
 	if (!data->m4u_dom) { /* Initialize the M4U HW */
+		ret = pm_runtime_resume_and_get(m4udev);
+		if (ret < 0)
+			return ret;
+
 		ret = mtk_iommu_hw_init(data);
-		if (ret)
+		if (ret) {
+			pm_runtime_put(m4udev);
 			return ret;
+		}
 		data->m4u_dom = dom;
 		writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
 		       data->base + REG_MMU_PT_BASE_ADDR);
+
+		pm_runtime_put(m4udev);
 	}
 
 	mtk_iommu_config(data, dev, true);
@@ -738,11 +761,13 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 	of_node_put(smicomm_node);
 	data->smicomm_dev = &plarbdev->dev;
 
+	pm_runtime_enable(dev);
+
 	link = device_link_add(data->smicomm_dev, dev,
 			DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
 	if (!link) {
 		dev_err(dev, "Unable link %s.\n", dev_name(data->smicomm_dev));
-		return -EINVAL;
+		goto out_runtime_disable;
 	}
 
 	platform_set_drvdata(pdev, data);
@@ -782,6 +807,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 	iommu_device_sysfs_remove(&data->iommu);
 out_link_remove:
 	device_link_remove(data->smicomm_dev, dev);
+out_runtime_disable:
+	pm_runtime_disable(dev);
 	return ret;
 }
 
@@ -797,6 +824,7 @@ static int mtk_iommu_remove(struct platform_device *pdev)
 
 	clk_disable_unprepare(data->bclk);
 	device_link_remove(data->smicomm_dev, &pdev->dev);
+	pm_runtime_disable(&pdev->dev);
 	devm_free_irq(&pdev->dev, data->irq, data);
 	component_master_del(&pdev->dev, &mtk_iommu_com_ops);
 	return 0;
@@ -828,6 +856,9 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
 	void __iomem *base = data->base;
 	int ret;
 
+	/* Avoid first resume to affect the default value of registers below. */
+	if (!m4u_dom)
+		return 0;
 	ret = clk_prepare_enable(data->bclk);
 	if (ret) {
 		dev_err(data->dev, "Failed to enable clk(%d) in resume\n", ret);
@@ -841,9 +872,7 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
 	writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
 	writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
 	writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
-	if (m4u_dom)
-		writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
-		       base + REG_MMU_PT_BASE_ADDR);
+	writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + REG_MMU_PT_BASE_ADDR);
 	return 0;
 }
 
-- 
2.18.0


WARNING: multiple messages have this Message-ID (diff)
From: Yong Wu <yong.wu@mediatek.com>
To: Joerg Roedel <joro@8bytes.org>, Rob Herring <robh+dt@kernel.org>,
	Matthias Brugger <matthias.bgg@gmail.com>,
	Will Deacon <will@kernel.org>,
	Robin Murphy <robin.murphy@arm.com>
Cc: youlin.pei@mediatek.com, devicetree@vger.kernel.org,
	Nicolas Boichat <drinkcat@chromium.org>,
	srv_heupstream@mediatek.com, chao.hao@mediatek.com,
	linux-kernel@vger.kernel.org, Evan Green <evgreen@chromium.org>,
	Tomasz Figa <tfiga@google.com>,
	iommu@lists.linux-foundation.org,
	linux-mediatek@lists.infradead.org,
	Krzysztof Kozlowski <krzk@kernel.org>,
	anan.sun@mediatek.com, linux-arm-kernel@lists.infradead.org
Subject: [PATCH v6 20/33] iommu/mediatek: Add power-domain operation
Date: Mon, 11 Jan 2021 19:19:01 +0800	[thread overview]
Message-ID: <20210111111914.22211-21-yong.wu@mediatek.com> (raw)
In-Reply-To: <20210111111914.22211-1-yong.wu@mediatek.com>

In the previous SoC, the M4U HW is in the EMI power domain which is
always on. the latest M4U is in the display power domain which may be
turned on/off, thus we have to add pm_runtime interface for it.

When the engine work, the engine always enable the power and clocks for
smi-larb/smi-common, then the M4U's power will always be powered on
automatically via the device link with smi-common.

Note: we don't enable the M4U power in iommu_map/unmap for tlb flush.
If its power already is on, of course it is ok. if the power is off,
the main tlb will be reset while M4U power on, thus the tlb flush while
m4u power off is unnecessary, just skip it.
Therefore, we increase the ref_count for pm when pm status is ACTIVE,
otherwise, skip it. Meanwhile, the tlb_flush_range is called so often,
thus, update pm ref_count while the SoC has power-domain to avoid touch the
dev->power.lock. and the tlb_flush_all only is called when boot, so no
need check if the SoC has power-domain to keep code clean.

There will be one case that pm runctime status is not expected when tlb
flush. After boot, the display may call dma_alloc_attrs before it call
pm_runtime_get(disp-dev), then the m4u's pm status is not active inside
the dma_alloc_attrs. Since it only happens after boot, the tlb is clean
at that time, I also think this is ok.

Signed-off-by: Yong Wu <yong.wu@mediatek.com>
---
 drivers/iommu/mtk_iommu.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 3682137b789a..b9c63c8de33e 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -182,10 +182,15 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
 static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
 {
 	for_each_m4u(data) {
+		if (pm_runtime_get_if_in_use(data->dev) <= 0)
+			continue;
+
 		writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
 			       data->base + data->plat_data->inv_sel_reg);
 		writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
 		wmb(); /* Make sure the tlb flush all done */
+
+		pm_runtime_put(data->dev);
 	}
 }
 
@@ -193,11 +198,17 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
 					   size_t granule,
 					   struct mtk_iommu_data *data)
 {
+	bool has_pm = !!data->dev->pm_domain;
 	unsigned long flags;
 	int ret;
 	u32 tmp;
 
 	for_each_m4u(data) {
+		if (has_pm) {
+			if (pm_runtime_get_if_in_use(data->dev) <= 0)
+				continue;
+		}
+
 		spin_lock_irqsave(&data->tlb_lock, flags);
 		writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
 			       data->base + data->plat_data->inv_sel_reg);
@@ -219,6 +230,9 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
 		/* Clear the CPE status */
 		writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
 		spin_unlock_irqrestore(&data->tlb_lock, flags);
+
+		if (has_pm)
+			pm_runtime_put(data->dev);
 	}
 }
 
@@ -367,18 +381,27 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
 {
 	struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
 	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct device *m4udev = data->dev;
 	int ret;
 
 	if (!data)
 		return -ENODEV;
 
 	if (!data->m4u_dom) { /* Initialize the M4U HW */
+		ret = pm_runtime_resume_and_get(m4udev);
+		if (ret < 0)
+			return ret;
+
 		ret = mtk_iommu_hw_init(data);
-		if (ret)
+		if (ret) {
+			pm_runtime_put(m4udev);
 			return ret;
+		}
 		data->m4u_dom = dom;
 		writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
 		       data->base + REG_MMU_PT_BASE_ADDR);
+
+		pm_runtime_put(m4udev);
 	}
 
 	mtk_iommu_config(data, dev, true);
@@ -738,11 +761,13 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 	of_node_put(smicomm_node);
 	data->smicomm_dev = &plarbdev->dev;
 
+	pm_runtime_enable(dev);
+
 	link = device_link_add(data->smicomm_dev, dev,
 			DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
 	if (!link) {
 		dev_err(dev, "Unable link %s.\n", dev_name(data->smicomm_dev));
-		return -EINVAL;
+		goto out_runtime_disable;
 	}
 
 	platform_set_drvdata(pdev, data);
@@ -782,6 +807,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 	iommu_device_sysfs_remove(&data->iommu);
 out_link_remove:
 	device_link_remove(data->smicomm_dev, dev);
+out_runtime_disable:
+	pm_runtime_disable(dev);
 	return ret;
 }
 
@@ -797,6 +824,7 @@ static int mtk_iommu_remove(struct platform_device *pdev)
 
 	clk_disable_unprepare(data->bclk);
 	device_link_remove(data->smicomm_dev, &pdev->dev);
+	pm_runtime_disable(&pdev->dev);
 	devm_free_irq(&pdev->dev, data->irq, data);
 	component_master_del(&pdev->dev, &mtk_iommu_com_ops);
 	return 0;
@@ -828,6 +856,9 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
 	void __iomem *base = data->base;
 	int ret;
 
+	/* Avoid first resume to affect the default value of registers below. */
+	if (!m4u_dom)
+		return 0;
 	ret = clk_prepare_enable(data->bclk);
 	if (ret) {
 		dev_err(data->dev, "Failed to enable clk(%d) in resume\n", ret);
@@ -841,9 +872,7 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
 	writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
 	writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
 	writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
-	if (m4u_dom)
-		writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
-		       base + REG_MMU_PT_BASE_ADDR);
+	writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + REG_MMU_PT_BASE_ADDR);
 	return 0;
 }
 
-- 
2.18.0

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

WARNING: multiple messages have this Message-ID (diff)
From: Yong Wu <yong.wu@mediatek.com>
To: Joerg Roedel <joro@8bytes.org>, Rob Herring <robh+dt@kernel.org>,
	"Matthias Brugger" <matthias.bgg@gmail.com>,
	Will Deacon <will@kernel.org>,
	Robin Murphy <robin.murphy@arm.com>
Cc: youlin.pei@mediatek.com, devicetree@vger.kernel.org,
	Nicolas Boichat <drinkcat@chromium.org>,
	srv_heupstream@mediatek.com, chao.hao@mediatek.com,
	linux-kernel@vger.kernel.org, Evan Green <evgreen@chromium.org>,
	yong.wu@mediatek.com, Tomasz Figa <tfiga@google.com>,
	iommu@lists.linux-foundation.org,
	linux-mediatek@lists.infradead.org,
	Krzysztof Kozlowski <krzk@kernel.org>,
	anan.sun@mediatek.com, linux-arm-kernel@lists.infradead.org
Subject: [PATCH v6 20/33] iommu/mediatek: Add power-domain operation
Date: Mon, 11 Jan 2021 19:19:01 +0800	[thread overview]
Message-ID: <20210111111914.22211-21-yong.wu@mediatek.com> (raw)
In-Reply-To: <20210111111914.22211-1-yong.wu@mediatek.com>

In the previous SoC, the M4U HW is in the EMI power domain which is
always on. the latest M4U is in the display power domain which may be
turned on/off, thus we have to add pm_runtime interface for it.

When the engine work, the engine always enable the power and clocks for
smi-larb/smi-common, then the M4U's power will always be powered on
automatically via the device link with smi-common.

Note: we don't enable the M4U power in iommu_map/unmap for tlb flush.
If its power already is on, of course it is ok. if the power is off,
the main tlb will be reset while M4U power on, thus the tlb flush while
m4u power off is unnecessary, just skip it.
Therefore, we increase the ref_count for pm when pm status is ACTIVE,
otherwise, skip it. Meanwhile, the tlb_flush_range is called so often,
thus, update pm ref_count while the SoC has power-domain to avoid touch the
dev->power.lock. and the tlb_flush_all only is called when boot, so no
need check if the SoC has power-domain to keep code clean.

There will be one case that pm runctime status is not expected when tlb
flush. After boot, the display may call dma_alloc_attrs before it call
pm_runtime_get(disp-dev), then the m4u's pm status is not active inside
the dma_alloc_attrs. Since it only happens after boot, the tlb is clean
at that time, I also think this is ok.

Signed-off-by: Yong Wu <yong.wu@mediatek.com>
---
 drivers/iommu/mtk_iommu.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 3682137b789a..b9c63c8de33e 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -182,10 +182,15 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
 static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
 {
 	for_each_m4u(data) {
+		if (pm_runtime_get_if_in_use(data->dev) <= 0)
+			continue;
+
 		writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
 			       data->base + data->plat_data->inv_sel_reg);
 		writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
 		wmb(); /* Make sure the tlb flush all done */
+
+		pm_runtime_put(data->dev);
 	}
 }
 
@@ -193,11 +198,17 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
 					   size_t granule,
 					   struct mtk_iommu_data *data)
 {
+	bool has_pm = !!data->dev->pm_domain;
 	unsigned long flags;
 	int ret;
 	u32 tmp;
 
 	for_each_m4u(data) {
+		if (has_pm) {
+			if (pm_runtime_get_if_in_use(data->dev) <= 0)
+				continue;
+		}
+
 		spin_lock_irqsave(&data->tlb_lock, flags);
 		writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
 			       data->base + data->plat_data->inv_sel_reg);
@@ -219,6 +230,9 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
 		/* Clear the CPE status */
 		writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
 		spin_unlock_irqrestore(&data->tlb_lock, flags);
+
+		if (has_pm)
+			pm_runtime_put(data->dev);
 	}
 }
 
@@ -367,18 +381,27 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
 {
 	struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
 	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct device *m4udev = data->dev;
 	int ret;
 
 	if (!data)
 		return -ENODEV;
 
 	if (!data->m4u_dom) { /* Initialize the M4U HW */
+		ret = pm_runtime_resume_and_get(m4udev);
+		if (ret < 0)
+			return ret;
+
 		ret = mtk_iommu_hw_init(data);
-		if (ret)
+		if (ret) {
+			pm_runtime_put(m4udev);
 			return ret;
+		}
 		data->m4u_dom = dom;
 		writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
 		       data->base + REG_MMU_PT_BASE_ADDR);
+
+		pm_runtime_put(m4udev);
 	}
 
 	mtk_iommu_config(data, dev, true);
@@ -738,11 +761,13 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 	of_node_put(smicomm_node);
 	data->smicomm_dev = &plarbdev->dev;
 
+	pm_runtime_enable(dev);
+
 	link = device_link_add(data->smicomm_dev, dev,
 			DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
 	if (!link) {
 		dev_err(dev, "Unable link %s.\n", dev_name(data->smicomm_dev));
-		return -EINVAL;
+		goto out_runtime_disable;
 	}
 
 	platform_set_drvdata(pdev, data);
@@ -782,6 +807,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 	iommu_device_sysfs_remove(&data->iommu);
 out_link_remove:
 	device_link_remove(data->smicomm_dev, dev);
+out_runtime_disable:
+	pm_runtime_disable(dev);
 	return ret;
 }
 
@@ -797,6 +824,7 @@ static int mtk_iommu_remove(struct platform_device *pdev)
 
 	clk_disable_unprepare(data->bclk);
 	device_link_remove(data->smicomm_dev, &pdev->dev);
+	pm_runtime_disable(&pdev->dev);
 	devm_free_irq(&pdev->dev, data->irq, data);
 	component_master_del(&pdev->dev, &mtk_iommu_com_ops);
 	return 0;
@@ -828,6 +856,9 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
 	void __iomem *base = data->base;
 	int ret;
 
+	/* Avoid first resume to affect the default value of registers below. */
+	if (!m4u_dom)
+		return 0;
 	ret = clk_prepare_enable(data->bclk);
 	if (ret) {
 		dev_err(data->dev, "Failed to enable clk(%d) in resume\n", ret);
@@ -841,9 +872,7 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
 	writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
 	writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
 	writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
-	if (m4u_dom)
-		writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
-		       base + REG_MMU_PT_BASE_ADDR);
+	writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + REG_MMU_PT_BASE_ADDR);
 	return 0;
 }
 
-- 
2.18.0
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

WARNING: multiple messages have this Message-ID (diff)
From: Yong Wu <yong.wu@mediatek.com>
To: Joerg Roedel <joro@8bytes.org>, Rob Herring <robh+dt@kernel.org>,
	"Matthias Brugger" <matthias.bgg@gmail.com>,
	Will Deacon <will@kernel.org>,
	Robin Murphy <robin.murphy@arm.com>
Cc: youlin.pei@mediatek.com, devicetree@vger.kernel.org,
	Nicolas Boichat <drinkcat@chromium.org>,
	srv_heupstream@mediatek.com, chao.hao@mediatek.com,
	linux-kernel@vger.kernel.org, Evan Green <evgreen@chromium.org>,
	yong.wu@mediatek.com, Tomasz Figa <tfiga@google.com>,
	iommu@lists.linux-foundation.org,
	linux-mediatek@lists.infradead.org,
	Krzysztof Kozlowski <krzk@kernel.org>,
	anan.sun@mediatek.com, linux-arm-kernel@lists.infradead.org
Subject: [PATCH v6 20/33] iommu/mediatek: Add power-domain operation
Date: Mon, 11 Jan 2021 19:19:01 +0800	[thread overview]
Message-ID: <20210111111914.22211-21-yong.wu@mediatek.com> (raw)
In-Reply-To: <20210111111914.22211-1-yong.wu@mediatek.com>

In the previous SoC, the M4U HW is in the EMI power domain which is
always on. the latest M4U is in the display power domain which may be
turned on/off, thus we have to add pm_runtime interface for it.

When the engine work, the engine always enable the power and clocks for
smi-larb/smi-common, then the M4U's power will always be powered on
automatically via the device link with smi-common.

Note: we don't enable the M4U power in iommu_map/unmap for tlb flush.
If its power already is on, of course it is ok. if the power is off,
the main tlb will be reset while M4U power on, thus the tlb flush while
m4u power off is unnecessary, just skip it.
Therefore, we increase the ref_count for pm when pm status is ACTIVE,
otherwise, skip it. Meanwhile, the tlb_flush_range is called so often,
thus, update pm ref_count while the SoC has power-domain to avoid touch the
dev->power.lock. and the tlb_flush_all only is called when boot, so no
need check if the SoC has power-domain to keep code clean.

There will be one case that pm runctime status is not expected when tlb
flush. After boot, the display may call dma_alloc_attrs before it call
pm_runtime_get(disp-dev), then the m4u's pm status is not active inside
the dma_alloc_attrs. Since it only happens after boot, the tlb is clean
at that time, I also think this is ok.

Signed-off-by: Yong Wu <yong.wu@mediatek.com>
---
 drivers/iommu/mtk_iommu.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 3682137b789a..b9c63c8de33e 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -182,10 +182,15 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
 static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
 {
 	for_each_m4u(data) {
+		if (pm_runtime_get_if_in_use(data->dev) <= 0)
+			continue;
+
 		writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
 			       data->base + data->plat_data->inv_sel_reg);
 		writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
 		wmb(); /* Make sure the tlb flush all done */
+
+		pm_runtime_put(data->dev);
 	}
 }
 
@@ -193,11 +198,17 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
 					   size_t granule,
 					   struct mtk_iommu_data *data)
 {
+	bool has_pm = !!data->dev->pm_domain;
 	unsigned long flags;
 	int ret;
 	u32 tmp;
 
 	for_each_m4u(data) {
+		if (has_pm) {
+			if (pm_runtime_get_if_in_use(data->dev) <= 0)
+				continue;
+		}
+
 		spin_lock_irqsave(&data->tlb_lock, flags);
 		writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
 			       data->base + data->plat_data->inv_sel_reg);
@@ -219,6 +230,9 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
 		/* Clear the CPE status */
 		writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
 		spin_unlock_irqrestore(&data->tlb_lock, flags);
+
+		if (has_pm)
+			pm_runtime_put(data->dev);
 	}
 }
 
@@ -367,18 +381,27 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
 {
 	struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
 	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct device *m4udev = data->dev;
 	int ret;
 
 	if (!data)
 		return -ENODEV;
 
 	if (!data->m4u_dom) { /* Initialize the M4U HW */
+		ret = pm_runtime_resume_and_get(m4udev);
+		if (ret < 0)
+			return ret;
+
 		ret = mtk_iommu_hw_init(data);
-		if (ret)
+		if (ret) {
+			pm_runtime_put(m4udev);
 			return ret;
+		}
 		data->m4u_dom = dom;
 		writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
 		       data->base + REG_MMU_PT_BASE_ADDR);
+
+		pm_runtime_put(m4udev);
 	}
 
 	mtk_iommu_config(data, dev, true);
@@ -738,11 +761,13 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 	of_node_put(smicomm_node);
 	data->smicomm_dev = &plarbdev->dev;
 
+	pm_runtime_enable(dev);
+
 	link = device_link_add(data->smicomm_dev, dev,
 			DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
 	if (!link) {
 		dev_err(dev, "Unable link %s.\n", dev_name(data->smicomm_dev));
-		return -EINVAL;
+		goto out_runtime_disable;
 	}
 
 	platform_set_drvdata(pdev, data);
@@ -782,6 +807,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 	iommu_device_sysfs_remove(&data->iommu);
 out_link_remove:
 	device_link_remove(data->smicomm_dev, dev);
+out_runtime_disable:
+	pm_runtime_disable(dev);
 	return ret;
 }
 
@@ -797,6 +824,7 @@ static int mtk_iommu_remove(struct platform_device *pdev)
 
 	clk_disable_unprepare(data->bclk);
 	device_link_remove(data->smicomm_dev, &pdev->dev);
+	pm_runtime_disable(&pdev->dev);
 	devm_free_irq(&pdev->dev, data->irq, data);
 	component_master_del(&pdev->dev, &mtk_iommu_com_ops);
 	return 0;
@@ -828,6 +856,9 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
 	void __iomem *base = data->base;
 	int ret;
 
+	/* Avoid first resume to affect the default value of registers below. */
+	if (!m4u_dom)
+		return 0;
 	ret = clk_prepare_enable(data->bclk);
 	if (ret) {
 		dev_err(data->dev, "Failed to enable clk(%d) in resume\n", ret);
@@ -841,9 +872,7 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
 	writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
 	writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
 	writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
-	if (m4u_dom)
-		writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
-		       base + REG_MMU_PT_BASE_ADDR);
+	writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + REG_MMU_PT_BASE_ADDR);
 	return 0;
 }
 
-- 
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2021-01-11 11:23 UTC|newest]

Thread overview: 206+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-11 11:18 [PATCH v6 00/33] MT8192 IOMMU support Yong Wu
2021-01-11 11:18 ` Yong Wu
2021-01-11 11:18 ` Yong Wu
2021-01-11 11:18 ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 01/33] dt-bindings: iommu: mediatek: Convert IOMMU to DT schema Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 02/33] dt-bindings: memory: mediatek: Add a common memory header file Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 03/33] dt-bindings: memory: mediatek: Extend LARB_NR_MAX to 32 Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 04/33] dt-bindings: memory: mediatek: Rename header guard for SMI header file Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 05/33] dt-bindings: mediatek: Add binding for mt8192 IOMMU Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 06/33] of/device: Move dma_range_map before of_iommu_configure Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-14 19:27   ` Rob Herring
2021-01-14 19:27     ` Rob Herring
2021-01-14 19:27     ` Rob Herring
2021-01-14 19:27     ` Rob Herring
2021-01-15  5:30     ` Yong Wu
2021-01-15  5:30       ` Yong Wu
2021-01-15  5:30       ` Yong Wu
2021-01-15  5:30       ` Yong Wu
2021-01-18 15:49       ` Robin Murphy
2021-01-18 15:49         ` Robin Murphy
2021-01-18 15:49         ` Robin Murphy
2021-01-18 15:49         ` Robin Murphy
2021-01-19  9:13         ` Paul Kocialkowski
2021-01-19  9:13           ` Paul Kocialkowski
2021-01-19  9:13           ` Paul Kocialkowski
2021-01-19  9:13           ` Paul Kocialkowski
2021-01-19  9:20         ` Yong Wu
2021-01-19  9:20           ` Yong Wu
2021-01-19  9:20           ` Yong Wu
2021-01-19  9:20           ` Yong Wu
2021-01-19  9:37           ` Paul Kocialkowski
2021-01-19  9:37             ` Paul Kocialkowski
2021-01-19  9:37             ` Paul Kocialkowski
2021-01-19  9:37             ` Paul Kocialkowski
2021-01-11 11:18 ` [PATCH v6 07/33] iommu: Avoid reallocate default domain for a group Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-26 22:23   ` Will Deacon
2021-01-26 22:23     ` Will Deacon
2021-01-26 22:23     ` Will Deacon
2021-01-26 22:23     ` Will Deacon
2021-01-27  9:39     ` Yong Wu
2021-01-27  9:39       ` Yong Wu
2021-01-27  9:39       ` Yong Wu
2021-01-27  9:39       ` Yong Wu
2021-01-28 21:10       ` Will Deacon
2021-01-28 21:10         ` Will Deacon
2021-01-28 21:10         ` Will Deacon
2021-01-28 21:10         ` Will Deacon
2021-01-28 21:14         ` Will Deacon
2021-01-28 21:14           ` Will Deacon
2021-01-28 21:14           ` Will Deacon
2021-01-28 21:14           ` Will Deacon
2021-01-29  0:03           ` Robin Murphy
2021-01-29  0:03             ` Robin Murphy
2021-01-29  0:03             ` Robin Murphy
2021-01-29  0:03             ` Robin Murphy
2021-01-29  1:52           ` Yong Wu
2021-01-29  1:52             ` Yong Wu
2021-01-29  1:52             ` Yong Wu
2021-01-29  1:52             ` Yong Wu
2021-01-29  8:47             ` Will Deacon
2021-01-29  8:47               ` Will Deacon
2021-01-29  8:47               ` Will Deacon
2021-01-11 11:18 ` [PATCH v6 08/33] iommu/mediatek: Use the common mtk-memory-port.h Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 09/33] iommu/io-pgtable-arm-v7s: Use ias to check the valid iova in unmap Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 10/33] iommu/io-pgtable-arm-v7s: Extend PA34 for MediaTek Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 11/33] iommu/io-pgtable-arm-v7s: Clarify LVL_SHIFT/BITS macro Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 12/33] iommu/io-pgtable-arm-v7s: Add cfg as a param in some macros Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 13/33] iommu/io-pgtable-arm-v7s: Quad lvl1 pgtable for MediaTek Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 14/33] iommu/mediatek: Add a flag for iova 34bits case Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 15/33] iommu/mediatek: Update oas for v7s Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 16/33] iommu/mediatek: Move hw_init into attach_device Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 17/33] iommu/mediatek: Add error handle for mtk_iommu_probe Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18 ` [PATCH v6 18/33] iommu/mediatek: Add device link for smi-common and m4u Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:18   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 19/33] iommu/mediatek: Add pm runtime callback Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` Yong Wu [this message]
2021-01-11 11:19   ` [PATCH v6 20/33] iommu/mediatek: Add power-domain operation Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 21/33] iommu/mediatek: Support up to 34bit iova in tlb flush Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 22/33] iommu/mediatek: Support report iova 34bit translation fault in ISR Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 23/33] iommu/mediatek: Adjust the structure Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 24/33] iommu/mediatek: Move domain_finalise into attach_device Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 25/33] iommu/mediatek: Move geometry.aperture updating into domain_finalise Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 26/33] iommu/mediatek: Add iova_region structure Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 27/33] iommu/mediatek: Add get_domain_id from dev->dma_range_map Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 28/33] iommu/mediatek: Support for multi domains Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 29/33] iommu/mediatek: Add iova reserved function Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 30/33] iommu/mediatek: Support master use iova over 32bit Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 31/33] iommu/mediatek: Remove unnecessary check in attach_device Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 32/33] iommu/mediatek: Add mt8192 support Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19 ` [PATCH v6 33/33] MAINTAINERS: Add entry for MediaTek IOMMU Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-11 11:19   ` Yong Wu
2021-01-26 22:25 ` [PATCH v6 00/33] MT8192 IOMMU support Will Deacon
2021-01-26 22:25   ` Will Deacon
2021-01-26 22:25   ` Will Deacon
2021-01-26 22:25   ` Will Deacon
2021-01-29 11:27 ` Tomasz Figa
2021-01-29 11:27   ` Tomasz Figa
2021-01-29 11:27   ` Tomasz Figa
2021-02-01 14:54 ` Will Deacon
2021-02-01 14:54   ` Will Deacon
2021-02-01 14:54   ` Will Deacon
2021-02-01 14:54   ` Will Deacon
2021-02-02  2:03   ` Yong Wu
2021-02-02  2:03     ` Yong Wu
2021-02-02  2:03     ` Yong Wu
2021-02-02  2:03     ` Yong Wu
2021-02-02 13:33     ` Will Deacon
2021-02-02 13:33       ` Will Deacon
2021-02-02 13:33       ` Will Deacon
2021-02-02 13:33       ` Will Deacon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210111111914.22211-21-yong.wu@mediatek.com \
    --to=yong.wu@mediatek.com \
    --cc=anan.sun@mediatek.com \
    --cc=chao.hao@mediatek.com \
    --cc=devicetree@vger.kernel.org \
    --cc=drinkcat@chromium.org \
    --cc=evgreen@chromium.org \
    --cc=iommu@lists.linux-foundation.org \
    --cc=joro@8bytes.org \
    --cc=krzk@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=matthias.bgg@gmail.com \
    --cc=robh+dt@kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=srv_heupstream@mediatek.com \
    --cc=tfiga@google.com \
    --cc=will@kernel.org \
    --cc=youlin.pei@mediatek.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.