Merge branch 'arm/smmu' into arm/mediatek
[linux-2.6-microblaze.git] / drivers / iommu / mtk_iommu.c
index 0827d51..67a483c 100644 (file)
@@ -28,6 +28,7 @@
 #include "mtk_iommu.h"
 
 #define REG_MMU_PT_BASE_ADDR                   0x000
+#define MMU_PT_ADDR_MASK                       GENMASK(31, 7)
 
 #define REG_MMU_INVALIDATE                     0x020
 #define F_ALL_INVLD                            0x2
 #define REG_MMU_DCM_DIS                                0x050
 
 #define REG_MMU_CTRL_REG                       0x110
+#define F_MMU_TF_PROT_TO_PROGRAM_ADDR          (2 << 4)
 #define F_MMU_PREFETCH_RT_REPLACE_MOD          BIT(4)
-#define F_MMU_TF_PROTECT_SEL_SHIFT(data) \
-       ((data)->m4u_plat == M4U_MT2712 ? 4 : 5)
-/* It's named by F_MMU_TF_PROT_SEL in mt2712. */
-#define F_MMU_TF_PROTECT_SEL(prot, data) \
-       (((prot) & 0x3) << F_MMU_TF_PROTECT_SEL_SHIFT(data))
+#define F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173   (2 << 5)
 
 #define REG_MMU_IVRP_PADDR                     0x114
 
 #define F_INT_CLR_BIT                          BIT(12)
 
 #define REG_MMU_INT_MAIN_CONTROL               0x124
-#define F_INT_TRANSLATION_FAULT                        BIT(0)
-#define F_INT_MAIN_MULTI_HIT_FAULT             BIT(1)
-#define F_INT_INVALID_PA_FAULT                 BIT(2)
-#define F_INT_ENTRY_REPLACEMENT_FAULT          BIT(3)
-#define F_INT_TLB_MISS_FAULT                   BIT(4)
-#define F_INT_MISS_TRANSACTION_FIFO_FAULT      BIT(5)
-#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT   BIT(6)
+                                               /* mmu0 | mmu1 */
+#define F_INT_TRANSLATION_FAULT                        (BIT(0) | BIT(7))
+#define F_INT_MAIN_MULTI_HIT_FAULT             (BIT(1) | BIT(8))
+#define F_INT_INVALID_PA_FAULT                 (BIT(2) | BIT(9))
+#define F_INT_ENTRY_REPLACEMENT_FAULT          (BIT(3) | BIT(10))
+#define F_INT_TLB_MISS_FAULT                   (BIT(4) | BIT(11))
+#define F_INT_MISS_TRANSACTION_FIFO_FAULT      (BIT(5) | BIT(12))
+#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT   (BIT(6) | BIT(13))
 
 #define REG_MMU_CPE_DONE                       0x12C
 
 #define REG_MMU_FAULT_ST1                      0x134
+#define F_REG_MMU0_FAULT_MASK                  GENMASK(6, 0)
+#define F_REG_MMU1_FAULT_MASK                  GENMASK(13, 7)
 
-#define REG_MMU_FAULT_VA                       0x13c
+#define REG_MMU0_FAULT_VA                      0x13c
 #define F_MMU_FAULT_VA_WRITE_BIT               BIT(1)
 #define F_MMU_FAULT_VA_LAYER_BIT               BIT(0)
 
-#define REG_MMU_INVLD_PA                       0x140
-#define REG_MMU_INT_ID                         0x150
-#define F_MMU0_INT_ID_LARB_ID(a)               (((a) >> 7) & 0x7)
-#define F_MMU0_INT_ID_PORT_ID(a)               (((a) >> 2) & 0x1f)
+#define REG_MMU0_INVLD_PA                      0x140
+#define REG_MMU1_FAULT_VA                      0x144
+#define REG_MMU1_INVLD_PA                      0x148
+#define REG_MMU0_INT_ID                                0x150
+#define REG_MMU1_INT_ID                                0x154
+#define F_MMU_INT_ID_LARB_ID(a)                        (((a) >> 7) & 0x7)
+#define F_MMU_INT_ID_PORT_ID(a)                        (((a) >> 2) & 0x1f)
 
 #define MTK_PROTECT_PA_ALIGN                   128
 
@@ -107,6 +111,30 @@ struct mtk_iommu_domain {
 
 static const struct iommu_ops mtk_iommu_ops;
 
+/*
+ * In M4U 4GB mode, the physical address is remapped as below:
+ *
+ * CPU Physical address:
+ * ====================
+ *
+ * 0      1G       2G     3G       4G     5G
+ * |---A---|---B---|---C---|---D---|---E---|
+ * +--I/O--+------------Memory-------------+
+ *
+ * IOMMU output physical address:
+ *  =============================
+ *
+ *                                 4G      5G     6G      7G      8G
+ *                                 |---E---|---B---|---C---|---D---|
+ *                                 +------------Memory-------------+
+ *
+ * The Region 'A'(I/O) can NOT be mapped by M4U; For Region 'B'/'C'/'D', the
+ * bit32 of the CPU physical address always is needed to set, and for Region
+ * 'E', the CPU physical address keep as is.
+ * Additionally, The iommu consumers always use the CPU phyiscal address.
+ */
+#define MTK_IOMMU_4GB_MODE_REMAP_BASE   0x140000000UL
+
 static LIST_HEAD(m4ulist);     /* List all the M4U HWs */
 
 #define for_each_m4u(data)     list_for_each_entry(data, &m4ulist, list)
@@ -226,13 +254,21 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
 
        /* Read error info from registers */
        int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST1);
-       fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
+       if (int_state & F_REG_MMU0_FAULT_MASK) {
+               regval = readl_relaxed(data->base + REG_MMU0_INT_ID);
+               fault_iova = readl_relaxed(data->base + REG_MMU0_FAULT_VA);
+               fault_pa = readl_relaxed(data->base + REG_MMU0_INVLD_PA);
+       } else {
+               regval = readl_relaxed(data->base + REG_MMU1_INT_ID);
+               fault_iova = readl_relaxed(data->base + REG_MMU1_FAULT_VA);
+               fault_pa = readl_relaxed(data->base + REG_MMU1_INVLD_PA);
+       }
        layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT;
        write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
-       fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
-       regval = readl_relaxed(data->base + REG_MMU_INT_ID);
-       fault_larb = F_MMU0_INT_ID_LARB_ID(regval);
-       fault_port = F_MMU0_INT_ID_PORT_ID(regval);
+       fault_larb = F_MMU_INT_ID_LARB_ID(regval);
+       fault_port = F_MMU_INT_ID_PORT_ID(regval);
+
+       fault_larb = data->plat_data->larbid_remap[fault_larb];
 
        if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
                               write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
@@ -264,7 +300,7 @@ static void mtk_iommu_config(struct mtk_iommu_data *data,
        for (i = 0; i < fwspec->num_ids; ++i) {
                larbid = MTK_M4U_TO_LARB(fwspec->ids[i]);
                portid = MTK_M4U_TO_PORT(fwspec->ids[i]);
-               larb_mmu = &data->smi_imu.larb_imu[larbid];
+               larb_mmu = &data->larb_imu[larbid];
 
                dev_dbg(dev, "%s iommu port: %d\n",
                        enable ? "enable" : "disable", portid);
@@ -285,17 +321,15 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom)
        dom->cfg = (struct io_pgtable_cfg) {
                .quirks = IO_PGTABLE_QUIRK_ARM_NS |
                        IO_PGTABLE_QUIRK_NO_PERMS |
-                       IO_PGTABLE_QUIRK_TLBI_ON_MAP,
+                       IO_PGTABLE_QUIRK_TLBI_ON_MAP |
+                       IO_PGTABLE_QUIRK_ARM_MTK_EXT,
                .pgsize_bitmap = mtk_iommu_ops.pgsize_bitmap,
                .ias = 32,
-               .oas = 32,
+               .oas = 34,
                .tlb = &mtk_iommu_flush_ops,
                .iommu_dev = data->dev,
        };
 
-       if (data->enable_4GB)
-               dom->cfg.quirks |= IO_PGTABLE_QUIRK_ARM_MTK_4GB;
-
        dom->iop = alloc_io_pgtable_ops(ARM_V7S, &dom->cfg, data);
        if (!dom->iop) {
                dev_err(data->dev, "Failed to alloc io pgtable\n");
@@ -358,7 +392,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
        /* Update the pgtable base address register of the M4U HW */
        if (!data->m4u_dom) {
                data->m4u_dom = dom;
-               writel(dom->cfg.arm_v7s_cfg.ttbr[0],
+               writel(dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
                       data->base + REG_MMU_PT_BASE_ADDR);
        }
 
@@ -381,12 +415,16 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
                         phys_addr_t paddr, size_t size, int prot)
 {
        struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+       struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
        unsigned long flags;
        int ret;
 
+       /* The "4GB mode" M4U physically can not use the lower remap of Dram. */
+       if (data->enable_4GB)
+               paddr |= BIT_ULL(32);
+
        spin_lock_irqsave(&dom->pgtlock, flags);
-       ret = dom->iop->map(dom->iop, iova, paddr & DMA_BIT_MASK(32),
-                           size, prot);
+       ret = dom->iop->map(dom->iop, iova, paddr, size, prot);
        spin_unlock_irqrestore(&dom->pgtlock, flags);
 
        return ret;
@@ -430,8 +468,8 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
        pa = dom->iop->iova_to_phys(dom->iop, iova);
        spin_unlock_irqrestore(&dom->pgtlock, flags);
 
-       if (data->enable_4GB)
-               pa |= BIT_ULL(32);
+       if (data->enable_4GB && pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE)
+               pa &= ~BIT_ULL(32);
 
        return pa;
 }
@@ -540,9 +578,11 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
                return ret;
        }
 
-       regval = F_MMU_TF_PROTECT_SEL(2, data);
-       if (data->m4u_plat == M4U_MT8173)
-               regval |= F_MMU_PREFETCH_RT_REPLACE_MOD;
+       if (data->plat_data->m4u_plat == M4U_MT8173)
+               regval = F_MMU_PREFETCH_RT_REPLACE_MOD |
+                        F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173;
+       else
+               regval = F_MMU_TF_PROT_TO_PROGRAM_ADDR;
        writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
 
        regval = F_L2_MULIT_HIT_EN |
@@ -562,14 +602,14 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
                F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
        writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
 
-       if (data->m4u_plat == M4U_MT8173)
+       if (data->plat_data->m4u_plat == M4U_MT8173)
                regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
        else
                regval = lower_32_bits(data->protect_base) |
                         upper_32_bits(data->protect_base);
        writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
 
-       if (data->enable_4GB && data->m4u_plat != M4U_MT8173) {
+       if (data->enable_4GB && data->plat_data->has_vld_pa_rng) {
                /*
                 * If 4GB mode is enabled, the validate PA range is from
                 * 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30].
@@ -579,8 +619,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
        }
        writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
 
-       /* It's MISC control register whose default value is ok except mt8173.*/
-       if (data->m4u_plat == M4U_MT8173)
+       if (data->plat_data->reset_axi)
                writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE);
 
        if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
@@ -613,7 +652,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
        if (!data)
                return -ENOMEM;
        data->dev = dev;
-       data->m4u_plat = (enum mtk_iommu_plat)of_device_get_match_data(dev);
+       data->plat_data = of_device_get_match_data(dev);
 
        /* Protect memory. HW will access here while translation fault.*/
        protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);
@@ -623,6 +662,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 
        /* Whether the current dram is over 4GB */
        data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
+       if (!data->plat_data->has_4gb_mode)
+               data->enable_4GB = false;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        data->base = devm_ioremap_resource(dev, res);
@@ -634,15 +675,16 @@ static int mtk_iommu_probe(struct platform_device *pdev)
        if (data->irq < 0)
                return data->irq;
 
-       data->bclk = devm_clk_get(dev, "bclk");
-       if (IS_ERR(data->bclk))
-               return PTR_ERR(data->bclk);
+       if (data->plat_data->has_bclk) {
+               data->bclk = devm_clk_get(dev, "bclk");
+               if (IS_ERR(data->bclk))
+                       return PTR_ERR(data->bclk);
+       }
 
        larb_nr = of_count_phandle_with_args(dev->of_node,
                                             "mediatek,larbs", NULL);
        if (larb_nr < 0)
                return larb_nr;
-       data->smi_imu.larb_nr = larb_nr;
 
        for (i = 0; i < larb_nr; i++) {
                struct device_node *larbnode;
@@ -667,7 +709,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
                        of_node_put(larbnode);
                        return -EPROBE_DEFER;
                }
-               data->smi_imu.larb_imu[id].dev = &plarbdev->dev;
+               data->larb_imu[id].dev = &plarbdev->dev;
 
                component_match_add_release(dev, &match, release_of,
                                            compare_of, larbnode);
@@ -728,6 +770,7 @@ static int __maybe_unused mtk_iommu_suspend(struct device *dev)
        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);
        clk_disable_unprepare(data->bclk);
        return 0;
 }
@@ -736,6 +779,7 @@ static int __maybe_unused mtk_iommu_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->m4u_dom;
        void __iomem *base = data->base;
        int ret;
 
@@ -751,8 +795,9 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
        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);
-       if (data->m4u_dom)
-               writel(data->m4u_dom->cfg.arm_v7s_cfg.ttbr[0],
+       writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
+       if (m4u_dom)
+               writel(m4u_dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
                       base + REG_MMU_PT_BASE_ADDR);
        return 0;
 }
@@ -761,9 +806,32 @@ static const struct dev_pm_ops mtk_iommu_pm_ops = {
        SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
 };
 
+static const struct mtk_iommu_plat_data mt2712_data = {
+       .m4u_plat     = M4U_MT2712,
+       .has_4gb_mode = true,
+       .has_bclk     = true,
+       .has_vld_pa_rng   = true,
+       .larbid_remap = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+};
+
+static const struct mtk_iommu_plat_data mt8173_data = {
+       .m4u_plat     = M4U_MT8173,
+       .has_4gb_mode = true,
+       .has_bclk     = true,
+       .reset_axi    = true,
+       .larbid_remap = {0, 1, 2, 3, 4, 5}, /* Linear mapping. */
+};
+
+static const struct mtk_iommu_plat_data mt8183_data = {
+       .m4u_plat     = M4U_MT8183,
+       .reset_axi    = true,
+       .larbid_remap = {0, 4, 5, 6, 7, 2, 3, 1},
+};
+
 static const struct of_device_id mtk_iommu_of_ids[] = {
-       { .compatible = "mediatek,mt2712-m4u", .data = (void *)M4U_MT2712},
-       { .compatible = "mediatek,mt8173-m4u", .data = (void *)M4U_MT8173},
+       { .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data},
+       { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data},
+       { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data},
        {}
 };