* [PATCH 1/3] dt-bindings: iommu: mediatek: add mt6572
2026-09-09 14:14 [PATCH 0/3] iommu/mediatek-v1: fix the driver + mt6572 support Roman Vivchar via B4 Relay
@ 2026-09-09 14:14 ` Roman Vivchar via B4 Relay
2026-09-11 7:27 ` Krzysztof Kozlowski
2026-09-09 14:14 ` [PATCH 2/3] iommu/mediatek-v1: fix IOMMU device binding Roman Vivchar via B4 Relay
2026-09-09 14:14 ` [PATCH 3/3] iommu/mediatek-v1: add mt6572 support Roman Vivchar via B4 Relay
2 siblings, 1 reply; 5+ messages in thread
From: Roman Vivchar via B4 Relay @ 2026-09-09 14:14 UTC (permalink / raw)
To: Yong Wu, Joerg Roedel (AMD), Will Deacon, Robin Murphy,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: iommu, linux-mediatek, devicetree, linux-kernel, linux-arm-kernel,
Roman Vivchar
From: Roman Vivchar <rva333@protonmail.com>
Add compatible string and header file for mt6572 IOMMU support.
Signed-off-by: Roman Vivchar <rva333@protonmail.com>
---
.../devicetree/bindings/iommu/mediatek,iommu.yaml | 3 +++
.../memory/mediatek,mt6572-memory-port.h | 26 ++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
index 79c573c47b08..d0ac4bd71911 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
@@ -72,6 +72,7 @@ properties:
- enum:
- mediatek,mt2701-m4u # generation one
- mediatek,mt2712-m4u # generation two
+ - mediatek,mt6572-m4u # generation one
- mediatek,mt6779-m4u # generation two
- mediatek,mt6795-m4u # generation two
- mediatek,mt6893-iommu-mm # generation two
@@ -134,6 +135,7 @@ properties:
dt-binding/memory/mediatek,mt8189-memory-port.h for mt8189,
dt-binding/memory/mt2701-larb-port.h for mt2701 and mt7623,
dt-binding/memory/mt2712-larb-port.h for mt2712,
+ dt-binding/memory/mediatek,mt6572-memory-port.h for mt6572,
dt-binding/memory/mt6779-larb-port.h for mt6779,
dt-binding/memory/mt6795-larb-port.h for mt6795,
dt-binding/memory/mediatek,mt6893-memory-port.h for mt6893,
@@ -162,6 +164,7 @@ allOf:
enum:
- mediatek,mt2701-m4u
- mediatek,mt2712-m4u
+ - mediatek,mt6572-m4u
- mediatek,mt6795-m4u
- mediatek,mt6893-iommu-mm
- mediatek,mt8173-m4u
diff --git a/include/dt-bindings/memory/mediatek,mt6572-memory-port.h b/include/dt-bindings/memory/mediatek,mt6572-memory-port.h
new file mode 100644
index 000000000000..6f8ddc98f1b1
--- /dev/null
+++ b/include/dt-bindings/memory/mediatek,mt6572-memory-port.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2026 Roman Vivchar <rva333@protonmail.com>
+ */
+
+#ifndef _DT_BINDINGS_MEMORY_MT6572_MEMORY_PORT_H_
+#define _DT_BINDINGS_MEMORY_MT6572_MEMORY_PORT_H_
+
+#define M4U_PORT_DISP_OVL 0
+#define M4U_PORT_DISP_RDMA 1
+#define M4U_PORT_DISP_WDMA 2
+#define M4U_PORT_DISP_DBI 3
+#define M4U_PORT_CAM_WDMA 4
+#define M4U_PORT_CMDQ 5
+#define M4U_PORT_VENC_BSDMA_VDEC_POST0 6
+#define M4U_PORT_MDP_RDMA 7
+#define M4U_PORT_MDP_WDMA 8
+#define M4U_PORT_MDP_ROTO 9
+#define M4U_PORT_MDP_ROTCO 10
+#define M4U_PORT_MDP_ROTVO 11
+#define M4U_PORT_VENC_MVQP 12
+#define M4U_PORT_VENC_MC 13
+#define M4U_PORT_VENC_CDMA_VDEC_CDMA 14
+#define M4U_PORT_VENC_REC_VDEC_WDMA 15
+
+#endif
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH 1/3] dt-bindings: iommu: mediatek: add mt6572
2026-09-09 14:14 ` [PATCH 1/3] dt-bindings: iommu: mediatek: add mt6572 Roman Vivchar via B4 Relay
@ 2026-09-11 7:27 ` Krzysztof Kozlowski
0 siblings, 0 replies; 5+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-11 7:27 UTC (permalink / raw)
To: Roman Vivchar
Cc: Yong Wu, Joerg Roedel (AMD), Will Deacon, Robin Murphy,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, iommu, linux-mediatek, devicetree,
linux-kernel, linux-arm-kernel
On Wed, Sep 09, 2026 at 05:14:05PM +0300, Roman Vivchar wrote:
> Add compatible string and header file for mt6572 IOMMU support.
>
> Signed-off-by: Roman Vivchar <rva333@protonmail.com>
> ---
> .../devicetree/bindings/iommu/mediatek,iommu.yaml | 3 +++
> .../memory/mediatek,mt6572-memory-port.h | 26 ++++++++++++++++++++++
> 2 files changed, 29 insertions(+)
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/3] iommu/mediatek-v1: fix IOMMU device binding
2026-09-09 14:14 [PATCH 0/3] iommu/mediatek-v1: fix the driver + mt6572 support Roman Vivchar via B4 Relay
2026-09-09 14:14 ` [PATCH 1/3] dt-bindings: iommu: mediatek: add mt6572 Roman Vivchar via B4 Relay
@ 2026-09-09 14:14 ` Roman Vivchar via B4 Relay
2026-09-09 14:14 ` [PATCH 3/3] iommu/mediatek-v1: add mt6572 support Roman Vivchar via B4 Relay
2 siblings, 0 replies; 5+ messages in thread
From: Roman Vivchar via B4 Relay @ 2026-09-09 14:14 UTC (permalink / raw)
To: Yong Wu, Joerg Roedel (AMD), Will Deacon, Robin Murphy,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: iommu, linux-mediatek, devicetree, linux-kernel, linux-arm-kernel,
Roman Vivchar, stable
From: Roman Vivchar <rva333@protonmail.com>
Currently the driver silently fails to bind devices and DRM subsystem
(which is the primary IOMMU user on MediaTek SoCs) falls back to PA mode.
Fix this by providing of_xlate callback, which lets the driver actually
bind devices and use VA mode.
The fix can be verified by reading overlay engine input address.
Before:
~ # devmem 0x14007040 32
0xBB900000
After:
~ # devmem 0x14007040 32
0x00000000
Fixes: b17336c55d89 ("iommu/mediatek: add support for mtk iommu generation one HW")
Cc: stable@vger.kernel.org
Signed-off-by: Roman Vivchar <rva333@protonmail.com>
---
Untested on mt2701.
---
drivers/iommu/mtk_iommu_v1.c | 86 ++++++++++++++++++++------------------------
1 file changed, 39 insertions(+), 47 deletions(-)
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index ac97dd2868d4..72355f41c36a 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -413,38 +413,10 @@ static const struct iommu_ops mtk_iommu_v1_ops;
* MTK generation one iommu HW only support one iommu domain, and all the client
* sharing the same iova address space.
*/
-static int mtk_iommu_v1_create_mapping(struct device *dev,
- const struct of_phandle_args *args)
+static int mtk_iommu_v1_create_mapping(struct device *dev)
{
struct mtk_iommu_v1_data *data;
- struct platform_device *m4updev;
struct dma_iommu_mapping *mtk_mapping;
- int ret;
-
- if (args->args_count != 1) {
- dev_err(dev, "invalid #iommu-cells(%d) property for IOMMU\n",
- args->args_count);
- return -EINVAL;
- }
-
- ret = iommu_fwspec_init(dev, of_fwnode_handle(args->np));
- if (ret)
- return ret;
-
- if (!dev_iommu_priv_get(dev)) {
- /* Get the m4u device */
- m4updev = of_find_device_by_node(args->np);
- if (WARN_ON(!m4updev))
- return -EINVAL;
-
- dev_iommu_priv_set(dev, platform_get_drvdata(m4updev));
-
- put_device(&m4updev->dev);
- }
-
- ret = iommu_fwspec_add_ids(dev, args->args, 1);
- if (ret)
- return ret;
data = dev_iommu_priv_get(dev);
mtk_mapping = data->mapping;
@@ -462,27 +434,12 @@ static int mtk_iommu_v1_create_mapping(struct device *dev,
static struct iommu_device *mtk_iommu_v1_probe_device(struct device *dev)
{
- struct iommu_fwspec *fwspec = NULL;
- struct of_phandle_args iommu_spec;
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct mtk_iommu_v1_data *data;
- int err, idx = 0, larbid, larbidx;
+ int idx, larbid, larbidx;
struct device_link *link;
struct device *larbdev;
- while (!of_parse_phandle_with_args(dev->of_node, "iommus",
- "#iommu-cells",
- idx, &iommu_spec)) {
-
- err = mtk_iommu_v1_create_mapping(dev, &iommu_spec);
- of_node_put(iommu_spec.np);
- if (err)
- return ERR_PTR(err);
-
- /* dev->iommu_fwspec might have changed */
- fwspec = dev_iommu_fwspec_get(dev);
- idx++;
- }
-
if (!fwspec)
return ERR_PTR(-ENODEV);
@@ -519,9 +476,15 @@ static void mtk_iommu_v1_probe_finalize(struct device *dev)
__maybe_unused struct mtk_iommu_v1_data *data = dev_iommu_priv_get(dev);
int err;
+ err = mtk_iommu_v1_create_mapping(dev);
+ if (err) {
+ dev_err(dev, "Can't create IOMMU mapping - DMA-OPS will not work\n");
+ return;
+ }
+
err = arm_iommu_attach_device(dev, data->mapping);
if (err)
- dev_err(dev, "Can't create IOMMU mapping - DMA-OPS will not work\n");
+ dev_err(dev, "Can't attach to IOMMU mapping - DMA-OPS will not work\n");
}
static void mtk_iommu_v1_release_device(struct device *dev)
@@ -537,6 +500,34 @@ static void mtk_iommu_v1_release_device(struct device *dev)
device_link_remove(dev, larbdev);
}
+static int mtk_iommu_v1_of_xlate(struct device *dev,
+ const struct of_phandle_args *args)
+{
+ struct platform_device *m4updev;
+ int ret;
+
+ if (args->args_count != 1) {
+ dev_err(dev, "invalid #iommu-cells(%d) property for IOMMU\n",
+ args->args_count);
+ return -EINVAL;
+ }
+
+ ret = iommu_fwspec_init(dev, of_fwnode_handle(args->np));
+ if (ret)
+ return ret;
+
+ if (!dev_iommu_priv_get(dev)) {
+ m4updev = of_find_device_by_node(args->np);
+ if (WARN_ON(!m4updev))
+ return -EINVAL;
+
+ dev_iommu_priv_set(dev, platform_get_drvdata(m4updev));
+ put_device(&m4updev->dev);
+ }
+
+ return iommu_fwspec_add_ids(dev, args->args, 1);
+}
+
static int mtk_iommu_v1_hw_init(const struct mtk_iommu_v1_data *data)
{
u32 regval;
@@ -585,6 +576,7 @@ static const struct iommu_ops mtk_iommu_v1_ops = {
.probe_finalize = mtk_iommu_v1_probe_finalize,
.release_device = mtk_iommu_v1_release_device,
.device_group = generic_device_group,
+ .of_xlate = mtk_iommu_v1_of_xlate,
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
.attach_dev = mtk_iommu_v1_attach_device,
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 3/3] iommu/mediatek-v1: add mt6572 support
2026-09-09 14:14 [PATCH 0/3] iommu/mediatek-v1: fix the driver + mt6572 support Roman Vivchar via B4 Relay
2026-09-09 14:14 ` [PATCH 1/3] dt-bindings: iommu: mediatek: add mt6572 Roman Vivchar via B4 Relay
2026-09-09 14:14 ` [PATCH 2/3] iommu/mediatek-v1: fix IOMMU device binding Roman Vivchar via B4 Relay
@ 2026-09-09 14:14 ` Roman Vivchar via B4 Relay
2 siblings, 0 replies; 5+ messages in thread
From: Roman Vivchar via B4 Relay @ 2026-09-09 14:14 UTC (permalink / raw)
To: Yong Wu, Joerg Roedel (AMD), Will Deacon, Robin Murphy,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: iommu, linux-mediatek, devicetree, linux-kernel, linux-arm-kernel,
Roman Vivchar
From: Roman Vivchar <rva333@protonmail.com>
mt6572 SoC utilizes an earlier version of the IOMMU, that shares the
same v1 architecture, but has minor hardware differences compared to
mt2701.
Introduce mtk_iommu_type to distinguish between mt2701 and mt6572
variant and apply the necessary logic.
Finally, add a platform data for the mt6572 SoC.
Signed-off-by: Roman Vivchar <rva333@protonmail.com>
---
Based on my downstream findings, this change may also support mt6582 SoC,
but I don't have the hardware to test if it actually works.
---
drivers/iommu/mtk_iommu_v1.c | 72 +++++++++++++++++++++++++++++++++-----------
1 file changed, 55 insertions(+), 17 deletions(-)
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 72355f41c36a..b6f547b100d1 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -7,6 +7,7 @@
*
* Based on driver/iommu/mtk_iommu.c
*/
+#include <linux/bitfield.h>
#include <linux/bug.h>
#include <linux/clk.h>
#include <linux/component.h>
@@ -85,6 +86,13 @@ struct dma_iommu_mapping {
#define F_DESC_NONSEC BIT(3)
#define MT2701_M4U_TF_LARB(TF) (6 - (((TF) >> 13) & 0x7))
#define MT2701_M4U_TF_PORT(TF) (((TF) >> 8) & 0xF)
+
+#define MT6572_MMU_INT_ID_PORT_ID GENMASK(12, 8)
+#define MT6572_MMU_INT_ID_LARB_ID GENMASK(14, 13)
+
+#define MT6572_M4U_TF_PORT(TF) FIELD_GET(MT6572_MMU_INT_ID_PORT_ID, TF)
+#define MT6572_M4U_TF_LARB(TF) (FIELD_GET(MT6572_MMU_INT_ID_LARB_ID, TF) - 1)
+
/* MTK generation one iommu HW only support 4K size mapping */
#define MT2701_IOMMU_PAGE_SHIFT 12
#define MT2701_IOMMU_PAGE_SIZE (1UL << MT2701_IOMMU_PAGE_SHIFT)
@@ -96,6 +104,11 @@ struct dma_iommu_mapping {
*/
#define M2701_IOMMU_PGT_SIZE SZ_4M
+enum mtk_iommu_type {
+ MTK_IOMMU_MT6572,
+ MTK_IOMMU_V1,
+};
+
struct mtk_iommu_v1_suspend_reg {
u32 standard_axi_mode;
u32 dcm_dis;
@@ -116,6 +129,8 @@ struct mtk_iommu_v1_data {
struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX];
struct mtk_iommu_v1_suspend_reg reg;
+
+ enum mtk_iommu_type type;
};
struct mtk_iommu_v1_domain {
@@ -170,8 +185,12 @@ static inline int mt2701_m4u_to_port(int id)
static void mtk_iommu_v1_tlb_flush_all(struct mtk_iommu_v1_data *data)
{
- writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
- data->base + REG_MMU_INV_SEL);
+ u32 val = F_INVLD_EN0;
+
+ if (data->type == MTK_IOMMU_V1)
+ val |= F_INVLD_EN1;
+
+ writel_relaxed(val, data->base + REG_MMU_INV_SEL);
writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
wmb(); /* Make sure the tlb flush all done */
}
@@ -180,25 +199,33 @@ static void mtk_iommu_v1_tlb_flush_range(struct mtk_iommu_v1_data *data,
unsigned long iova, size_t size)
{
int ret;
- u32 tmp;
+ u32 tmp, val = F_INVLD_EN0;
- writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
- data->base + REG_MMU_INV_SEL);
+ if (data->type == MTK_IOMMU_V1)
+ val |= F_INVLD_EN1;
+
+ writel_relaxed(val, data->base + REG_MMU_INV_SEL);
writel_relaxed(iova & F_MMU_FAULT_VA_MSK,
data->base + REG_MMU_INVLD_START_A);
writel_relaxed((iova + size - 1) & F_MMU_FAULT_VA_MSK,
data->base + REG_MMU_INVLD_END_A);
writel_relaxed(F_MMU_INV_RANGE, data->base + REG_MMU_INVALIDATE);
- ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE,
- tmp, tmp != 0, 10, 100000);
- if (ret) {
- dev_warn(data->dev,
- "Partial TLB flush timed out, falling back to full flush\n");
- mtk_iommu_v1_tlb_flush_all(data);
+ if (data->type == MTK_IOMMU_V1) {
+ ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE,
+ tmp, tmp != 0, 10, 100000);
+ if (ret) {
+ dev_warn(data->dev,
+ "Partial TLB flush timed out, falling back to full flush\n");
+ mtk_iommu_v1_tlb_flush_all(data);
+ }
+
+ /* Clear the CPE status */
+ writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
+ } else {
+ /* Make sure the TLB flush is done */
+ wmb();
}
- /* Clear the CPE status */
- writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
}
static irqreturn_t mtk_iommu_v1_isr(int irq, void *dev_id)
@@ -215,8 +242,14 @@ static irqreturn_t mtk_iommu_v1_isr(int irq, void *dev_id)
fault_iova &= F_MMU_FAULT_VA_MSK;
fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
regval = readl_relaxed(data->base + REG_MMU_INT_ID);
- fault_larb = MT2701_M4U_TF_LARB(regval);
- fault_port = MT2701_M4U_TF_PORT(regval);
+
+ if (data->type == MTK_IOMMU_V1) {
+ fault_larb = MT2701_M4U_TF_LARB(regval);
+ fault_port = MT2701_M4U_TF_PORT(regval);
+ } else {
+ fault_larb = MT6572_M4U_TF_LARB(regval);
+ fault_port = MT6572_M4U_TF_PORT(regval);
+ }
/*
* MTK v1 iommu HW could not determine whether the fault is read or
@@ -539,7 +572,10 @@ static int mtk_iommu_v1_hw_init(const struct mtk_iommu_v1_data *data)
return ret;
}
- regval = F_MMU_CTRL_COHERENT_EN | F_MMU_TF_PROTECT_SEL(2);
+ regval = F_MMU_TF_PROTECT_SEL(2);
+ if (data->type == MTK_IOMMU_V1)
+ regval |= F_MMU_CTRL_COHERENT_EN;
+
writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
regval = F_INT_TRANSLATION_FAULT |
@@ -588,7 +624,8 @@ static const struct iommu_ops mtk_iommu_v1_ops = {
};
static const struct of_device_id mtk_iommu_v1_of_ids[] = {
- { .compatible = "mediatek,mt2701-m4u", },
+ { .compatible = "mediatek,mt2701-m4u", .data = (void *)MTK_IOMMU_V1 },
+ { .compatible = "mediatek,mt6572-m4u", .data = (void *)MTK_IOMMU_MT6572 },
{}
};
MODULE_DEVICE_TABLE(of, mtk_iommu_v1_of_ids);
@@ -612,6 +649,7 @@ static int mtk_iommu_v1_probe(struct platform_device *pdev)
return -ENOMEM;
data->dev = dev;
+ data->type = (enum mtk_iommu_type)(uintptr_t)of_device_get_match_data(dev);
/* Protect memory. HW will access here while translation fault.*/
protect = devm_kcalloc(dev, 2, MTK_PROTECT_PA_ALIGN,
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread