The SMI local arbiters (larbs) gate a multimedia subsystem's access to
DRAM. On the MT8188 the display data path feeds through the VDO1 larbs
(larb2 and larb3), whose clocks must be ungated for the HDMI pipeline to
reach the framebuffer.

There is no dedicated SMI larb driver upstream, as Linux handles the
larbs through its SMI/IOMMU framework (drivers/memory/mtk-smi.c). Add a
minimal U-Boot driver that ungates the clocks of one larb, and export
mtk_smi_larb_enable() and mtk_smi_larb_disable() so that the DMA master
behind a larb can tie it to its own lifetime.

The larbs are not video devices: they serve every multimedia master
(display, video codec, camera, MDP), so the driver lives in
drivers/memory with its own Kconfig symbol rather than being built as
part of one master's driver. Every "mediatek,mt8188-smi-larb" node
binds, which is cheap, and a larb is only probed once a master asks
for it.

Signed-off-by: Julien Stephan <[email protected]>
---
 drivers/memory/Kconfig   |  9 +++++
 drivers/memory/Makefile  |  1 +
 drivers/memory/mtk-smi.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/mtk_smi.h        | 37 ++++++++++++++++++++
 4 files changed, 136 insertions(+)

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 5f029fd3e70..a3b7c722070 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -20,6 +20,15 @@ config ATMEL_EBI
          driver. Doesn't provide an access to EBI controller. Select
          this option to enable the NAND flash controller driver
 
+config MTK_SMI
+       bool "MediaTek SoC Memory Controller driver"
+       depends on ARCH_MEDIATEK && DM
+       select MEMORY
+       help
+         This driver is for the Memory Controller module in MediaTek SoCs,
+         mainly help enable/disable iommu and control the power domain and
+         clocks for each local arbiter.
+
 config SANDBOX_MEMORY
        bool "Enable Sandbox Memory Controller driver"
        depends on SANDBOX && MEMORY
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index d5f5b073672..f33d8acd5b2 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -1,6 +1,7 @@
 
 obj-$(CONFIG_ATMEL_EBI) += atmel_ebi.o
 obj-$(CONFIG_MEMORY) += memory-uclass.o
+obj-$(CONFIG_MTK_SMI) += mtk-smi.o
 obj-$(CONFIG_SANDBOX_MEMORY) += memory-sandbox.o
 obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
 obj-$(CONFIG_STM32_OMM) += stm32_omm.o
diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
new file mode 100644
index 00000000000..b90f5cc135f
--- /dev/null
+++ b/drivers/memory/mtk-smi.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * MediaTek SMI local arbiter (larb) driver
+ *
+ * Copyright (c) 2026 BayLibre, SAS.
+ * Author: Julien Stephan <[email protected]>
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <errno.h>
+#include <mtk_smi.h>
+
+/**
+ * struct mtk_smi_larb_priv - private data of an SMI larb
+ * @clk_bulk: clocks of the larb
+ * @enable_count: number of DMA masters that enabled the larb
+ *
+ * The SMI local arbiters gate a multimedia subsystem's access to DRAM. Linux
+ * handles them as part of its SMI/IOMMU framework (drivers/memory/mtk-smi.c);
+ * U-Boot has no such framework, so this minimal driver only ungates the larb
+ * clocks on behalf of the DMA master sitting behind it.
+ */
+struct mtk_smi_larb_priv {
+       struct clk_bulk clk_bulk;
+       unsigned int enable_count;
+};
+
+int mtk_smi_larb_enable(struct udevice *dev)
+{
+       struct mtk_smi_larb_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       /* several DMA masters can sit behind the same larb */
+       if (priv->enable_count++)
+               return 0;
+
+       ret = clk_enable_bulk(&priv->clk_bulk);
+       if (ret) {
+               dev_err(dev, "failed to enable clocks: %d\n", ret);
+               priv->enable_count--;
+       }
+
+       return ret;
+}
+
+int mtk_smi_larb_disable(struct udevice *dev)
+{
+       struct mtk_smi_larb_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       if (!priv->enable_count)
+               return -EINVAL;
+
+       if (--priv->enable_count)
+               return 0;
+
+       ret = clk_disable_bulk(&priv->clk_bulk);
+       if (ret)
+               dev_err(dev, "failed to disable clocks: %d\n", ret);
+
+       return ret;
+}
+
+static int mtk_smi_larb_probe(struct udevice *dev)
+{
+       struct mtk_smi_larb_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       ret = clk_get_bulk(dev, &priv->clk_bulk);
+       if (ret)
+               dev_err(dev, "failed to get clocks: %d\n", ret);
+
+       return ret;
+}
+
+static const struct udevice_id mtk_smi_larb_ids[] = {
+       { .compatible = "mediatek,mt8188-smi-larb" },
+       { }
+};
+
+U_BOOT_DRIVER(mtk_smi_larb) = {
+       .name      = "mtk_smi_larb",
+       .id        = UCLASS_MEMORY,
+       .of_match  = mtk_smi_larb_ids,
+       .probe     = mtk_smi_larb_probe,
+       .priv_auto = sizeof(struct mtk_smi_larb_priv),
+};
diff --git a/include/mtk_smi.h b/include/mtk_smi.h
new file mode 100644
index 00000000000..b0166b37538
--- /dev/null
+++ b/include/mtk_smi.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * MediaTek SMI local arbiter (larb) API
+ *
+ * Copyright (c) 2026 BayLibre, SAS.
+ * Author: Julien Stephan <[email protected]>
+ */
+
+#ifndef _MTK_SMI_H
+#define _MTK_SMI_H
+
+struct udevice;
+
+/**
+ * mtk_smi_larb_enable() - ungate an SMI local arbiter
+ * @dev: larb device
+ *
+ * Enable the clocks of the larb so that the DMA master behind it can reach
+ * DRAM. Calls are refcounted, so several masters can share one larb.
+ *
+ * Return: 0 on success, or a negative error code
+ */
+int mtk_smi_larb_enable(struct udevice *dev);
+
+/**
+ * mtk_smi_larb_disable() - gate an SMI local arbiter
+ * @dev: larb device
+ *
+ * Drop one reference taken by mtk_smi_larb_enable(), and disable the larb
+ * clocks when it was the last one.
+ *
+ * Return: 0 on success, -EINVAL if the larb is not enabled, or another
+ * negative error code
+ */
+int mtk_smi_larb_disable(struct udevice *dev);
+
+#endif /* _MTK_SMI_H */

-- 
2.55.0

Reply via email to