iommu/mediatek: Backup/restore regsiters for multi banks
authorYong Wu <yong.wu@mediatek.com>
Tue, 3 May 2022 07:14:25 +0000 (15:14 +0800)
committerJoerg Roedel <jroedel@suse.de>
Wed, 4 May 2022 08:39:40 +0000 (10:39 +0200)
Each bank has some independent registers. thus backup/restore them for
each a bank when suspend and resume.

Signed-off-by: Yong Wu <yong.wu@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
Link: https://lore.kernel.org/r/20220503071427.2285-35-yong.wu@mediatek.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/mtk_iommu.c

index 400dea33aea11c170ae9db035c400b77aa301f9f..d3e8773b4c4756465bdecf5bf14f0e87622e3847 100644 (file)
@@ -173,11 +173,12 @@ struct mtk_iommu_suspend_reg {
        u32                     misc_ctrl;
        u32                     dcm_dis;
        u32                     ctrl_reg;
-       u32                     int_control0;
-       u32                     int_main_control;
-       u32                     ivrp_paddr;
        u32                     vld_pa_rng;
        u32                     wr_len_ctrl;
+
+       u32                     int_control[MTK_IOMMU_BANK_MAX];
+       u32                     int_main_control[MTK_IOMMU_BANK_MAX];
+       u32                     ivrp_paddr[MTK_IOMMU_BANK_MAX];
 };
 
 struct mtk_iommu_plat_data {
@@ -1302,16 +1303,23 @@ static int __maybe_unused mtk_iommu_runtime_suspend(struct device *dev)
 {
        struct mtk_iommu_data *data = dev_get_drvdata(dev);
        struct mtk_iommu_suspend_reg *reg = &data->reg;
-       void __iomem *base = data->bank[0].base;
+       void __iomem *base;
+       int i = 0;
 
+       base = data->bank[i].base;
        reg->wr_len_ctrl = readl_relaxed(base + REG_MMU_WR_LEN_CTRL);
        reg->misc_ctrl = readl_relaxed(base + REG_MMU_MISC_CTRL);
        reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM_DIS);
        reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG);
-       reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0);
-       reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL);
-       reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR);
        reg->vld_pa_rng = readl_relaxed(base + REG_MMU_VLD_PA_RNG);
+       do {
+               if (!data->plat_data->banks_enable[i])
+                       continue;
+               base = data->bank[i].base;
+               reg->int_control[i] = readl_relaxed(base + REG_MMU_INT_CONTROL0);
+               reg->int_main_control[i] = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL);
+               reg->ivrp_paddr[i] = readl_relaxed(base + REG_MMU_IVRP_PADDR);
+       } while (++i < data->plat_data->banks_num);
        clk_disable_unprepare(data->bclk);
        return 0;
 }
@@ -1320,9 +1328,9 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
 {
        struct mtk_iommu_data *data = dev_get_drvdata(dev);
        struct mtk_iommu_suspend_reg *reg = &data->reg;
-       struct mtk_iommu_domain *m4u_dom = data->bank[0].m4u_dom;
-       void __iomem *base = data->bank[0].base;
-       int ret;
+       struct mtk_iommu_domain *m4u_dom;
+       void __iomem *base;
+       int ret, i = 0;
 
        ret = clk_prepare_enable(data->bclk);
        if (ret) {
@@ -1334,18 +1342,26 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev)
         * Uppon first resume, only enable the clk and return, since the values of the
         * registers are not yet set.
         */
-       if (!m4u_dom)
+       if (!reg->wr_len_ctrl)
                return 0;
 
+       base = data->bank[i].base;
        writel_relaxed(reg->wr_len_ctrl, base + REG_MMU_WR_LEN_CTRL);
        writel_relaxed(reg->misc_ctrl, base + REG_MMU_MISC_CTRL);
        writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM_DIS);
        writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG);
-       writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
-       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);
-       writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + REG_MMU_PT_BASE_ADDR);
+       do {
+               m4u_dom = data->bank[i].m4u_dom;
+               if (!data->plat_data->banks_enable[i] || !m4u_dom)
+                       continue;
+               base = data->bank[i].base;
+               writel_relaxed(reg->int_control[i], base + REG_MMU_INT_CONTROL0);
+               writel_relaxed(reg->int_main_control[i], base + REG_MMU_INT_MAIN_CONTROL);
+               writel_relaxed(reg->ivrp_paddr[i], base + REG_MMU_IVRP_PADDR);
+               writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
+                      base + REG_MMU_PT_BASE_ADDR);
+       } while (++i < data->plat_data->banks_num);
 
        /*
         * Users may allocate dma buffer before they call pm_runtime_get,