Skip to content

Commit c0b5758

Browse files
YongWu-HFwilldeacon
authored andcommitted
iommu/mediatek: Add power-domain operation
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 <[email protected]> Reviewed-by: Tomasz Figa <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 34665c7 commit c0b5758

File tree

1 file changed

+34
-5
lines changed

1 file changed

+34
-5
lines changed

drivers/iommu/mtk_iommu.c

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,22 +182,33 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
182182
static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
183183
{
184184
for_each_m4u(data) {
185+
if (pm_runtime_get_if_in_use(data->dev) <= 0)
186+
continue;
187+
185188
writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
186189
data->base + data->plat_data->inv_sel_reg);
187190
writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
188191
wmb(); /* Make sure the tlb flush all done */
192+
193+
pm_runtime_put(data->dev);
189194
}
190195
}
191196

192197
static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
193198
size_t granule,
194199
struct mtk_iommu_data *data)
195200
{
201+
bool has_pm = !!data->dev->pm_domain;
196202
unsigned long flags;
197203
int ret;
198204
u32 tmp;
199205

200206
for_each_m4u(data) {
207+
if (has_pm) {
208+
if (pm_runtime_get_if_in_use(data->dev) <= 0)
209+
continue;
210+
}
211+
201212
spin_lock_irqsave(&data->tlb_lock, flags);
202213
writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
203214
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,
219230
/* Clear the CPE status */
220231
writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
221232
spin_unlock_irqrestore(&data->tlb_lock, flags);
233+
234+
if (has_pm)
235+
pm_runtime_put(data->dev);
222236
}
223237
}
224238

@@ -367,18 +381,27 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
367381
{
368382
struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
369383
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
384+
struct device *m4udev = data->dev;
370385
int ret;
371386

372387
if (!data)
373388
return -ENODEV;
374389

375390
if (!data->m4u_dom) { /* Initialize the M4U HW */
391+
ret = pm_runtime_resume_and_get(m4udev);
392+
if (ret < 0)
393+
return ret;
394+
376395
ret = mtk_iommu_hw_init(data);
377-
if (ret)
396+
if (ret) {
397+
pm_runtime_put(m4udev);
378398
return ret;
399+
}
379400
data->m4u_dom = dom;
380401
writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
381402
data->base + REG_MMU_PT_BASE_ADDR);
403+
404+
pm_runtime_put(m4udev);
382405
}
383406

384407
mtk_iommu_config(data, dev, true);
@@ -738,11 +761,13 @@ static int mtk_iommu_probe(struct platform_device *pdev)
738761
of_node_put(smicomm_node);
739762
data->smicomm_dev = &plarbdev->dev;
740763

764+
pm_runtime_enable(dev);
765+
741766
link = device_link_add(data->smicomm_dev, dev,
742767
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
743768
if (!link) {
744769
dev_err(dev, "Unable link %s.\n", dev_name(data->smicomm_dev));
745-
return -EINVAL;
770+
goto out_runtime_disable;
746771
}
747772

748773
platform_set_drvdata(pdev, data);
@@ -782,6 +807,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
782807
iommu_device_sysfs_remove(&data->iommu);
783808
out_link_remove:
784809
device_link_remove(data->smicomm_dev, dev);
810+
out_runtime_disable:
811+
pm_runtime_disable(dev);
785812
return ret;
786813
}
787814

@@ -797,6 +824,7 @@ static int mtk_iommu_remove(struct platform_device *pdev)
797824

798825
clk_disable_unprepare(data->bclk);
799826
device_link_remove(data->smicomm_dev, &pdev->dev);
827+
pm_runtime_disable(&pdev->dev);
800828
devm_free_irq(&pdev->dev, data->irq, data);
801829
component_master_del(&pdev->dev, &mtk_iommu_com_ops);
802830
return 0;
@@ -828,6 +856,9 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
828856
void __iomem *base = data->base;
829857
int ret;
830858

859+
/* Avoid first resume to affect the default value of registers below. */
860+
if (!m4u_dom)
861+
return 0;
831862
ret = clk_prepare_enable(data->bclk);
832863
if (ret) {
833864
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)
841872
writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
842873
writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
843874
writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
844-
if (m4u_dom)
845-
writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
846-
base + REG_MMU_PT_BASE_ADDR);
875+
writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + REG_MMU_PT_BASE_ADDR);
847876
return 0;
848877
}
849878

0 commit comments

Comments
 (0)