Some platforms(ex: mt6779) need to improve performance by setting
REG_MMU_WR_LEN register. And we can use WR_THROT_EN macro to control
whether we need to set the register. If the register uses default value,
iommu will send command to EMI without restriction, when the number of
commands become more and more, it will drop the EMI performance. So when
more than ten_commands(default value) don't be handled for EMI, iommu will
stop send command to EMI for keeping EMI's performace by enabling write
throttling mechanism(bit[5][21]=0) in MMU_WR_LEN_CTRL register.

Cc: Matthias Brugger <matthias....@gmail.com>
Signed-off-by: Chao Hao <chao....@mediatek.com>
---
 drivers/iommu/mtk_iommu.c | 10 ++++++++++
 drivers/iommu/mtk_iommu.h |  2 ++
 2 files changed, 12 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index ec1f86913739..92316c4175a9 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -46,6 +46,8 @@
 #define F_MMU_STANDARD_AXI_MODE_BIT            (BIT(3) | BIT(19))
 
 #define REG_MMU_DCM_DIS                                0x050
+#define REG_MMU_WR_LEN                         0x054
+#define F_MMU_WR_THROT_DIS_BIT                 (BIT(5) |  BIT(21))
 
 #define REG_MMU_CTRL_REG                       0x110
 #define F_MMU_TF_PROT_TO_PROGRAM_ADDR          (2 << 4)
@@ -582,6 +584,12 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
                writel_relaxed(regval, data->base + REG_MMU_VLD_PA_RNG);
        }
        writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
+       if (MTK_IOMMU_HAS_FLAG(data->plat_data, WR_THROT_EN)) {
+               /* write command throttling mode */
+               regval = readl_relaxed(data->base + REG_MMU_WR_LEN);
+               regval &= ~F_MMU_WR_THROT_DIS_BIT;
+               writel_relaxed(regval, data->base + REG_MMU_WR_LEN);
+       }
 
        regval = readl_relaxed(data->base + REG_MMU_MISC_CTRL);
        if (MTK_IOMMU_HAS_FLAG(data->plat_data, RESET_AXI)) {
@@ -737,6 +745,7 @@ static int __maybe_unused mtk_iommu_suspend(struct device 
*dev)
        struct mtk_iommu_suspend_reg *reg = &data->reg;
        void __iomem *base = data->base;
 
+       reg->wr_len = readl_relaxed(base + REG_MMU_WR_LEN);
        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);
@@ -761,6 +770,7 @@ static int __maybe_unused mtk_iommu_resume(struct device 
*dev)
                dev_err(data->dev, "Failed to enable clk(%d) in resume\n", ret);
                return ret;
        }
+       writel_relaxed(reg->wr_len, base + REG_MMU_WR_LEN);
        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);
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index be6d32ee5bda..ce4f4e8f03aa 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -24,6 +24,7 @@
 #define RESET_AXI                      BIT(3)
 #define OUT_ORDER_EN                   BIT(4)
 #define HAS_SUB_COMM                   BIT(5)
+#define WR_THROT_EN                    BIT(6)
 
 #define MTK_IOMMU_HAS_FLAG(pdata, _x) \
                ((((pdata)->flags) & (_x)) == (_x))
@@ -36,6 +37,7 @@ struct mtk_iommu_suspend_reg {
        u32                             int_main_control;
        u32                             ivrp_paddr;
        u32                             vld_pa_rng;
+       u32                             wr_len;
 };
 
 enum mtk_iommu_plat {
-- 
2.18.0
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to