Commit d7127de1 authored by Yong Wu's avatar Yong Wu Committed by Joerg Roedel
Browse files

iommu/mediatek: Backup/restore regsiters for multi banks



Each bank has some independent registers. thus backup/restore them for
each a bank when suspend and resume.

Signed-off-by: default avatarYong Wu <yong.wu@mediatek.com>
Reviewed-by: default avatarAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: default avatarMatthias Brugger <matthias.bgg@gmail.com>
Link: https://lore.kernel.org/r/20220503071427.2285-35-yong.wu@mediatek.com


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 42d57fc5
Loading
Loading
Loading
Loading
+31 −15
Original line number Diff line number Diff line
@@ -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,