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        | 10 ++++++
 drivers/memory/Makefile       |  1 +
 drivers/memory/mtk-smi-larb.c | 71 +++++++++++++++++++++++++++++++++++++++++++
 include/mtk_smi.h             | 17 +++++++++++
 4 files changed, 99 insertions(+)

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 5f029fd3e70..52b0104e2f0 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -20,6 +20,16 @@ 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_LARB
+       bool "MediaTek SMI local arbiter driver"
+       depends on ARCH_MEDIATEK && DM
+       select MEMORY
+       help
+         This driver ungates the clocks of the SMI local arbiters (larb)
+         found on MediaTek SoCs. A larb gates the access of one multimedia
+         subsystem (display, video codec, camera, MDP) to DRAM, so the larb
+         feeding a DMA master must be ungated before that master can run.
+
 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..ee7bd9a9ea1 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_LARB) += mtk-smi-larb.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-larb.c b/drivers/memory/mtk-smi-larb.c
new file mode 100644
index 00000000000..bb96c7b912b
--- /dev/null
+++ b/drivers/memory/mtk-smi-larb.c
@@ -0,0 +1,71 @@
+// 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 <mtk_smi.h>
+
+/*
+ * 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;
+};
+
+int mtk_smi_larb_enable(struct udevice *dev)
+{
+       struct mtk_smi_larb_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       ret = clk_enable_bulk(&priv->clk_bulk);
+       if (ret)
+               dev_err(dev, "failed to enable clocks: %d\n", ret);
+
+       return ret;
+}
+
+int mtk_smi_larb_disable(struct udevice *dev)
+{
+       struct mtk_smi_larb_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       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..6b17b152cb7
--- /dev/null
+++ b/include/mtk_smi.h
@@ -0,0 +1,17 @@
+/* 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;
+
+int mtk_smi_larb_enable(struct udevice *dev);
+int mtk_smi_larb_disable(struct udevice *dev);
+
+#endif /* _MTK_SMI_H */

-- 
2.55.0

Reply via email to