Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 07/15] clk: mediatek: Add MT8189 topckgen clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
	Edward-JW Yang, Richard Cochran
  Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>

Add support for the MT8189 topckgen clock controller, which provides
muxes and dividers for clock selection in other IP blocks.

Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
 drivers/clk/mediatek/Makefile              |    2 +-
 drivers/clk/mediatek/clk-mt8189-topckgen.c | 1024 ++++++++++++++++++++++++++++
 2 files changed, 1025 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 66577ccb9b93..9d3d2983bfb2 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -123,7 +123,7 @@ obj-$(CONFIG_COMMON_CLK_MT8188_VDOSYS) += clk-mt8188-vdo0.o clk-mt8188-vdo1.o
 obj-$(CONFIG_COMMON_CLK_MT8188_VENCSYS) += clk-mt8188-venc.o
 obj-$(CONFIG_COMMON_CLK_MT8188_VPPSYS) += clk-mt8188-vpp0.o clk-mt8188-vpp1.o
 obj-$(CONFIG_COMMON_CLK_MT8188_WPESYS) += clk-mt8188-wpe.o
-obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o
+obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o clk-mt8189-topckgen.o
 obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
 obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
 obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-topckgen.c b/drivers/clk/mediatek/clk-mt8189-topckgen.c
new file mode 100644
index 000000000000..62d292f5b8b8
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-topckgen.c
@@ -0,0 +1,1024 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ *                    Qiqi Wang <qiqi.wang@mediatek.com>
+ *                    Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ *                    AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ *                    Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+#include "clk-mux.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+
+static DEFINE_SPINLOCK(mt8189_clk_lock);
+
+static const struct mtk_fixed_factor top_divs[] = {
+	FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3),
+	FACTOR(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4),
+	FACTOR(CLK_TOP_MAINPLL_D4_D2, "mainpll_d4_d2", "mainpll", 1, 8),
+	FACTOR(CLK_TOP_MAINPLL_D4_D4, "mainpll_d4_d4", "mainpll", 1, 16),
+	FACTOR(CLK_TOP_MAINPLL_D4_D8, "mainpll_d4_d8", "mainpll", 43, 1375),
+	FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5),
+	FACTOR(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll", 1, 10),
+	FACTOR(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll", 1, 20),
+	FACTOR(CLK_TOP_MAINPLL_D5_D8, "mainpll_d5_d8", "mainpll", 1, 40),
+	FACTOR(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6),
+	FACTOR(CLK_TOP_MAINPLL_D6_D2, "mainpll_d6_d2", "mainpll", 1, 12),
+	FACTOR(CLK_TOP_MAINPLL_D6_D4, "mainpll_d6_d4", "mainpll", 1, 24),
+	FACTOR(CLK_TOP_MAINPLL_D6_D8, "mainpll_d6_d8", "mainpll", 1, 48),
+	FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7),
+	FACTOR(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll", 1, 14),
+	FACTOR(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll", 1, 28),
+	FACTOR(CLK_TOP_MAINPLL_D7_D8, "mainpll_d7_d8", "mainpll", 1, 56),
+	FACTOR(CLK_TOP_MAINPLL_D9, "mainpll_d9", "mainpll", 1, 9),
+	FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+	FACTOR(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL_D4_D2, "univpll_d4_d2", "univpll", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL_D4_D4, "univpll_d4_d4", "univpll", 1, 16),
+	FACTOR(CLK_TOP_UNIVPLL_D4_D8, "univpll_d4_d8", "univpll", 1, 32),
+	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+	FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll", 1, 10),
+	FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll", 1, 20),
+	FACTOR(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6),
+	FACTOR(CLK_TOP_UNIVPLL_D6_D2, "univpll_d6_d2", "univpll", 1, 12),
+	FACTOR(CLK_TOP_UNIVPLL_D6_D4, "univpll_d6_d4", "univpll", 1, 24),
+	FACTOR(CLK_TOP_UNIVPLL_D6_D8, "univpll_d6_d8", "univpll", 1, 48),
+	FACTOR(CLK_TOP_UNIVPLL_D6_D16, "univpll_d6_d16", "univpll", 1, 96),
+	FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+	FACTOR(CLK_TOP_UNIVPLL_D7_D2, "univpll_d7_d2", "univpll", 1, 14),
+	FACTOR(CLK_TOP_UNIVPLL_D7_D3, "univpll_d7_d3", "univpll", 1, 21),
+	FACTOR(CLK_TOP_LVDSTX_DG_CTS, "lvdstx_dg_cts", "univpll", 1, 21),
+	FACTOR(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univpll", 1, 13),
+	FACTOR(CLK_TOP_UNIVPLL_192M_D2, "univpll_192m_d2", "univpll", 1, 26),
+	FACTOR(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll", 1, 52),
+	FACTOR(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll", 1, 104),
+	FACTOR(CLK_TOP_UNIVPLL_192M_D10, "univpll_192m_d10", "univpll", 1, 130),
+	FACTOR(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll", 1, 208),
+	FACTOR(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll", 1, 416),
+	FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1, 2),
+	FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4),
+	FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1, 8),
+	FACTOR(CLK_TOP_APLL1_D3, "apll1_d3", "apll1", 1, 3),
+	FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2),
+	FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4),
+	FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2", 1, 8),
+	FACTOR(CLK_TOP_APLL2_D3, "apll2_d3", "apll2", 1, 3),
+	FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, 4),
+	FACTOR(CLK_TOP_MMPLL_D4_D2, "mmpll_d4_d2", "mmpll", 1, 8),
+	FACTOR(CLK_TOP_MMPLL_D4_D4, "mmpll_d4_d4", "mmpll", 1, 16),
+	FACTOR(CLK_TOP_VPLL_DPIX, "vpll_dpix", "mmpll", 1, 16),
+	FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
+	FACTOR(CLK_TOP_MMPLL_D5_D2, "mmpll_d5_d2", "mmpll", 1, 10),
+	FACTOR(CLK_TOP_MMPLL_D5_D4, "mmpll_d5_d4", "mmpll", 1, 20),
+	FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll", 1, 6),
+	FACTOR(CLK_TOP_MMPLL_D6_D2, "mmpll_d6_d2", "mmpll", 1, 12),
+	FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
+	FACTOR(CLK_TOP_MMPLL_D9, "mmpll_d9", "mmpll", 1, 9),
+	FACTOR(CLK_TOP_TVDPLL1_D2, "tvdpll1_d2", "tvdpll1", 1, 2),
+	FACTOR(CLK_TOP_TVDPLL1_D4, "tvdpll1_d4", "tvdpll1", 1, 4),
+	FACTOR(CLK_TOP_TVDPLL1_D8, "tvdpll1_d8", "tvdpll1", 1, 8),
+	FACTOR(CLK_TOP_TVDPLL1_D16, "tvdpll1_d16", "tvdpll1", 92, 1473),
+	FACTOR(CLK_TOP_TVDPLL2_D2, "tvdpll2_d2", "tvdpll2", 1, 2),
+	FACTOR(CLK_TOP_TVDPLL2_D4, "tvdpll2_d4", "tvdpll2", 1, 4),
+	FACTOR(CLK_TOP_TVDPLL2_D8, "tvdpll2_d8", "tvdpll2", 1, 8),
+	FACTOR(CLK_TOP_TVDPLL2_D16, "tvdpll2_d16", "tvdpll2", 92, 1473),
+	FACTOR(CLK_TOP_ETHPLL_D2, "ethpll_d2", "ethpll", 1, 2),
+	FACTOR(CLK_TOP_ETHPLL_D8, "ethpll_d8", "ethpll", 1, 8),
+	FACTOR(CLK_TOP_ETHPLL_D10, "ethpll_d10", "ethpll", 1, 10),
+	FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+	FACTOR(CLK_TOP_UFSPLL_D2, "ufspll_d2", "ufspll", 1, 2),
+	FACTOR(CLK_TOP_F26M_CK_D2, "f26m_d2", "clk26m", 1, 2),
+	FACTOR(CLK_TOP_OSC_D2, "osc_d2", "ulposc", 1, 2),
+	FACTOR(CLK_TOP_OSC_D4, "osc_d4", "ulposc", 1, 4),
+	FACTOR(CLK_TOP_OSC_D8, "osc_d8", "ulposc", 1, 8),
+	FACTOR(CLK_TOP_OSC_D16, "osc_d16", "ulposc", 61, 973),
+	FACTOR(CLK_TOP_OSC_D3, "osc_d3", "ulposc", 1, 3),
+	FACTOR(CLK_TOP_OSC_D7, "osc_d7", "ulposc", 1, 7),
+	FACTOR(CLK_TOP_OSC_D10, "osc_d10", "ulposc", 1, 10),
+	FACTOR(CLK_TOP_OSC_D20, "osc_d20", "ulposc", 1, 20),
+};
+
+static const char * const ap2conn_host_parents[] = {
+	"clk26m",
+	"mainpll_d7_d4"
+};
+
+static const char * const apll_m_parents[] = {
+	"aud_1_sel",
+	"aud_2_sel"
+};
+
+static const char * const aud_1_parents[] = {
+	"clk26m",
+	"apll1"
+};
+
+static const char * const aud_2_parents[] = {
+	"clk26m",
+	"apll2"
+};
+
+static const char * const mfg_sel_mfgpll_parents[] = {
+	"mfg_ref_sel",
+	"mfgpll"
+};
+
+static const char * const pwm_parents[] = {
+	"clk26m",
+	"univpll_d4_d8"
+};
+
+static const char * const snps_eth_250m_parents[] = {
+	"clk26m",
+	"ethpll_d2"
+};
+
+static const char * const snps_eth_50m_rmii_parents[] = {
+	"clk26m",
+	"ethpll_d10"
+};
+
+static const char * const uart_parents[] = {
+	"clk26m",
+	"univpll_d6_d8"
+};
+
+static const char * const atb_parents[] = {
+	"clk26m",
+	"mainpll_d4_d2",
+	"mainpll_d5_d2"
+};
+
+static const char * const aud_intbus_parents[] = {
+	"clk26m",
+	"mainpll_d4_d4",
+	"mainpll_d7_d4"
+};
+
+static const char * const msdc5hclk_parents[] = {
+	"clk26m",
+	"mainpll_d4_d2",
+	"mainpll_d6_d2"
+};
+
+static const char * const pcie_mac_tl_parents[] = {
+	"clk26m",
+	"mainpll_d4_d4",
+	"univpll_d5_d4"
+};
+
+static const char * const pll_dpix_parents[] = {
+	"clk26m",
+	"vpll_dpix",
+	"mmpll_d4_d4"
+};
+
+static const char * const usb_parents[] = {
+	"clk26m",
+	"univpll_d5_d4",
+	"univpll_d6_d4"
+};
+
+static const char * const vdstx_dg_cts_parents[] = {
+	"clk26m",
+	"lvdstx_dg_cts",
+	"univpll_d7_d3"
+};
+
+static const char * const audio_h_parents[] = {
+	"clk26m",
+	"univpll_d7_d2",
+	"apll1",
+	"apll2"
+};
+
+static const char * const aud_engen1_parents[] = {
+	"clk26m",
+	"apll1_d2",
+	"apll1_d4",
+	"apll1_d8"
+};
+
+static const char * const aud_engen2_parents[] = {
+	"clk26m",
+	"apll2_d2",
+	"apll2_d4",
+	"apll2_d8"
+};
+
+static const char * const axi_peri_parents[] = {
+	"clk26m",
+	"mainpll_d4_d4",
+	"mainpll_d7_d2",
+	"osc_d4"
+};
+
+static const char * const axi_u_parents[] = {
+	"clk26m",
+	"mainpll_d4_d8",
+	"mainpll_d7_d4",
+	"osc_d8"
+};
+
+static const char * const camtm_parents[] = {
+	"clk26m",
+	"osc_d2",
+	"univpll_d6_d2",
+	"univpll_d6_d4"
+};
+
+static const char * const dsi_occ_parents[] = {
+	"clk26m",
+	"univpll_d6_d2",
+	"univpll_d5_d2",
+	"univpll_d4_d2"
+};
+
+static const char * const dxcc_parents[] = {
+	"clk26m",
+	"mainpll_d4_d8",
+	"mainpll_d4_d4",
+	"mainpll_d4_d2"
+};
+
+static const char * const i2c_parents[] = {
+	"clk26m",
+	"mainpll_d4_d8",
+	"univpll_d5_d4",
+	"mainpll_d4_d4"
+};
+
+static const char * const mcupm_parents[] = {
+	"clk26m",
+	"univpll_d6_d2",
+	"mainpll_d5_d2",
+	"mainpll_d6_d2"
+};
+
+static const char * const mfg_ref_parents[] = {
+	"clk26m",
+	"mainpll_d6_d2",
+	"mainpll_d6",
+	"mainpll_d5_d2"
+};
+
+static const char * const msdc30_h_parents[] = {
+	"clk26m",
+	"msdcpll_d2",
+	"mainpll_d4_d4",
+	"mainpll_d6_d4"
+};
+
+static const char * const msdc_macro_p_parents[] = {
+	"clk26m",
+	"msdcpll",
+	"mmpll_d5_d4",
+	"univpll_d4_d2"
+};
+
+static const char * const snps_eth_62p4m_ptp_parents[] = {
+	"clk26m",
+	"ethpll_d8",
+	"apll1_d3",
+	"apll2_d3"
+};
+
+static const char * const ufs_mbist_parents[] = {
+	"clk26m",
+	"mainpll_d4_d2",
+	"univpll_d4_d2",
+	"ufspll_d2"
+};
+
+static const char * const aes_msdcfde_parents[] = {
+	"clk26m",
+	"mainpll_d4_d2",
+	"mainpll_d6",
+	"mainpll_d4_d4",
+	"msdcpll"
+};
+
+static const char * const bus_aximem_parents[] = {
+	"clk26m",
+	"mainpll_d7_d2",
+	"mainpll_d5_d2",
+	"mainpll_d4_d2",
+	"mainpll_d6"
+};
+
+static const char * const dp_parents[] = {
+	"clk26m",
+	"tvdpll1_d16",
+	"tvdpll1_d8",
+	"tvdpll1_d4",
+	"tvdpll1_d2"
+};
+
+static const char * const msdc30_parents[] = {
+	"clk26m",
+	"univpll_d6_d2",
+	"mainpll_d6_d2",
+	"mainpll_d7_d2",
+	"msdcpll_d2"
+};
+
+static const char * const ecc_parents[] = {
+	"clk26m",
+	"univpll_d6_d2",
+	"univpll_d4_d2",
+	"univpll_d6",
+	"mainpll_d4",
+	"univpll_d4"
+};
+
+static const char * const emi_n_parents[] = {
+	"clk26m",
+	"osc_d2",
+	"mainpll_d9",
+	"mainpll_d6",
+	"mainpll_d5",
+	"emipll"
+};
+
+static const char * const sr_pka_parents[] = {
+	"clk26m",
+	"mainpll_d4_d4",
+	"mainpll_d4_d2",
+	"mainpll_d7",
+	"mainpll_d6",
+	"mainpll_d5"
+};
+
+static const char * const aes_ufsfde_parents[] = {
+	"clk26m",
+	"mainpll_d4",
+	"mainpll_d4_d2",
+	"mainpll_d6",
+	"mainpll_d4_d4",
+	"univpll_d4_d2",
+	"univpll_d6"
+};
+
+static const char * const axi_parents[] = {
+	"clk26m",
+	"mainpll_d4_d4",
+	"mainpll_d7_d2",
+	"mainpll_d4_d2",
+	"mainpll_d5_d2",
+	"mainpll_d6_d2",
+	"osc_d4"
+};
+
+static const char * const disp_pwm_parents[] = {
+	"clk26m",
+	"univpll_d6_d4",
+	"osc_d2",
+	"osc_d4",
+	"osc_d16",
+	"univpll_d5_d4",
+	"mainpll_d4_d4"
+};
+
+static const char * const edp_parents[] = {
+	"clk26m",
+	"tvdpll2_d16",
+	"tvdpll2_d8",
+	"tvdpll2_d4",
+	"tvdpll2_d2"
+};
+
+static const char * const gcpu_parents[] = {
+	"clk26m",
+	"mainpll_d6",
+	"mainpll_d4_d2",
+	"univpll_d4_d2",
+	"univpll_d5_d2",
+	"univpll_d5_d4",
+	"univpll_d6"
+};
+
+static const char * const msdc50_0_parents[] = {
+	"clk26m",
+	"msdcpll",
+	"msdcpll_d2",
+	"mainpll_d6_d2",
+	"mainpll_d4_d4",
+	"mainpll_d6",
+	"univpll_d4_d4"
+};
+
+static const char * const ufs_parents[] = {
+	"clk26m",
+	"mainpll_d4_d8",
+	"mainpll_d4_d4",
+	"mainpll_d5_d2",
+	"mainpll_d6_d2",
+	"univpll_d6_d2",
+	"msdcpll_d2"
+};
+
+static const char * const dsp_parents[] = {
+	"clk26m",
+	"osc_d4",
+	"osc_d3",
+	"osc_d2",
+	"univpll_d7_d2",
+	"univpll_d6_d2",
+	"mainpll_d6",
+	"univpll_d5"
+};
+
+static const char * const mem_sub_peri_u_parents[] = {
+	"clk26m",
+	"univpll_d4_d4",
+	"mainpll_d5_d2",
+	"mainpll_d4_d2",
+	"mainpll_d6",
+	"mainpll_d5",
+	"univpll_d5",
+	"mainpll_d4"
+};
+
+static const char * const seninf_parents[] = {
+	"clk26m",
+	"osc_d2",
+	"univpll_d6_d2",
+	"mainpll_d4_d2",
+	"univpll_d4_d2",
+	"mmpll_d7",
+	"univpll_d6",
+	"univpll_d5"
+};
+
+static const char * const sflash_parents[] = {
+	"clk26m",
+	"mainpll_d7_d8",
+	"univpll_d6_d8",
+	"mainpll_d7_d4",
+	"mainpll_d6_d4",
+	"univpll_d6_d4",
+	"univpll_d7_d3",
+	"univpll_d5_d4"
+};
+
+static const char * const spi_parents[] = {
+	"clk26m",
+	"univpll_d6_d2",
+	"univpll_192m",
+	"mainpll_d6_d2",
+	"univpll_d4_d4",
+	"mainpll_d4_d4",
+	"univpll_d5_d4",
+	"univpll_d6_d4"
+};
+
+static const char * const img1_parents[] = {
+	"clk26m",
+	"univpll_d4",
+	"mmpll_d5",
+	"mmpll_d6",
+	"univpll_d6",
+	"mmpll_d7",
+	"mmpll_d4_d2",
+	"univpll_d4_d2",
+	"mainpll_d4_d2",
+	"mmpll_d6_d2",
+	"mmpll_d5_d2"
+};
+
+static const char * const ipe_parents[] = {
+	"clk26m",
+	"univpll_d4",
+	"mainpll_d4",
+	"mmpll_d6",
+	"univpll_d6",
+	"mainpll_d6",
+	"mmpll_d4_d2",
+	"univpll_d4_d2",
+	"mainpll_d4_d2",
+	"mmpll_d6_d2",
+	"mmpll_d5_d2"
+};
+
+static const char * const mem_sub_parents[] = {
+	"clk26m",
+	"univpll_d4_d4",
+	"mainpll_d6_d2",
+	"mainpll_d5_d2",
+	"mainpll_d4_d2",
+	"mainpll_d6",
+	"mmpll_d7",
+	"mainpll_d5",
+	"univpll_d5",
+	"mainpll_d4",
+	"univpll_d4"
+};
+
+static const char * const cam_parents[] = {
+	"clk26m",
+	"mainpll_d4",
+	"mmpll_d4",
+	"univpll_d4",
+	"univpll_d5",
+	"mmpll_d7",
+	"mmpll_d6",
+	"univpll_d6",
+	"univpll_d4_d2",
+	"mmpll_d9",
+	"mainpll_d4_d2",
+	"osc_d2"
+};
+
+static const char * const mmsys_parents[] = {
+	"clk26m",
+	"mainpll_d5_d2",
+	"univpll_d5_d2",
+	"mainpll_d4_d2",
+	"univpll_d4_d2",
+	"mainpll_d6",
+	"univpll_d6",
+	"mmpll_d6",
+	"tvdpll1",
+	"tvdpll2",
+	"univpll_d4",
+	"mmpll_d4"
+};
+
+static const char * const mminfra_parents[] = {
+	"clk26m",
+	"osc_d2",
+	"mainpll_d5_d2",
+	"mmpll_d6_d2",
+	"mainpll_d4_d2",
+	"mmpll_d4_d2",
+	"mainpll_d6",
+	"mmpll_d7",
+	"univpll_d6",
+	"mainpll_d5",
+	"mmpll_d6",
+	"univpll_d5",
+	"mainpll_d4",
+	"univpll_d4",
+	"mmpll_d4",
+	"emipll"
+};
+
+static const char * const vdec_parents[] = {
+	"clk26m",
+	"univpll_192m_d2",
+	"univpll_d5_d4",
+	"mainpll_d5",
+	"mainpll_d5_d2",
+	"mmpll_d6_d2",
+	"univpll_d5_d2",
+	"mainpll_d4_d2",
+	"univpll_d4_d2",
+	"univpll_d7",
+	"mmpll_d7",
+	"mmpll_d6",
+	"univpll_d6",
+	"mainpll_d4",
+	"univpll_d4",
+	"mmpll_d5_d2"
+};
+
+static const char * const venc_parents[] = {
+	"clk26m",
+	"mmpll_d4_d2",
+	"mainpll_d6",
+	"univpll_d4_d2",
+	"mainpll_d4_d2",
+	"univpll_d6",
+	"mmpll_d6",
+	"mainpll_d5_d2",
+	"mainpll_d6_d2",
+	"mmpll_d9",
+	"mmpll_d4",
+	"mainpll_d4",
+	"univpll_d4",
+	"univpll_d5",
+	"univpll_d5_d2",
+	"mainpll_d5"
+};
+
+static const struct mtk_mux top_muxes[] = {
+	/* CLK_CFG_0 */
+	MUX_CLR_SET_UPD(CLK_TOP_AXI_SEL, "axi_sel",
+			axi_parents, 0x010, 0x014, 0x018, 0, 3, 0x04, 0),
+	MUX_CLR_SET_UPD(CLK_TOP_AXI_PERI_SEL, "axi_peri_sel",
+			axi_peri_parents, 0x010, 0x014, 0x018,
+			8, 2, 0x04, 1),
+	MUX_CLR_SET_UPD(CLK_TOP_AXI_U_SEL, "axi_u_sel",
+			axi_u_parents, 0x010, 0x014, 0x018,
+			16, 2, 0x04, 2),
+	MUX_CLR_SET_UPD(CLK_TOP_BUS_AXIMEM_SEL, "bus_aximem_sel",
+			bus_aximem_parents, 0x010, 0x014, 0x018,
+			24, 3, 0x04, 3),
+	/* CLK_CFG_1 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP0_SEL, "disp0_sel",
+			     mmsys_parents, 0x020, 0x024, 0x028,
+			     0, 4, 7, 0x04, 4),
+	MUX_CLR_SET_UPD(CLK_TOP_MMINFRA_SEL, "mminfra_sel",
+			mminfra_parents, 0x020, 0x024, 0x028,
+			8, 4, 0x04, 5),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel",
+			     uart_parents, 0x020, 0x024, 0x028,
+			     16, 1, 23, 0x04, 6),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI0_SEL, "spi0_sel",
+			     spi_parents, 0x020, 0x024, 0x028,
+			     24, 3, 31, 0x04, 7),
+	/* CLK_CFG_2 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI1_SEL, "spi1_sel",
+			     spi_parents, 0x030, 0x034, 0x038,
+			     0, 3, 7, 0x04, 8),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI2_SEL, "spi2_sel",
+			     spi_parents, 0x030, 0x034, 0x038,
+			     8, 3, 15, 0x04, 9),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI3_SEL, "spi3_sel",
+			     spi_parents, 0x030, 0x034, 0x038,
+			     16, 3, 23, 0x04, 10),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI4_SEL, "spi4_sel",
+			     spi_parents, 0x030, 0x034, 0x038,
+			     24, 3, 31, 0x04, 11),
+	/* CLK_CFG_3 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI5_SEL, "spi5_sel",
+			     spi_parents, 0x040, 0x044, 0x048,
+			     0, 3, 7, 0x04, 12),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC_MACRO_0P_SEL, "msdc_macro_0p_sel",
+			     msdc_macro_p_parents, 0x040, 0x044, 0x048,
+			     8, 2, 15, 0x04, 13),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc5hclk_sel",
+			     msdc5hclk_parents, 0x040, 0x044, 0x048,
+			     16, 2, 23, 0x04, 14),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel",
+			     msdc50_0_parents, 0x040, 0x044, 0x048,
+			     24, 3, 31, 0x04, 15),
+	/* CLK_CFG_4 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_MSDCFDE_SEL, "aes_msdcfde_sel",
+			     aes_msdcfde_parents, 0x050, 0x054, 0x058,
+			     0, 3, 7, 0x04, 16),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC_MACRO_1P_SEL, "msdc_macro_1p_sel",
+			     msdc_macro_p_parents, 0x050, 0x054, 0x058,
+			     8, 2, 15, 0x04, 17),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel",
+			     msdc30_parents, 0x050, 0x054, 0x058,
+			     16, 3, 23, 0x04, 18),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_HCLK_SEL, "msdc30_1_h_sel",
+			     msdc30_h_parents, 0x050, 0x054, 0x058,
+			     24, 2, 31, 0x04, 19),
+	/* CLK_CFG_5 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC_MACRO_2P_SEL, "msdc_macro_2p_sel",
+			     msdc_macro_p_parents, 0x060, 0x064, 0x068,
+			     0, 2, 7, 0x04, 20),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel",
+			     msdc30_parents, 0x060, 0x064, 0x068,
+			     8, 3, 15, 0x04, 21),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2_HCLK_SEL, "msdc30_2_h_sel",
+			     msdc30_h_parents, 0x060, 0x064, 0x068,
+			     16, 2, 23, 0x04, 22),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel",
+			     aud_intbus_parents, 0x060, 0x064, 0x068,
+			     24, 2, 31, 0x04, 23),
+	/* CLK_CFG_6 */
+	MUX_CLR_SET_UPD(CLK_TOP_ATB_SEL, "atb_sel",
+			atb_parents, 0x070, 0x074, 0x078, 0, 2, 0x04, 24),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM_SEL, "disp_pwm_sel",
+			     disp_pwm_parents, 0x070, 0x074, 0x078,
+			     8, 3, 15, 0x04, 25),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_P0_SEL, "usb_p0_sel",
+			     usb_parents, 0x070, 0x074, 0x078,
+			     16, 2, 23, 0x04, 26),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P0_SEL, "ssusb_xhci_p0_sel",
+			     usb_parents, 0x070, 0x074, 0x078,
+			     24, 2, 31, 0x04, 27),
+	/* CLK_CFG_7 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_P1_SEL, "usb_p1_sel",
+			     usb_parents, 0x080, 0x084, 0x088,
+			     0, 2, 7, 0x04, 28),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P1_SEL, "ssusb_xhci_p1_sel",
+			     usb_parents, 0x080, 0x084, 0x088,
+			     8, 2, 15, 0x04, 29),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_P2_SEL, "usb_p2_sel",
+			     usb_parents, 0x080, 0x084, 0x088,
+			     16, 2, 23, 0x04, 30),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P2_SEL, "ssusb_xhci_p2_sel",
+			     usb_parents, 0x080, 0x084, 0x088,
+			     24, 2, 31, 0x08, 0),
+	/* CLK_CFG_8 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_P3_SEL, "usb_p3_sel",
+			     usb_parents, 0x090, 0x094, 0x098,
+			     0, 2, 7, 0x08, 1),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P3_SEL, "ssusb_xhci_p3_sel",
+			     usb_parents, 0x090, 0x094, 0x098,
+			     8, 2, 15, 0x08, 2),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_P4_SEL, "usb_p4_sel",
+			     usb_parents, 0x090, 0x094, 0x098,
+			     16, 2, 23, 0x08, 3),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P4_SEL, "ssusb_xhci_p4_sel",
+			     usb_parents, 0x090, 0x094, 0x098,
+			     24, 2, 31, 0x08, 4),
+	/* CLK_CFG_9 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel",
+			     i2c_parents, 0x0a0, 0x0a4, 0x0a8,
+			     0, 2, 7, 0x08, 5),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF_SEL, "seninf_sel",
+			     seninf_parents, 0x0a0, 0x0a4, 0x0a8,
+			     8, 3, 15, 0x08, 6),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF1_SEL, "seninf1_sel",
+			     seninf_parents, 0x0a0, 0x0a4, 0x0a8,
+			     16, 3, 23, 0x08, 7),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel",
+			     aud_engen1_parents, 0x0a0, 0x0a4, 0x0a8,
+			     24, 2, 31, 0x08, 8),
+	/* CLK_CFG_10 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN2_SEL, "aud_engen2_sel",
+			     aud_engen2_parents, 0x0b0, 0x0b4, 0x0b8,
+			     0, 2, 7, 0x08, 9),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_UFSFDE_SEL, "aes_ufsfde_sel",
+			     aes_ufsfde_parents, 0x0b0, 0x0b4, 0x0b8,
+			     8, 3, 15, 0x08, 10),
+	MUX_CLR_SET_UPD(CLK_TOP_U_SEL, "ufs_sel",
+			ufs_parents, 0x0b0, 0x0b4, 0x0b8,
+			16, 3, 0x08, 11),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_U_MBIST_SEL, "ufs_mbist_sel",
+			     ufs_mbist_parents, 0x0b0, 0x0b4, 0x0b8,
+			     24, 2, 31, 0x08, 12),
+	/* CLK_CFG_11 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_1_SEL, "aud_1_sel",
+			     aud_1_parents, 0x0c0, 0x0c4, 0x0c8,
+			     0, 1, 7, 0x08, 13),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_2_SEL, "aud_2_sel",
+			     aud_2_parents, 0x0c0, 0x0c4, 0x0c8,
+			     8, 1, 15, 0x08, 14),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_VENC_SEL, "venc_sel",
+			     venc_parents, 0x0c0, 0x0c4, 0x0c8,
+			     16, 4, 23, 0x08, 15),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_VDEC_SEL, "vdec_sel",
+			     vdec_parents, 0x0c0, 0x0c4, 0x0c8,
+			     24, 4, 31, 0x08, 16),
+	/* CLK_CFG_12 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel",
+			     pwm_parents, 0x0d0, 0x0d4, 0x0d8,
+			     0, 1, 7, 0x08, 17),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_H_SEL, "audio_h_sel",
+			     audio_h_parents, 0x0d0, 0x0d4, 0x0d8,
+			     8, 2, 15, 0x08, 18),
+	MUX_CLR_SET_UPD(CLK_TOP_MCUPM_SEL, "mcupm_sel",
+			mcupm_parents, 0x0d0, 0x0d4, 0x0d8,
+			16, 2, 0x08, 19),
+	MUX_CLR_SET_UPD(CLK_TOP_MEM_SUB_SEL, "mem_sub_sel",
+			mem_sub_parents, 0x0d0, 0x0d4, 0x0d8,
+			24, 4, 0x08, 20),
+	/* CLK_CFG_13 */
+	MUX_CLR_SET_UPD(CLK_TOP_MEM_SUB_PERI_SEL, "mem_sub_peri_sel",
+			mem_sub_peri_u_parents, 0x0e0, 0x0e4, 0x0e8,
+			0, 3, 0x08, 21),
+	MUX_CLR_SET_UPD(CLK_TOP_MEM_SUB_U_SEL, "mem_sub_u_sel",
+			mem_sub_peri_u_parents, 0x0e0, 0x0e4, 0x0e8,
+			8, 3, 0x08, 22),
+	MUX_CLR_SET_UPD(CLK_TOP_EMI_N_SEL, "emi_n_sel",
+			emi_n_parents, 0x0e0, 0x0e4, 0x0e8,
+			16, 3, 0x08, 23),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_DSI_OCC_SEL, "dsi_occ_sel",
+			     dsi_occ_parents, 0x0e0, 0x0e4, 0x0e8,
+			     24, 2, 31, 0x08, 24),
+	/* CLK_CFG_14 */
+	MUX_CLR_SET_UPD(CLK_TOP_AP2CONN_HOST_SEL, "ap2conn_host_sel",
+			ap2conn_host_parents, 0x0f0, 0x0f4, 0x0f8,
+			0, 1, 0x08, 25),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_IMG1_SEL, "img1_sel",
+			     img1_parents, 0x0f0, 0x0f4, 0x0f8,
+			     8, 4, 15, 0x08, 26),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_IPE_SEL, "ipe_sel",
+			     ipe_parents, 0x0f0, 0x0f4, 0x0f8,
+			     16, 4, 23, 0x08, 27),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_CAM_SEL, "cam_sel",
+			     cam_parents, 0x0f0, 0x0f4, 0x0f8,
+			     24, 4, 31, 0x08, 28),
+	/* CLK_CFG_15 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM_SEL, "camtm_sel",
+			     camtm_parents, 0x100, 0x104, 0x108,
+			     0, 2, 7, 0x08, 29),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP_SEL, "dsp_sel",
+			     dsp_parents, 0x100, 0x104, 0x108,
+			     8, 3, 15, 0x08, 30),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_SR_PKA_SEL, "sr_pka_sel",
+			     sr_pka_parents, 0x100, 0x104, 0x108,
+			     16, 3, 23, 0x0c, 0),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC_SEL, "dxcc_sel",
+			     dxcc_parents, 0x100, 0x104, 0x108,
+			     24, 2, 31, 0x0c, 1),
+	/* CLK_CFG_16 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG_REF_SEL, "mfg_ref_sel",
+			     mfg_ref_parents, 0x110, 0x114, 0x118,
+			     0, 2, 7, 0x0c, 2),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MDP0_SEL, "mdp0_sel",
+			     mmsys_parents, 0x110, 0x114, 0x118,
+			     8, 4, 15, 0x0c, 3),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_DP_SEL, "dp_sel",
+			     dp_parents, 0x110, 0x114, 0x118,
+			     16, 3, 23, 0x0c, 4),
+	MUX_CLR_SET_UPD(CLK_TOP_EDP_SEL, "edp_sel",
+			edp_parents, 0x110, 0x114, 0x118,
+			24, 3, 0x0c, 5),
+	/* CLK_CFG_17 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_EDP_FAVT_SEL, "edp_favt_sel",
+			     edp_parents, 0x180, 0x184, 0x188,
+			     0, 3, 7, 0x0c, 6),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_250M_SEL, "snps_eth_250m_sel",
+			     snps_eth_250m_parents, 0x180, 0x184, 0x188,
+			     8, 1, 15, 0x0c, 7),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_62P4M_PTP_SEL,
+			     "snps_eth_62p4m_ptp_sel",
+			     snps_eth_62p4m_ptp_parents,
+			     0x180, 0x184, 0x188, 16, 2, 23, 0x0c, 8),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_50M_RMII_SEL,
+			     "snps_eth_50m_rmii_sel",
+			     snps_eth_50m_rmii_parents,
+			     0x180, 0x184, 0x188, 24, 1, 31, 0x0c, 9),
+	/* CLK_CFG_18 */
+	MUX_CLR_SET_UPD(CLK_TOP_SFLASH_SEL, "sflash_sel",
+			sflash_parents, 0x190, 0x194, 0x198,
+			0, 3, 0x0c, 10),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_GCPU_SEL, "gcpu_sel",
+			     gcpu_parents, 0x190, 0x194, 0x198,
+			     8, 3, 15, 0x0c, 11),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_MAC_TL_SEL, "pcie_mac_tl_sel",
+			     pcie_mac_tl_parents, 0x190, 0x194, 0x198,
+			     16, 2, 23, 0x0c, 12),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_VDSTX_DG_CTS_SEL, "vdstx_dg_cts_sel",
+			     vdstx_dg_cts_parents, 0x190, 0x194, 0x198,
+			     24, 2, 31, 0x0c, 13),
+	/* CLK_CFG_19 */
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_PLL_DPIX_SEL, "pll_dpix_sel",
+			     pll_dpix_parents, 0x240, 0x244, 0x248,
+			     0, 2, 7, 0x0c, 14),
+	MUX_GATE_CLR_SET_UPD(CLK_TOP_ECC_SEL, "ecc_sel",
+			     ecc_parents, 0x240, 0x244, 0x248,
+			     8, 3, 15, 0x0c, 15),
+	/* CLK_MISC_CFG_3 */
+	GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MFG_SEL_MFGPLL, "mfg_sel_mfgpll",
+			       mfg_sel_mfgpll_parents,
+			       0x510, 0x514, 0x0518, 16, 1, 0, -1, -1,
+			       CLK_SET_RATE_PARENT,
+			       mtk_mux_clr_set_upd_ops)
+};
+
+static const struct mtk_composite top_composites[] = {
+	/* CLK_AUDDIV_0 */
+	MUX(CLK_TOP_APLL_I2SIN0_MCK_SEL, "apll_i2sin0_m_sel",
+	    apll_m_parents, 0x0320, 16, 1),
+	MUX(CLK_TOP_APLL_I2SIN1_MCK_SEL, "apll_i2sin1_m_sel",
+	    apll_m_parents, 0x0320, 17, 1),
+	MUX(CLK_TOP_APLL_I2SIN2_MCK_SEL, "apll_i2sin2_m_sel",
+	    apll_m_parents, 0x0320, 18, 1),
+	MUX(CLK_TOP_APLL_I2SIN3_MCK_SEL, "apll_i2sin3_m_sel",
+	    apll_m_parents, 0x0320, 19, 1),
+	MUX(CLK_TOP_APLL_I2SIN4_MCK_SEL, "apll_i2sin4_m_sel",
+	    apll_m_parents, 0x0320, 20, 1),
+	MUX(CLK_TOP_APLL_I2SIN6_MCK_SEL, "apll_i2sin6_m_sel",
+	    apll_m_parents, 0x0320, 21, 1),
+	MUX(CLK_TOP_APLL_I2SOUT0_MCK_SEL, "apll_i2sout0_m_sel",
+	    apll_m_parents, 0x0320, 22, 1),
+	MUX(CLK_TOP_APLL_I2SOUT1_MCK_SEL, "apll_i2sout1_m_sel",
+	    apll_m_parents, 0x0320, 23, 1),
+	MUX(CLK_TOP_APLL_I2SOUT2_MCK_SEL, "apll_i2sout2_m_sel",
+	    apll_m_parents, 0x0320, 24, 1),
+	MUX(CLK_TOP_APLL_I2SOUT3_MCK_SEL, "apll_i2sout3_m_sel",
+	    apll_m_parents, 0x0320, 25, 1),
+	MUX(CLK_TOP_APLL_I2SOUT4_MCK_SEL, "apll_i2sout4_m_sel",
+	    apll_m_parents, 0x0320, 26, 1),
+	MUX(CLK_TOP_APLL_I2SOUT6_MCK_SEL, "apll_i2sout6_m_sel",
+	    apll_m_parents, 0x0320, 27, 1),
+	MUX(CLK_TOP_APLL_FMI2S_MCK_SEL, "apll_fmi2s_m_sel",
+	    apll_m_parents, 0x0320, 28, 1),
+	MUX(CLK_TOP_APLL_TDMOUT_MCK_SEL, "apll_tdmout_m_sel",
+	    apll_m_parents, 0x0320, 29, 1),
+	/* CLK_AUDDIV_2 */
+	DIV_GATE(CLK_TOP_APLL12_CK_DIV_I2SIN0, "apll12_div_i2sin0",
+		 "apll_i2sin0_m_sel", 0x0320, 0, 0x0328, 8, 0),
+	DIV_GATE(CLK_TOP_APLL12_CK_DIV_I2SIN1, "apll12_div_i2sin1",
+		 "apll_i2sin1_m_sel", 0x0320, 1, 0x0328, 8, 8),
+	/* CLK_AUDDIV_3 */
+	DIV_GATE(CLK_TOP_APLL12_CK_DIV_I2SOUT0, "apll12_div_i2sout0",
+		 "apll_i2sout0_m_sel", 0x0320, 6, 0x0334, 8, 16),
+	DIV_GATE(CLK_TOP_APLL12_CK_DIV_I2SOUT1, "apll12_div_i2sout1",
+		 "apll_i2sout1_m_sel", 0x0320, 7, 0x0334, 8, 24),
+	/* CLK_AUDDIV_5 */
+	DIV_GATE(CLK_TOP_APLL12_CK_DIV_FMI2S, "apll12_div_fmi2s",
+		 "apll_fmi2s_m_sel", 0x0320, 12, 0x033c, 8, 0),
+	DIV_GATE(CLK_TOP_APLL12_CK_DIV_TDMOUT_M, "apll12_div_tdmout_m",
+		 "apll_tdmout_m_sel", 0x0320, 13, 0x033c, 8, 8),
+	DIV_GATE(CLK_TOP_APLL12_CK_DIV_TDMOUT_B, "apll12_div_tdmout_b",
+		 "apll12_div_tdmout_m", 0x0320, 14, 0x033c, 8, 16),
+};
+
+static const struct mtk_gate_regs top_cg_regs = {
+	.set_ofs = 0x514,
+	.clr_ofs = 0x518,
+	.sta_ofs = 0x510,
+};
+
+#define GATE_TOP_FLAGS(_id, _name, _parent, _shift, _flag) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &top_cg_regs,			\
+		.shift = _shift,			\
+		.flags = _flag,				\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_TOP(_id, _name, _parent, _shift)		\
+	GATE_TOP_FLAGS(_id, _name, _parent, _shift, 0)
+
+static const struct mtk_gate top_clks[] = {
+	GATE_TOP_FLAGS(CLK_TOP_FMCNT_P0_EN, "fmcnt_p0_en", "univpll_192m_d4", 0, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_FMCNT_P1_EN, "fmcnt_p1_en", "univpll_192m_d4", 1, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_FMCNT_P2_EN, "fmcnt_p2_en", "univpll_192m_d4", 2, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_FMCNT_P3_EN, "fmcnt_p3_en", "univpll_192m_d4", 3, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_FMCNT_P4_EN, "fmcnt_p4_en", "univpll_192m_d4", 4, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_USB_F26M_CK_EN, "ssusb_f26m", "clk26m", 5, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_SSPXTP_F26M_CK_EN, "sspxtp_f26m", "clk26m", 6, CLK_IS_CRITICAL),
+	GATE_TOP(CLK_TOP_USB2_PHY_RF_P0_EN, "usb2_phy_rf_p0_en", "ssusb_f26m", 7),
+	GATE_TOP(CLK_TOP_USB2_PHY_RF_P1_EN, "usb2_phy_rf_p1_en", "ssusb_f26m", 10),
+	GATE_TOP(CLK_TOP_USB2_PHY_RF_P2_EN, "usb2_phy_rf_p2_en", "ssusb_f26m", 11),
+	GATE_TOP(CLK_TOP_USB2_PHY_RF_P3_EN, "usb2_phy_rf_p3_en", "ssusb_f26m", 12),
+	GATE_TOP(CLK_TOP_USB2_PHY_RF_P4_EN, "usb2_phy_rf_p4_en", "ssusb_f26m", 13),
+	GATE_TOP_FLAGS(CLK_TOP_USB2_26M_CK_P0_EN, "usb2_26m_p0_en", "ssusb_f26m", 14, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_USB2_26M_CK_P1_EN, "usb2_26m_p1_en", "ssusb_f26m", 15, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_USB2_26M_CK_P2_EN, "usb2_26m_p2_en", "ssusb_f26m", 18, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_USB2_26M_CK_P3_EN, "usb2_26m_p3_en", "ssusb_f26m", 19, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_USB2_26M_CK_P4_EN, "usb2_26m_p4_en", "ssusb_f26m", 20, CLK_IS_CRITICAL),
+	GATE_TOP(CLK_TOP_F26M_CK_EN, "pcie_f26m", "sspxtp_f26m", 21),
+	GATE_TOP_FLAGS(CLK_TOP_AP2CON_EN, "ap2con", "clk26m", 24, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_EINT_N_EN, "eint_n", "clk26m", 25, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_TOPCKGEN_FMIPI_CSI_UP26M_CK_EN,
+		       "fmipi_csi_up26m", "osc_d10", 26, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_EINT_E_EN, "eint_e", "clk26m", 28, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_EINT_W_EN, "eint_w", "clk26m", 30, CLK_IS_CRITICAL),
+	GATE_TOP_FLAGS(CLK_TOP_EINT_S_EN, "eint_s", "clk26m", 31, CLK_IS_CRITICAL),
+};
+
+/* Register mux notifier for MFG mux */
+static int clk_mt8189_reg_mfg_mux_notifier(struct device *dev,
+					   struct clk *clk)
+{
+	struct mtk_mux_nb *mfg_mux_nb;
+
+	mfg_mux_nb = devm_kzalloc(dev, sizeof(*mfg_mux_nb), GFP_KERNEL);
+	if (!mfg_mux_nb)
+		return -ENOMEM;
+
+	mfg_mux_nb->ops = &mtk_mux_clr_set_upd_ops;
+	mfg_mux_nb->bypass_index = 0; /* Bypass to CLK_TOP_MFG_REF_SEL */
+
+	return devm_mtk_clk_mux_notifier_register(dev, clk, mfg_mux_nb);
+}
+
+static const struct mtk_clk_desc topck_desc = {
+	.factor_clks = top_divs,
+	.num_factor_clks = ARRAY_SIZE(top_divs),
+	.mux_clks = top_muxes,
+	.num_mux_clks = ARRAY_SIZE(top_muxes),
+	.composite_clks = top_composites,
+	.num_composite_clks = ARRAY_SIZE(top_composites),
+	.clks = top_clks,
+	.num_clks = ARRAY_SIZE(top_clks),
+	.clk_notifier_func = clk_mt8189_reg_mfg_mux_notifier,
+	.mfg_clk_idx = CLK_TOP_MFG_SEL_MFGPLL,
+	.clk_lock = &mt8189_clk_lock,
+};
+
+static const struct of_device_id of_match_clk_mt8189_topck[] = {
+	{ .compatible = "mediatek,mt8189-topckgen", .data = &topck_desc },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8189_topck_drv = {
+	.probe = mtk_clk_simple_probe,
+	.remove = mtk_clk_simple_remove,
+	.driver = {
+		.name = "clk-mt8189-topck",
+		.of_match_table = of_match_clk_mt8189_topck,
+	},
+};
+module_platform_driver(clk_mt8189_topck_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 topckgen clocks driver");
+MODULE_LICENSE("GPL");

-- 
2.54.0



^ permalink raw reply related

* [PATCH 09/15] clk: mediatek: Add MT8189 vlpcfg clock support
From: Louis-Alexis Eyraud @ 2026-07-01 13:11 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Chun-Jie Chen, Philipp Zabel,
	Edward-JW Yang, Richard Cochran
  Cc: kernel, linux-clk, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, netdev, Irving-CH Lin, Louis-Alexis Eyraud
In-Reply-To: <20260701-mt8189-clocks-system-base-v1-0-2b048feea50a@collabora.com>

Add support for the MT8189 vlpcfg clock controller,
which provides clock gate control for vlp domain IPs.

Co-developed-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Signed-off-by: Irving-CH Lin <irving-ch.lin@mediatek.com>
Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
 drivers/clk/mediatek/Makefile            |   2 +-
 drivers/clk/mediatek/clk-mt8189-vlpcfg.c | 115 +++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 3b25df9e7b50..d9279b237b7b 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -124,7 +124,7 @@ obj-$(CONFIG_COMMON_CLK_MT8188_VENCSYS) += clk-mt8188-venc.o
 obj-$(CONFIG_COMMON_CLK_MT8188_VPPSYS) += clk-mt8188-vpp0.o clk-mt8188-vpp1.o
 obj-$(CONFIG_COMMON_CLK_MT8188_WPESYS) += clk-mt8188-wpe.o
 obj-$(CONFIG_COMMON_CLK_MT8189) += clk-mt8189-apmixedsys.o clk-mt8189-topckgen.o \
-				   clk-mt8189-vlpckgen.o
+				   clk-mt8189-vlpckgen.o clk-mt8189-vlpcfg.o
 obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192-apmixedsys.o clk-mt8192.o
 obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o
 obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o
diff --git a/drivers/clk/mediatek/clk-mt8189-vlpcfg.c b/drivers/clk/mediatek/clk-mt8189-vlpcfg.c
new file mode 100644
index 000000000000..81e2d44bd320
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8189-vlpcfg.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026 MediaTek Inc.
+ *                    Qiqi Wang <qiqi.wang@mediatek.com>
+ *                    Irving-CH Lin <irving-ch.lin@mediatek.com>
+ * Copyright (C) 2026 Collabora Ltd.
+ *                    AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ *                    Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mediatek,mt8189-clk.h>
+
+static const struct mtk_gate_regs vlpcfg_ao_reg_cg_regs = {
+	.set_ofs = 0x0,
+	.clr_ofs = 0x0,
+	.sta_ofs = 0x0,
+};
+
+#define GATE_VLPCFG_AO_REG(_id, _name, _parent, _shift)		\
+	GATE_MTK(_id, _name, _parent, &vlpcfg_ao_reg_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr)
+
+static const struct mtk_gate vlpcfg_ao_reg_clks[] = {
+	GATE_VLPCFG_AO_REG(CLK_VLPCFG_AO_APEINT_RX, "vlpcfg_ao_apeint_rx", "clk26m", 8),
+};
+
+static const struct mtk_clk_desc vlpcfg_ao_reg_mcd = {
+	.clks = vlpcfg_ao_reg_clks,
+	.num_clks = ARRAY_SIZE(vlpcfg_ao_reg_clks),
+};
+
+static const struct mtk_gate_regs vlpcfg_reg_cg_regs = {
+	.set_ofs = 0x4,
+	.clr_ofs = 0x4,
+	.sta_ofs = 0x4,
+};
+
+#define GATE_VLPCFG_REG_FLAGS(_id, _name, _parent, _shift, _flags)		\
+	GATE_MTK_FLAGS(_id, _name, _parent, &vlpcfg_reg_cg_regs, _shift,	\
+		       &mtk_clk_gate_ops_no_setclr_inv, _flags)
+
+#define GATE_VLPCFG_REG(_id, _name, _parent, _shift)		\
+	GATE_VLPCFG_REG_FLAGS(_id, _name, _parent, _shift, 0)
+
+static const struct mtk_gate vlpcfg_reg_clks[] = {
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SCP, "vlpcfg_scp",
+			      "vlp_scp_sel", 28, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_RG_R_APXGPT_26M, "vlpcfg_r_apxgpt_26m",
+			      "clk26m", 24, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_DPMSRCK_TEST, "vlpcfg_dpmsrck_test",
+			      "clk26m", 23, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_RG_DPMSRRTC_TEST, "vlpcfg_dpmsrrtc_test",
+			      "clk32k", 22, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_DPMSRULP_TEST, "vlpcfg_dpmsrulp_test",
+			      "osc_d10", 21, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SPMI_P_MST, "vlpcfg_spmi_p",
+			      "vlp_spmi_p_sel", 20, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SPMI_P_MST_32K, "vlpcfg_spmi_p_32k",
+			      "clk32k", 18, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_PMIF_SPMI_P_SYS, "vlpcfg_pmif_spmi_p_sys",
+			      "vlp_pwrap_ulposc_sel", 13, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_PMIF_SPMI_P_TMR, "vlpcfg_pmif_spmi_p_tmr",
+			      "vlp_pwrap_ulposc_sel", 12, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG(CLK_VLPCFG_REG_PMIF_SPMI_M_SYS, "vlpcfg_pmif_spmi_m_sys",
+			"vlp_pwrap_ulposc_sel", 11),
+	GATE_VLPCFG_REG(CLK_VLPCFG_REG_PMIF_SPMI_M_TMR, "vlpcfg_pmif_spmi_m_tmr",
+			"vlp_pwrap_ulposc_sel", 10),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_DVFSRC, "vlpcfg_dvfsrc",
+			      "vlp_dvfsrc_sel", 9, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_PWM_VLP, "vlpcfg_pwm_vlp",
+			      "vlp_pwm_vlp_sel", 8, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SRCK, "vlpcfg_srck",
+			      "vlp_srck_sel", 7, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SSPM_F26M, "vlpcfg_sspm_f26m",
+			      "vlp_sspm_f26m_sel", 4, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SSPM_F32K, "vlpcfg_sspm_f32k",
+			      "clk32k", 3, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_SSPM_ULPOSC, "vlpcfg_sspm_ulposc",
+			      "vlp_sspm_ulposc_sel", 2, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_VLP_32K_COM, "vlpcfg_vlp_32k_com",
+			      "clk32k", 1, CLK_IS_CRITICAL),
+	GATE_VLPCFG_REG_FLAGS(CLK_VLPCFG_REG_VLP_26M_COM, "vlpcfg_vlp_26m_com",
+			      "clk26m", 0, CLK_IS_CRITICAL),
+};
+
+static const struct mtk_clk_desc vlpcfg_reg_mcd = {
+	.clks = vlpcfg_reg_clks,
+	.num_clks = ARRAY_SIZE(vlpcfg_reg_clks),
+};
+
+static const struct of_device_id of_match_clk_mt8189_vlpcfg[] = {
+	{ .compatible = "mediatek,mt8189-vlpcfg", .data = &vlpcfg_reg_mcd },
+	{ .compatible = "mediatek,mt8189-vlpcfg-ao", .data = &vlpcfg_ao_reg_mcd },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_mt8189_vlpcfg_drv = {
+	.probe = mtk_clk_simple_probe,
+	.remove = mtk_clk_simple_remove,
+	.driver = {
+		.name = "clk-mt8189-vlpcfg",
+		.of_match_table = of_match_clk_mt8189_vlpcfg,
+	},
+};
+module_platform_driver(clk_mt8189_vlpcfg_drv);
+
+MODULE_DESCRIPTION("MediaTek MT8189 vlpcfg clocks driver");
+MODULE_LICENSE("GPL");

-- 
2.54.0



^ permalink raw reply related

* Re: [PATCH 1/3] dt-bindings: rtc: Add sii,wakealarm-output-pin property for S35390A
From: Alexandre Belloni @ 2026-07-01 15:11 UTC (permalink / raw)
  To: Markus Probst
  Cc: Krzysztof Kozlowski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Uwe Kleine-König, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, linux-arm-kernel, linux-rtc, devicetree,
	linux-kernel
In-Reply-To: <45e8157be53c3d8827fcccece7f706968bc056d3.camel@posteo.de>

On 01/07/2026 13:25:41+0000, Markus Probst wrote:
> On Wed, 2026-07-01 at 09:35 +0200, Krzysztof Kozlowski wrote:
> > On Tue, Jun 30, 2026 at 07:22:21PM +0000, Markus Probst wrote:
> > > Synology NAS devices use the output pin for interrupt signal 1 to wake up
> > > the system.
> > > 
> > > Move devicetree bindings for sii,s35390a into its own file.
> > > Add sii,wakealarm-output-pin property to enable the use of the output
> > > pin for interrupt signal 1 for the wake alarm, which makes it possible to
> > > set an wake alarm on Synology NAS devices.
> > > 
> > > Signed-off-by: Markus Probst <markus.probst@posteo.de>
> > > ---
> > >  .../devicetree/bindings/rtc/sii,s35390a.yaml       | 54 ++++++++++++++++++++++
> > >  .../devicetree/bindings/rtc/trivial-rtc.yaml       |  3 --
> > >  MAINTAINERS                                        |  1 +
> > >  include/dt-bindings/rtc/s35390a.h                  |  9 ++++
> > >  4 files changed, 64 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/rtc/sii,s35390a.yaml b/Documentation/devicetree/bindings/rtc/sii,s35390a.yaml
> > > new file mode 100644
> > > index 000000000000..31a578673870
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/rtc/sii,s35390a.yaml
> > > @@ -0,0 +1,54 @@
> > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > +%YAML 1.2
> > > +---
> > > +$id: http://devicetree.org/schemas/rtc/sii,s35390a.yaml#
> > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > +
> > > +title: S-35390A 2-WIRE REAL-TIME CLOCK
> > > +
> > > +maintainers:
> > > +  - Alexandre Belloni <alexandre.belloni@bootlin.com>
> > 
> > This should be someone caring about this hardware.
> He does have the majority of commits on this driver (excluding merge
> commits and commits not exclusive to this driver), although most of
> them are pretty tiny.
> 
> Who would you suggest instead?

I can take it but the point of Krzysztof is mainly that the ones working
on the driver don't necessarily have to be the DT bindings maintainers
as both are well separated.

I mostly did clean ups in the driver, Lorenz Brun submitted something
way more interesting.

> > 
> > > +
> > > +description:
> > > +  The S-35390A is a CMOS 2-wire real-time clock IC which operates with the
> > > +  very low current consumption in the wide range of operation voltage.
> > > +
> > > +allOf:
> > > +  - $ref: rtc.yaml#
> > > +
> > > +properties:
> > > +  compatible:
> > > +    const: sii,s35390a
> > > +
> > > +  reg:
> > > +    maxItems: 1
> > > +
> > > +  sii,wakealarm-output-pin:
> > > +    $ref: /schemas/types.yaml#/definitions/uint32
> > > +    enum: [1, 2]
> > > +    description: |
> > > +      The output pin to wake up the system.
> > > +      Default will use the output pin for interrupt signal 2.
> > > +        <S35390A_OUTPUT_PIN_INT1> : Output pin for interrupt signal 1
> > > +        <S35390A_OUTPUT_PIN_INT2> : Output pin for interrupt signal 2
> > 
> > Does that mean device generates the interrupts?
> Yes.
> 
> Thanks
> - Markus Probst
> 
> > 
> > Best regards,
> > Krzysztof



-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


^ permalink raw reply

* [PATCH 02/11] dt-bindings: display: mediatek: dp: Add compatible for MT8196 eDP
From: AngeloGioacchino Del Regno @ 2026-07-01 12:20 UTC (permalink / raw)
  To: chunkuang.hu
  Cc: p.zabel, airlied, simona, maarten.lankhorst, mripard, tzimmermann,
	robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
	jitao.shi, granquet, rex-bc.chen, dmitry.osipenko, ck.hu,
	amergnat, justin.yeh, jason-jh.lin, dri-devel, linux-mediatek,
	devicetree, linux-kernel, linux-arm-kernel, kernel
In-Reply-To: <20260701122024.19557-1-angelogioacchino.delregno@collabora.com>

Add a new compatible for the Embedded DisplayPort IP found in the
MT8196 SoC.

This IP is compatible with the previous ones, but not fully.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 .../devicetree/bindings/display/mediatek/mediatek,dp.yaml        | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml
index 980f76667ada..3a752a99949a 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml
@@ -25,6 +25,7 @@ properties:
       - mediatek,mt8188-edp-tx
       - mediatek,mt8195-dp-tx
       - mediatek,mt8195-edp-tx
+      - mediatek,mt8196-edp-tx
 
   reg:
     maxItems: 1
-- 
2.54.0



^ permalink raw reply related

* [PATCH 00/11] drm: MediaTek DisplayPort cleanups and MT8196 eDP
From: AngeloGioacchino Del Regno @ 2026-07-01 12:20 UTC (permalink / raw)
  To: chunkuang.hu
  Cc: p.zabel, airlied, simona, maarten.lankhorst, mripard, tzimmermann,
	robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
	jitao.shi, granquet, rex-bc.chen, dmitry.osipenko, ck.hu,
	amergnat, justin.yeh, jason-jh.lin, dri-devel, linux-mediatek,
	devicetree, linux-kernel, linux-arm-kernel, kernel

This series performs some very much needed cleanups to the MediaTek
DisplayPort driver, including a fix for the audio codec and PHY driver
unregistration, a refactor to finally correctly use the PHY (!) and
introduces support for the Embedded DisplayPort (eDP) IP in MT8196.

Note that this deprecates the nvmem related properties in this driver
because those are NOT related to the DisplayPort IP, but rather to the
DisplayPort PHY, and were therefore transferred there instead (code in
a different series, updating the PHY driver).

On legacy devices, this driver was carefully tested with both NEW and
OLD devicetrees, so both with the new, proper PHY usage, and with the
old platform device registration strategy and eFuse retrieval from DP
instead of PHY driver.

This was also successfully (manually) tested in a kernel that misses
the PHY driver updates on devices using old devicetrees (mt8195/88)
and no regressions were experienced.

AngeloGioacchino Del Regno (11):
  dt-bindings: display: mediatek: dp: Deprecate nvmem efuse data
  dt-bindings: display: mediatek: dp: Add compatible for MT8196 eDP
  drm/mediatek: mtk_dp: Fix hdmi codec and phy driver unregistration
  drm/mediatek: mtk_dp: Clarify SMC eDP/DP video unmute commands
  drm/mediatek: mtk_dp: Rework register offsets for proper PHY usage
  drm/mediatek: mtk_dp: Use PHY API for PHY power sequences
  drm/mediatek: mtk_dp: Add support for PHY from devicetree
  drm/mediatek: mtk_dp: Move max link rate to SoC specific data
  drm/mediatek: mtk_dp: Add support for HotPlug Detection in DP AUX
  drm/mediatek: mtk_dp: Add support for eDP1.5 IPs and MT8196 SoC
  drm/mediatek: mtk_dp: Clarify XTAL freq and Debounce registers

 .../display/mediatek/mediatek,dp.yaml         |   5 +-
 drivers/gpu/drm/mediatek/mtk_dp.c             | 576 +++++++++++++++---
 drivers/gpu/drm/mediatek/mtk_dp_reg.h         | 328 +++++-----
 3 files changed, 691 insertions(+), 218 deletions(-)

-- 
2.54.0



^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: rtc: Add sii,wakealarm-output-pin property for S35390A
From: Krzysztof Kozlowski @ 2026-07-01 15:14 UTC (permalink / raw)
  To: Markus Probst
  Cc: Alexandre Belloni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Uwe Kleine-König, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, linux-arm-kernel, linux-rtc, devicetree,
	linux-kernel
In-Reply-To: <45e8157be53c3d8827fcccece7f706968bc056d3.camel@posteo.de>

On 01/07/2026 15:25, Markus Probst wrote:
>>> +
>>> +maintainers:
>>> +  - Alexandre Belloni <alexandre.belloni@bootlin.com>
>>
>> This should be someone caring about this hardware.
> He does have the majority of commits on this driver (excluding merge
> commits and commits not exclusive to this driver), although most of
> them are pretty tiny.
> 
> Who would you suggest instead?

Someone adding features for this driver, maybe driver maintainers. But
if Alexandre is fine, you can leave him.

>>
>>> +
>>> +description:
>>> +  The S-35390A is a CMOS 2-wire real-time clock IC which operates with the
>>> +  very low current consumption in the wide range of operation voltage.
>>> +
>>> +allOf:
>>> +  - $ref: rtc.yaml#
>>> +
>>> +properties:
>>> +  compatible:
>>> +    const: sii,s35390a
>>> +
>>> +  reg:
>>> +    maxItems: 1
>>> +
>>> +  sii,wakealarm-output-pin:
>>> +    $ref: /schemas/types.yaml#/definitions/uint32
>>> +    enum: [1, 2]
>>> +    description: |
>>> +      The output pin to wake up the system.
>>> +      Default will use the output pin for interrupt signal 2.
>>> +        <S35390A_OUTPUT_PIN_INT1> : Output pin for interrupt signal 1
>>> +        <S35390A_OUTPUT_PIN_INT2> : Output pin for interrupt signal 2
>>
>> Does that mean device generates the interrupts?
> Yes.
> 


Then I think you miss interrupts property.

Best regards,
Krzysztof


^ permalink raw reply

* [PATCH] dt-bindings: mfd: mediatek,mt8195-scpsys: Add support for MT8189 SoC
From: Louis-Alexis Eyraud @ 2026-07-01 15:14 UTC (permalink / raw)
  To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Matthias Brugger, AngeloGioacchino Del Regno
  Cc: kernel, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, Louis-Alexis Eyraud

Add a compatible string for the scpsys block found in the MediaTek
MT8189 SoC.

Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
The patch is based on linux-next tree (tag: next-20260630) and has
been tested on Mediatek Genio 520-EVK (MT8371) and 720-EVK (MT8391)
boards with board hardware enablement patch series.
---
 Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml
index 4cafa381979b..9f073d0c28ef 100644
--- a/Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt8195-scpsys.yaml
@@ -26,6 +26,7 @@ properties:
           - mediatek,mt8183-scpsys
           - mediatek,mt8186-scpsys
           - mediatek,mt8188-scpsys
+          - mediatek,mt8189-scpsys
           - mediatek,mt8192-scpsys
           - mediatek,mt8195-scpsys
           - mediatek,mt8365-scpsys

---
base-commit: ba7c57499e5999aeae8dd4f954eb2600589d80aa
change-id: 20260701-mt8189-dt-bindings-scpsys-01c9610acc52

Best regards,
-- 
Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>



^ permalink raw reply related

* [PATCH 1/1] arm64: dts: s32g: describe GPIO and EIRQ resources in SIUL2 pinctrl node
From: Khristine Andreea Barbulescu @ 2026-07-01 11:51 UTC (permalink / raw)
  To: Bartosz Golaszewski, Chester Lin, Matthias Brugger,
	Ghennadi Procopciuc, Frank Li, Sascha Hauer, Fabio Estevam,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Pengutronix Kernel Team, linux-arm-kernel, imx, devicetree,
	linux-kernel, NXP S32 Linux, Christophe Lizzi, Alberto Ruiz,
	Enric Balletbo
In-Reply-To: <20260701115120.1115494-1-khristineandreea.barbulescu@oss.nxp.com>

Update the SIUL2 pinctrl node to describe the additional register
ranges and DT properties used by the updated SIUL2 driver.

Besides the MSCR and IMCR ranges used for pinmux and pin
configuration, the SIUL2 block also provides PGPDO and
PGPDI registers for GPIO output and input operations,
as well as an EIRQ register window for external interrupt configuration.

The driver supports both legacy pinctrl-only DTs and
extended DTs with GPIO and IRQ.

Reflect these resources in the SIUL2 pinctrl node by adding:
  - the PGPDO and PGPDI register ranges
  - the EIRQ register range
  - gpio-controller, #gpio-cells and gpio-ranges
  - interrupt-controller, #interrupt-cells and interrupts

Keep the hardware description aligned with the updated SIUL2
driver, where pinctrl, GPIO data access and the EIRQ register
block are described under the same device node.

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Khristine Andreea Barbulescu <khristineandreea.barbulescu@oss.nxp.com>
---
 arch/arm64/boot/dts/freescale/s32g2.dtsi | 21 ++++++++++++++++++++-
 arch/arm64/boot/dts/freescale/s32g3.dtsi | 21 ++++++++++++++++++++-
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/s32g2.dtsi b/arch/arm64/boot/dts/freescale/s32g2.dtsi
index 809019ea0e29..8dc0c5d9f368 100644
--- a/arch/arm64/boot/dts/freescale/s32g2.dtsi
+++ b/arch/arm64/boot/dts/freescale/s32g2.dtsi
@@ -135,7 +135,26 @@ pinctrl: pinctrl@4009c240 {
 				/* IMCR119-IMCR397 registers on siul2_1 */
 			      <0x44010c1c 0x45c>,
 				/* IMCR430-IMCR495 registers on siul2_1 */
-			      <0x440110f8 0x108>;
+			      <0x440110f8 0x108>,
+				/* PGPDO registers on siul2_0 */
+			      <0x4009d700 0x10>,
+				/* PGPDI registers on siul2_0 */
+			      <0x4009d740 0x10>,
+				/* PGPDO registers on siul2_1 */
+			      <0x44011700 0x18>,
+				/* PGPDI registers on siul2_1 */
+			      <0x44011740 0x18>,
+				/* EIRQ window: DISR0..IFEER0 */
+			      <0x44010010 0x34>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl 0 0 102>,
+					<&pinctrl 112 112 79>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>;
 
 			jtag_pins: jtag-pins {
 				jtag-grp0 {
diff --git a/arch/arm64/boot/dts/freescale/s32g3.dtsi b/arch/arm64/boot/dts/freescale/s32g3.dtsi
index 22e80fc03f9c..129d6ad8e5c6 100644
--- a/arch/arm64/boot/dts/freescale/s32g3.dtsi
+++ b/arch/arm64/boot/dts/freescale/s32g3.dtsi
@@ -193,7 +193,26 @@ pinctrl: pinctrl@4009c240 {
 				/* IMCR119-IMCR397 registers on siul2_1 */
 			      <0x44010c1c 0x45c>,
 				/* IMCR430-IMCR495 registers on siul2_1 */
-			      <0x440110f8 0x108>;
+			      <0x440110f8 0x108>,
+				/* PGPDO registers on siul2_0 */
+			      <0x4009d700 0x10>,
+				/* PGPDI registers on siul2_0 */
+			      <0x4009d740 0x10>,
+				/* PGPDO registers on siul2_1 */
+			      <0x44011700 0x18>,
+				/* PGPDI registers on siul2_1 */
+			      <0x44011740 0x18>,
+				/* EIRQ window: DISR0..IFEER0 */
+			      <0x44010010 0x34>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl 0 0 102>,
+					<&pinctrl 112 112 79>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>;
 
 			jtag_pins: jtag-pins {
 				jtag-grp0 {
-- 
2.34.1



^ permalink raw reply related

* [PATCH] dt-bindings: PCI: mediatek-gen3: Add support for MT8189 SoC
From: Louis-Alexis Eyraud @ 2026-07-01 15:27 UTC (permalink / raw)
  To: Ryder Lee, Bjorn Helgaas, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Jianjun Wang
  Cc: kernel, linux-pci, linux-mediatek, devicetree, linux-kernel,
	linux-arm-kernel, Louis-Alexis Eyraud

Add compatible for MT8189 PCIe Gen3 controller, that is compatible with
the one found MT8192.

Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
 Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
index 4db700fc36ba..fbc0378392d4 100644
--- a/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie-gen3.yaml
@@ -51,6 +51,7 @@ properties:
               - mediatek,mt7981-pcie
               - mediatek,mt7986-pcie
               - mediatek,mt8188-pcie
+              - mediatek,mt8189-pcie
               - mediatek,mt8195-pcie
           - const: mediatek,mt8192-pcie
       - items:
@@ -193,6 +194,7 @@ allOf:
           contains:
             enum:
               - mediatek,mt8188-pcie
+              - mediatek,mt8189-pcie
               - mediatek,mt8195-pcie
     then:
       properties:

---
base-commit: ba7c57499e5999aeae8dd4f954eb2600589d80aa
change-id: 20260701-mt8189-dt-bindings-pcie-283bb19944bc

Best regards,
-- 
Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>



^ permalink raw reply related

* Re: [PATCH v2 6/6] KVM: arm64: ptdump: Introduce the shadow ptdump file
From: Leonardo Bras @ 2026-07-01 15:28 UTC (permalink / raw)
  To: Wei-Lin Chang
  Cc: Leonardo Bras, linux-arm-kernel, kvmarm, linux-kernel,
	Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Itaru Kitayama, Sebastian Ene
In-Reply-To: <20260630121005.1130996-7-weilin.chang@arm.com>

On Tue, Jun 30, 2026 at 01:10:05PM +0100, Wei-Lin Chang wrote:
> Create a ptdump file for all shadow page tables. It will dump out all
> valid shadow page tables at the time of request, with the mmu's index,
> guest VTCR_EL2, VTTBR_EL2, and whether the guest stage-2 is enabled or
> not.
> 
> Also detach the nested mmu array under the mmu_lock in
> kvm_arch_flush_shadow_all() so readers cannot race with the array being
> removed, then free the old array after dropping the lock.

Out of curiosity: why drop the lock before kfree'ing ?

Thanks!
Leo

> 
> Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
> ---
>  arch/arm64/kvm/nested.c | 12 ++++++--
>  arch/arm64/kvm/ptdump.c | 61 ++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 69 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
> index 6435efd65cb5..17a180ddf6ca 100644
> --- a/arch/arm64/kvm/nested.c
> +++ b/arch/arm64/kvm/nested.c
> @@ -1283,6 +1283,7 @@ void kvm_nested_s2_flush(struct kvm *kvm)
>  
>  void kvm_arch_flush_shadow_all(struct kvm *kvm)
>  {
> +	struct kvm_s2_mmu *mmus;
>  	int i;
>  
>  	for (i = 0; i < kvm->arch.nested_mmus_size; i++) {
> @@ -1291,9 +1292,14 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm)
>  		if (!WARN_ON(atomic_read(&mmu->refcnt)))
>  			kvm_free_stage2_pgd(mmu);
>  	}
> -	kvfree(kvm->arch.nested_mmus);
> -	kvm->arch.nested_mmus = NULL;
> -	kvm->arch.nested_mmus_size = 0;
> +
> +	scoped_guard(write_lock, &kvm->mmu_lock) {
> +		mmus = kvm->arch.nested_mmus;
> +		kvm->arch.nested_mmus = NULL;
> +		kvm->arch.nested_mmus_size = 0;
> +	}
> +
> +	kvfree(mmus);
>  	kvm_uninit_stage2_mmu(kvm);
>  }
>  
> diff --git a/arch/arm64/kvm/ptdump.c b/arch/arm64/kvm/ptdump.c
> index 40f93b7c7ad9..1649eaa75798 100644
> --- a/arch/arm64/kvm/ptdump.c
> +++ b/arch/arm64/kvm/ptdump.c
> @@ -181,6 +181,50 @@ static int kvm_ptdump_guest_canonical_show(struct seq_file *m, void *unused)
>  	return 0;
>  }
>  
> +static int kvm_ptdump_guest_nested_show(struct seq_file *m, void *unused)
> +{
> +	int ret = 0, i;
> +	struct kvm_ptdump_guest_state *st = m->private;
> +	struct kvm *kvm = st->kvm;
> +	struct kvm_pgtable_walker walker = (struct kvm_pgtable_walker) {
> +		.cb	= kvm_ptdump_visitor,
> +		.arg	= &st->parser_state,
> +		.flags	= KVM_PGTABLE_WALK_LEAF,
> +	};
> +
> +	guard(write_lock)(&kvm->mmu_lock);
> +
> +	if (!kvm->arch.nested_mmus)
> +		return 0;
> +
> +	for (i = 0; i < kvm->arch.nested_mmus_size; i++) {
> +		struct kvm_s2_mmu *mmu = &kvm->arch.nested_mmus[i];
> +
> +		if (!mmu->pgt)
> +			continue;
> +
> +		if (kvm_s2_mmu_valid(mmu)) {
> +			memset(st, 0, sizeof(*st));
> +			ret = kvm_ptdump_parser_init(st, kvm, mmu->pgt);
> +			if (ret)
> +				return ret;
> +			st->parser_state = (struct ptdump_pg_state) {
> +				.marker		= &st->ipa_marker[0],
> +				.level		= -1,
> +				.pg_level	= &st->level[0],
> +				.seq		= m,
> +			};
> +			seq_printf(m, "nested mmu %d VTCR: 0x%016llx VTTBR: 0x%016llx s2: %s\n",
> +				   i, mmu->tlb_vtcr, mmu->tlb_vttbr,
> +				   mmu->nested_stage2_enabled ? "enabled" : "disabled");
> +			ret = kvm_pgtable_walk(mmu->pgt, 0, BIT(mmu->pgt->ia_bits), &walker);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +	return ret;
> +}
> +
>  static int kvm_ptdump_guest_open(struct inode *m, struct file *file,
>  				 int (*show)(struct seq_file *, void *))
>  {
> @@ -212,6 +256,11 @@ static int kvm_ptdump_guest_canonical_open(struct inode *m, struct file *file)
>  	return kvm_ptdump_guest_open(m, file, kvm_ptdump_guest_canonical_show);
>  }
>  
> +static int kvm_ptdump_guest_nested_open(struct inode *m, struct file *file)
> +{
> +	return kvm_ptdump_guest_open(m, file, kvm_ptdump_guest_nested_show);
> +}
> +
>  static int kvm_ptdump_guest_close(struct inode *m, struct file *file)
>  {
>  	struct kvm *kvm = m->i_private;
> @@ -230,6 +279,13 @@ static const struct file_operations kvm_ptdump_guest_canonical_fops = {
>  	.release	= kvm_ptdump_guest_close,
>  };
>  
> +static const struct file_operations kvm_ptdump_guest_nested_fops = {
> +	.open		= kvm_ptdump_guest_nested_open,
> +	.read		= seq_read,
> +	.llseek		= seq_lseek,
> +	.release	= kvm_ptdump_guest_close,
> +};
> +
>  static int kvm_pgtable_range_show(struct seq_file *m, void *unused)
>  {
>  	struct kvm *kvm = m->private;
> @@ -307,6 +363,9 @@ void kvm_s2_ptdump_create_debugfs(struct kvm *kvm)
>  			    kvm, &kvm_pgtable_range_fops);
>  	debugfs_create_file("stage2_levels", 0400, kvm->debugfs_dentry,
>  			    kvm, &kvm_pgtable_levels_fops);
> -	if (cpus_have_final_cap(ARM64_HAS_NESTED_VIRT))
> +	if (cpus_have_final_cap(ARM64_HAS_NESTED_VIRT)) {
>  		kvm->arch.debugfs_nv_dentry = debugfs_create_dir("nested", kvm->debugfs_dentry);
> +		debugfs_create_file("shadow_page_tables", 0400, kvm->arch.debugfs_nv_dentry,
> +				    kvm, &kvm_ptdump_guest_nested_fops);
> +	}
>  }
> -- 
> 2.43.0
> 


^ permalink raw reply

* Re: [PATCH v3] ARM: breakpoint: CFI breakpoints only on demand
From: Sami Tolvanen @ 2026-07-01 15:30 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Russell King, Nathan Chancellor, Kees Cook, linux-arm-kernel,
	linux-kernel, stable, slipher
In-Reply-To: <CAD++jL=_j69pFuM+vv-8Q7x4VA=PUX8iV1Yfw4YkdxGDFo9D1g@mail.gmail.com>

On Wed, Jul 1, 2026 at 5:50 AM Linus Walleij <linusw@kernel.org> wrote:
>
> On Wed, Jul 1, 2026 at 1:10 PM Russell King <linux@armlinux.org.uk> wrote:
>
> > Have the LLVM compiler people responded to this bug yet? What is their
> > plan with the silly choice of BKPT usage for CFI failure?
>
> Haven't heard anything.

LLVM's generic KCFI pass uses a debug trap as an architecture-agnostic
way to trap on failure. It shouldn't be a problem to switch to
something else now that we have an ARM back-end implementation thanks
to Kees.

> My tentative plan is to follow this up with a patch to LLVM (and I guess
> then later also GCC...) to enable handling CFI faults with a read
> to the guard region at 0xffc00000 instead of using BKPT so we get a
> good old predictable segfault instead. I was thinking something like
>
> -fsanitize-kcfi-guard-region-address=0xffc00000
>
> My idea is that the unwinder can then see that this is caused by KCFI
> and act accordingly, but already the existing stack trace should make
> it pretty obvious what happened.
>
> It's the best I can think of at least, haven't seen any other ideas.

Note that for X86 and RISC-V the compiler emits a list of CFI trap
locations in the .kcfi_traps section (see CONFIG_ARCH_USES_CFI_TRAPS),
which the kernel uses to figure out if an exception was caused by a
CFI failure. I'm not sure if this is useful in your case, but the
plumbing is already in the compiler and could also be enabled in the
ARM implementation if needed.

Sami


^ permalink raw reply

* [PATCH] dt-bindings: phy: mediatek,tphy: Add support for MT8189 SoC
From: Louis-Alexis Eyraud @ 2026-07-01 15:36 UTC (permalink / raw)
  To: Chunfeng Yun, Vinod Koul, Neil Armstrong, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: kernel, linux-arm-kernel, linux-mediatek, linux-phy, devicetree,
	linux-kernel, Louis-Alexis Eyraud

Add a compatible string for the MediaTek MT8189 SoC, that integrates a
MediaTek generic T-PHY version 3.

Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
 Documentation/devicetree/bindings/phy/mediatek,tphy.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
index ff5c77ef1176..8b240cfd537d 100644
--- a/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
+++ b/Documentation/devicetree/bindings/phy/mediatek,tphy.yaml
@@ -90,6 +90,7 @@ properties:
       - items:
           - enum:
               - mediatek,mt8188-tphy
+              - mediatek,mt8189-tphy
               - mediatek,mt8195-tphy
           - const: mediatek,generic-tphy-v3
       - const: mediatek,mt2701-u3phy

---
base-commit: ba7c57499e5999aeae8dd4f954eb2600589d80aa
change-id: 20260701-mt8189-dt-bindings-tphy-4b661e3a9e50

Best regards,
-- 
Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>



^ permalink raw reply related

* [PATCH 04/42] drm/mediatek: Move mtk_ddp_comp_type enumeration to mtk-mmsys.h
From: AngeloGioacchino Del Regno @ 2026-07-01 12:20 UTC (permalink / raw)
  To: chunkuang.hu
  Cc: p.zabel, airlied, simona, maarten.lankhorst, mripard, tzimmermann,
	robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
	dri-devel, linux-mediatek, devicetree, linux-kernel,
	linux-arm-kernel, justin.yeh, jason-jh.lin, kernel
In-Reply-To: <20260701122057.19648-1-angelogioacchino.delregno@collabora.com>

In preparation for a major refactoring of MMSYS, MUTEX and of
mediatek-drm, move the mtk_ddp_comp_type enumeration to the
mtk-mmsys.h header, as this will be shared between multiple
MediaTek multimedia related drivers.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/gpu/drm/mediatek/mtk_ddp_comp.h | 25 ------------------
 include/linux/soc/mediatek/mtk-mmsys.h  | 34 +++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
index 99bf1e1015da..bbc66072fe6b 100644
--- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
@@ -22,31 +22,6 @@ struct mtk_plane_state;
 struct drm_crtc_state;
 struct drm_dsc_config;
 
-enum mtk_ddp_comp_type {
-	MTK_DISP_AAL,
-	MTK_DISP_BLS,
-	MTK_DISP_CCORR,
-	MTK_DISP_COLOR,
-	MTK_DISP_DITHER,
-	MTK_DISP_DSC,
-	MTK_DISP_GAMMA,
-	MTK_DISP_MERGE,
-	MTK_DISP_MUTEX,
-	MTK_DISP_OD,
-	MTK_DISP_OVL,
-	MTK_DISP_OVL_2L,
-	MTK_DISP_OVL_ADAPTOR,
-	MTK_DISP_POSTMASK,
-	MTK_DISP_PWM,
-	MTK_DISP_RDMA,
-	MTK_DISP_UFOE,
-	MTK_DISP_WDMA,
-	MTK_DPI,
-	MTK_DP_INTF,
-	MTK_DSI,
-	MTK_DDP_COMP_TYPE_MAX,
-};
-
 struct mtk_ddp_comp;
 struct cmdq_pkt;
 struct mtk_ddp_comp_funcs {
diff --git a/include/linux/soc/mediatek/mtk-mmsys.h b/include/linux/soc/mediatek/mtk-mmsys.h
index 4885b065b849..3ddfdeac658d 100644
--- a/include/linux/soc/mediatek/mtk-mmsys.h
+++ b/include/linux/soc/mediatek/mtk-mmsys.h
@@ -84,6 +84,40 @@ enum mtk_ddp_comp_id {
 	DDP_COMPONENT_ID_MAX,
 };
 
+enum mtk_ddp_comp_type {
+	/* DISP Components */
+	MTK_DISP_AAL,
+	MTK_DISP_BLS,
+	MTK_DISP_CCORR,
+	MTK_DISP_COLOR,
+	MTK_DISP_DITHER,
+	MTK_DISP_DSC,
+	MTK_DISP_ETHDR_MIXER,
+	MTK_DISP_GAMMA,
+	MTK_DISP_MERGE,
+	MTK_DISP_MUTEX,
+	MTK_DISP_OD,
+	MTK_DISP_OVL,
+	MTK_DISP_OVL_2L,
+	MTK_DISP_OVL_ADAPTOR,
+	MTK_DISP_PADDING,
+	MTK_DISP_POSTMASK,
+	MTK_DISP_PWM,
+	MTK_DISP_RDMA,
+	MTK_DISP_UFOE,
+	MTK_DISP_WDMA,
+
+	/* MDP Components */
+	MTK_DISP_MDP_RDMA,
+
+	/* Keep Display outputs at the end for readability */
+	MTK_DPI,
+	MTK_DP_INTF,
+	MTK_DSI,
+
+	MTK_DDP_COMP_TYPE_MAX
+};
+
 void mtk_mmsys_ddp_connect(struct device *dev,
 			   enum mtk_ddp_comp_id cur,
 			   enum mtk_ddp_comp_id next);
-- 
2.54.0



^ permalink raw reply related

* [PATCH 02/42] drm/mediatek: Export OVL formats definitions and format conversion API
From: AngeloGioacchino Del Regno @ 2026-07-01 12:20 UTC (permalink / raw)
  To: chunkuang.hu
  Cc: p.zabel, airlied, simona, maarten.lankhorst, mripard, tzimmermann,
	robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
	dri-devel, linux-mediatek, devicetree, linux-kernel,
	linux-arm-kernel, justin.yeh, jason-jh.lin, kernel, Nancy Lin,
	Paul-pl Chen
In-Reply-To: <20260701122057.19648-1-angelogioacchino.delregno@collabora.com>

From: Nancy Lin <nancy.lin@mediatek.com>

In upcoming SoCs, the OVL component will be divided into multiple
smaller hardware units to enhance flexibility. To facilitate this
transition, the OVL format definitions and format conversion API
should be exported for reuse across these units.

Signed-off-by: Nancy Lin <nancy.lin@mediatek.com>
Signed-off-by: Paul-pl Chen <paul-pl.chen@mediatek.com>
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 192 ++++++++++++++----------
 drivers/gpu/drm/mediatek/mtk_disp_ovl.h |  19 +++
 2 files changed, 132 insertions(+), 79 deletions(-)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.h

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 87c2b5e6d6b0..9ded20202191 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -4,7 +4,6 @@
  */
 
 #include <drm/drm_blend.h>
-#include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 
 #include <linux/clk.h>
@@ -18,6 +17,7 @@
 #include "mtk_crtc.h"
 #include "mtk_ddp_comp.h"
 #include "mtk_disp_drv.h"
+#include "mtk_disp_ovl.h"
 #include "mtk_drm_drv.h"
 
 #define DISP_REG_OVL_INTEN			0x0004
@@ -62,22 +62,16 @@
 /* OVL_CON_RGB_SWAP works only if OVL_CON_CLRFMT_MAN is enabled */
 #define OVL_CON_RGB_SWAP	BIT(25)
 
-#define OVL_CON_CLRFMT_RGB	(1 << 12)
-#define OVL_CON_CLRFMT_ARGB8888	(2 << 12)
-#define OVL_CON_CLRFMT_RGBA8888	(3 << 12)
-#define OVL_CON_CLRFMT_ABGR8888	(OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_BGRA8888	(OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_UYVY	(4 << 12)
-#define OVL_CON_CLRFMT_YUYV	(5 << 12)
-#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
-#define OVL_CON_CLRFMT_PARGB8888 ((3 << 12) | OVL_CON_CLRFMT_MAN)
-#define OVL_CON_CLRFMT_PABGR8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_RGB_SWAP)
-#define OVL_CON_CLRFMT_PBGRA8888 (OVL_CON_CLRFMT_PARGB8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_PRGBA8888 (OVL_CON_CLRFMT_PABGR8888 | OVL_CON_BYTE_SWAP)
-#define OVL_CON_CLRFMT_RGB565(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
-					0 : OVL_CON_CLRFMT_RGB)
-#define OVL_CON_CLRFMT_RGB888(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
-					OVL_CON_CLRFMT_RGB : 0)
+#define OVL_CON_CLRFMT_SHIFT			(12)
+#define OVL_CON_CLRFMT_RGB565(shift)		(0 << (shift))
+#define OVL_CON_CLRFMT_RGB888(shift)		(1 << (shift))
+#define OVL_CON_CLRFMT_ARGB8888(shift)		(2 << (shift))
+#define OVL_CON_CLRFMT_RGBA8888(shift)		(3 << (shift))
+#define OVL_CON_CLRFMT_UYVY(shift)		(4 << (shift))
+#define OVL_CON_CLRFMT_YUYV(shift)		(5 << (shift))
+#define OVL_CON_MTX_YUV_TO_RGB			(6 << 16)
+#define OVL_CON_CLRFMT_PARGB8888(shift, man)	((3 << (shift)) | (man))
+
 #define	OVL_CON_AEN		BIT(8)
 #define	OVL_CON_ALPHA		0xff
 #define	OVL_CON_VIRT_FLIP	BIT(9)
@@ -85,21 +79,6 @@
 
 #define OVL_COLOR_ALPHA		GENMASK(31, 24)
 
-static inline bool is_10bit_rgb(u32 fmt)
-{
-	switch (fmt) {
-	case DRM_FORMAT_XRGB2101010:
-	case DRM_FORMAT_ARGB2101010:
-	case DRM_FORMAT_RGBX1010102:
-	case DRM_FORMAT_RGBA1010102:
-	case DRM_FORMAT_XBGR2101010:
-	case DRM_FORMAT_ABGR2101010:
-	case DRM_FORMAT_BGRX1010102:
-	case DRM_FORMAT_BGRA1010102:
-		return true;
-	}
-	return false;
-}
 
 static const u32 mt8173_ovl_formats[] = {
 	DRM_FORMAT_XRGB8888,
@@ -115,7 +94,9 @@ static const u32 mt8173_ovl_formats[] = {
 	DRM_FORMAT_YUYV,
 };
 
-static const u32 mt8195_ovl_formats[] = {
+static const size_t mt8173_ovl_formats_len = ARRAY_SIZE(mt8173_ovl_formats);
+
+const u32 mt8195_ovl_formats[] = {
 	DRM_FORMAT_XRGB8888,
 	DRM_FORMAT_ARGB8888,
 	DRM_FORMAT_XRGB2101010,
@@ -139,6 +120,8 @@ static const u32 mt8195_ovl_formats[] = {
 	DRM_FORMAT_YUYV,
 };
 
+const size_t mt8195_ovl_formats_len = ARRAY_SIZE(mt8195_ovl_formats);
+
 struct mtk_disp_ovl_data {
 	unsigned int addr;
 	unsigned int gmc_bits;
@@ -168,6 +151,22 @@ struct mtk_disp_ovl {
 	void				*vblank_cb_data;
 };
 
+bool mtk_ovl_is_10bit_rgb(unsigned int fmt)
+{
+	switch (fmt) {
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_BGRX1010102:
+	case DRM_FORMAT_BGRA1010102:
+		return true;
+	}
+	return false;
+}
+
 static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
 {
 	struct mtk_disp_ovl *priv = dev_id;
@@ -303,7 +302,7 @@ static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
 	if (!ovl->data->supports_clrfmt_ext)
 		return;
 
-	if (is_10bit_rgb(format))
+	if (mtk_ovl_is_10bit_rgb(format))
 		bit_depth = OVL_CON_CLRFMT_10_BIT;
 
 	mtk_ddp_write_mask(cmdq_pkt, OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx),
@@ -402,70 +401,97 @@ void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
 		      DISP_REG_OVL_RDMA_CTRL(idx));
 }
 
-static unsigned int mtk_ovl_fmt_convert(struct mtk_disp_ovl *ovl,
-					struct mtk_plane_state *state)
+unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
+				 bool fmt_rgb565_is_0, bool color_convert,
+				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap)
 {
-	unsigned int fmt = state->pending.format;
-	unsigned int blend_mode = DRM_MODE_BLEND_COVERAGE;
-
-	/*
-	 * For the platforms where OVL_CON_CLRFMT_MAN is defined in the hardware data sheet
-	 * and supports premultiplied color formats, such as OVL_CON_CLRFMT_PARGB8888.
-	 *
-	 * Check blend_modes in the driver data to see if premultiplied mode is supported.
-	 * If not, use coverage mode instead to set it to the supported color formats.
-	 *
-	 * Current DRM assumption is that alpha is default premultiplied, so the bitmask of
-	 * blend_modes must include BIT(DRM_MODE_BLEND_PREMULTI). Otherwise, mtk_plane_init()
-	 * will get an error return from drm_plane_create_blend_mode_property() and
-	 * state->base.pixel_blend_mode should not be used.
-	 */
-	if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
-		blend_mode = state->base.pixel_blend_mode;
+	unsigned int con = 0;
+	bool need_byte_swap = false, need_rgb_swap = false;
 
 	switch (fmt) {
 	default:
 	case DRM_FORMAT_RGB565:
-		return OVL_CON_CLRFMT_RGB565(ovl);
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
+	break;
 	case DRM_FORMAT_BGR565:
-		return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP;
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB565(clrfmt_shift) : OVL_CON_CLRFMT_RGB888(clrfmt_shift);
+		need_byte_swap = true;	/* RGB565 -> BGR565 */
+	break;
 	case DRM_FORMAT_RGB888:
-		return OVL_CON_CLRFMT_RGB888(ovl);
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
+	break;
 	case DRM_FORMAT_BGR888:
-		return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
+		con = fmt_rgb565_is_0 ?
+			OVL_CON_CLRFMT_RGB888(clrfmt_shift) : OVL_CON_CLRFMT_RGB565(clrfmt_shift);
+		need_byte_swap = true;	/* RGB888 -> BGR888 */
+	break;
 	case DRM_FORMAT_RGBX8888:
 	case DRM_FORMAT_RGBA8888:
 	case DRM_FORMAT_RGBX1010102:
 	case DRM_FORMAT_RGBA1010102:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_RGBA8888 :
-		       OVL_CON_CLRFMT_PRGBA8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
+			need_rgb_swap = true;	/* PBGRA8888 -> PRGBA8888 */
+		}
+	break;
 	case DRM_FORMAT_BGRX8888:
 	case DRM_FORMAT_BGRA8888:
 	case DRM_FORMAT_BGRX1010102:
 	case DRM_FORMAT_BGRA1010102:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_BGRA8888 :
-		       OVL_CON_CLRFMT_PBGRA8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_RGBA8888(clrfmt_shift);
+			need_byte_swap = true;	/* RGB8888 -> BGR8888 */
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_byte_swap = true;	/* PARGB8888 -> PBGRA8888 */
+		}
+	break;
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_ARGB8888:
 	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_ARGB2101010:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_ARGB8888 :
-		       OVL_CON_CLRFMT_PARGB8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE)
+			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
+		else
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+	break;
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ABGR8888:
 	case DRM_FORMAT_XBGR2101010:
 	case DRM_FORMAT_ABGR2101010:
-		return blend_mode == DRM_MODE_BLEND_COVERAGE ?
-		       OVL_CON_CLRFMT_ABGR8888 :
-		       OVL_CON_CLRFMT_PABGR8888;
+		if (blend_mode == DRM_MODE_BLEND_COVERAGE) {
+			con = OVL_CON_CLRFMT_ARGB8888(clrfmt_shift);
+			need_rgb_swap = true;	/* ARGB8888 -> ABGR8888 */
+		} else {
+			con = OVL_CON_CLRFMT_PARGB8888(clrfmt_shift, clrfmt_man);
+			need_rgb_swap = true;	/* PARGB8888 -> PABGR8888 */
+		}
+	break;
 	case DRM_FORMAT_UYVY:
-		return OVL_CON_CLRFMT_UYVY | OVL_CON_MTX_YUV_TO_RGB;
+		con = OVL_CON_CLRFMT_UYVY(clrfmt_shift);
+		if (color_convert)
+			con |= OVL_CON_MTX_YUV_TO_RGB;
+	break;
 	case DRM_FORMAT_YUYV:
-		return OVL_CON_CLRFMT_YUYV | OVL_CON_MTX_YUV_TO_RGB;
+		con = OVL_CON_CLRFMT_YUYV(clrfmt_shift);
+		if (color_convert)
+			con |= OVL_CON_MTX_YUV_TO_RGB;
+	break;
 	}
+
+	if (need_byte_swap)
+		con |= byte_swap;
+
+	if (need_rgb_swap)
+		con |= rgb_swap;
+
+	return con;
 }
 
 static void mtk_ovl_afbc_layer_config(struct mtk_disp_ovl *ovl,
@@ -512,7 +538,15 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
 		return;
 	}
 
-	con = mtk_ovl_fmt_convert(ovl, state);
+	if (ovl->data->blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
+		con = mtk_ovl_fmt_convert(fmt, blend_mode,
+					  ovl->data->fmt_rgb565_is_0, true, OVL_CON_CLRFMT_SHIFT,
+					  OVL_CON_CLRFMT_MAN, OVL_CON_BYTE_SWAP, OVL_CON_RGB_SWAP);
+	else
+		con = mtk_ovl_fmt_convert(fmt, DRM_MODE_BLEND_COVERAGE,
+					  ovl->data->fmt_rgb565_is_0, true, OVL_CON_CLRFMT_SHIFT,
+					  OVL_CON_CLRFMT_MAN, OVL_CON_BYTE_SWAP, OVL_CON_RGB_SWAP);
+
 	if (state->base.fb) {
 		con |= state->base.alpha & OVL_CON_ALPHA;
 
@@ -674,7 +708,7 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
 	.layer_nr = 4,
 	.fmt_rgb565_is_0 = false,
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8167_ovl_driver_data = {
@@ -693,7 +727,7 @@ static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
 	.layer_nr = 4,
 	.fmt_rgb565_is_0 = true,
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
@@ -702,7 +736,7 @@ static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
 	.layer_nr = 4,
 	.fmt_rgb565_is_0 = true,
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
@@ -711,7 +745,7 @@ static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
 	.layer_nr = 2,
 	.fmt_rgb565_is_0 = true,
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
@@ -724,7 +758,7 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
 		       BIT(DRM_MODE_BLEND_COVERAGE) |
 		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
@@ -737,7 +771,7 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
 		       BIT(DRM_MODE_BLEND_COVERAGE) |
 		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
 	.formats = mt8173_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8173_ovl_formats),
+	.num_formats = mt8173_ovl_formats_len,
 };
 
 static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
@@ -751,7 +785,7 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
 		       BIT(DRM_MODE_BLEND_COVERAGE) |
 		       BIT(DRM_MODE_BLEND_PIXEL_NONE),
 	.formats = mt8195_ovl_formats,
-	.num_formats = ARRAY_SIZE(mt8195_ovl_formats),
+	.num_formats = mt8195_ovl_formats_len,
 	.supports_clrfmt_ext = true,
 };
 
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.h b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
new file mode 100644
index 000000000000..919498496bb6
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#ifndef __MTK_DISP_OVL_H__
+#define __MTK_DISP_OVL_H__
+
+#include <drm/drm_fourcc.h>
+
+extern const u32 mt8195_ovl_formats[];
+extern const size_t mt8195_ovl_formats_len;
+
+bool mtk_ovl_is_10bit_rgb(unsigned int fmt);
+unsigned int mtk_ovl_fmt_convert(unsigned int fmt, unsigned int blend_mode,
+				 bool fmt_rgb565_is_0, bool color_convert,
+				 u8 clrfmt_shift, u32 clrfmt_man, u32 byte_swap, u32 rgb_swap);
+
+#endif
-- 
2.54.0



^ permalink raw reply related

* [PATCH 01/12] dt-bindings: phy: Document MT8195 and MT8196 DisplayPort PHYs
From: AngeloGioacchino Del Regno @ 2026-07-01 12:19 UTC (permalink / raw)
  To: chunfeng.yun
  Cc: vkoul, neil.armstrong, robh, krzk+dt, conor+dt, matthias.bgg,
	angelogioacchino.delregno, chunkuang.hu, p.zabel, justin.yeh,
	linux-arm-kernel, linux-mediatek, linux-phy, devicetree,
	linux-kernel, dri-devel, kernel
In-Reply-To: <20260701122008.19509-1-angelogioacchino.delregno@collabora.com>

This adds bindings for the DisplayPort and Embedded DisplayPort
PHYs found in the MediaTek MT8195 SoC (and variants of) and for
the Embedded DisplayPort found in the MT8196 SoC (and variants).

This PHY supports varying impedance calibrations for the various
signals to reach an optimal EYE signal pattern for any specific
board(s), especially useful for very high bitrates such as HBR3
and higher, depending on board design.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 .../bindings/phy/mediatek,mt8195-dp-phy.yaml  | 77 +++++++++++++++++++
 1 file changed, 77 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/mediatek,mt8195-dp-phy.yaml

diff --git a/Documentation/devicetree/bindings/phy/mediatek,mt8195-dp-phy.yaml b/Documentation/devicetree/bindings/phy/mediatek,mt8195-dp-phy.yaml
new file mode 100644
index 000000000000..5847963a7085
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/mediatek,mt8195-dp-phy.yaml
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/mediatek,mt8195-dp-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek SoC DisplayPort Transmitter PHY
+
+maintainers:
+  - AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt8195-dp-phy
+      - mediatek,mt8196-edp-phy
+
+  reg:
+    maxItems: 1
+
+  "#phy-cells":
+    const: 0
+
+  nvmem-cells:
+    description: PHY calibrations from eFuse for optimal EYE signal pattern
+    items:
+      - description: PHY-Global Reference Bias trim
+      - description: PHY-Global AUX Transmitter clock impedance adjustment
+      - description: Lane 0 Transmitter impedance selection (P-MOSFET)
+      - description: Lane 0 Transmitter impedance selection (N-MOSFET)
+      - description: Lane 1 Transmitter impedance selection (P-MOSFET)
+      - description: Lane 1 Transmitter impedance selection (N-MOSFET)
+      - description: Lane 2 Transmitter impedance selection (P-MOSFET)
+      - description: Lane 2 Transmitter impedance selection (N-MOSFET)
+      - description: Lane 3 Transmitter impedance selection (P-MOSFET)
+      - description: Lane 3 Transmitter impedance selection (N-MOSFET)
+
+  nvmem-cell-names:
+    items:
+      - const: rbias-trim
+      - const: impedance-txclk
+      - const: impedance-lane0p
+      - const: impedance-lane0n
+      - const: impedance-lane1p
+      - const: impedance-lane1n
+      - const: impedance-lane2p
+      - const: impedance-lane2n
+      - const: impedance-lane3p
+      - const: impedance-lane3n
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    phy@1c500000 {
+        compatible = "mediatek,mt8195-dp-phy";
+        reg = <0 0x1c500000 0 0x2000>;
+        #phy-cells = <0>;
+        nvmem-cells = <&edp_glb_bias_trim>, <&edp_clktx_impsel>,
+                      <&edp_imp_ln0_pmos>, <&edp_imp_ln0_nmos>,
+                      <&edp_imp_ln1_pmos>, <&edp_imp_ln1_nmos>,
+                      <&edp_imp_ln2_pmos>, <&edp_imp_ln2_nmos>,
+                      <&edp_imp_ln3_pmos>, <&edp_imp_ln3_nmos>;
+        nvmem-cell-names = "rbias-trim", "impedance-txclk",
+                           "impedance-lane0p", "impedance-lane0n",
+                           "impedance-lane1p", "impedance-lane1n",
+                           "impedance-lane2p", "impedance-lane2n",
+                           "impedance-lane3p", "impedance-lane3n";
+    };
-- 
2.54.0



^ permalink raw reply related

* Re: [PATCH v6 2/2] clk: amlogic: Add A9 peripherals clock controller driver
From: Jerome Brunet @ 2026-07-01 15:41 UTC (permalink / raw)
  To: Jian Hu via B4 Relay
  Cc: Neil Armstrong, Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Xianwei Zhao, Kevin Hilman,
	Martin Blumenstingl, Brian Masney, jian.hu, linux-amlogic,
	linux-clk, devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20260701-a9_peripherals-v6-2-9630f39879e5@amlogic.com>

On mer. 01 juil. 2026 at 16:30, Jian Hu via B4 Relay <devnull+jian.hu.amlogic.com@kernel.org> wrote:

> From: Jian Hu <jian.hu@amlogic.com>
>
> Add the peripherals clock controller driver for the Amlogic A9 SoC family.
>
> Signed-off-by: Jian Hu <jian.hu@amlogic.com>
> ---
>  drivers/clk/meson/Kconfig          |   15 +
>  drivers/clk/meson/Makefile         |    1 +
>  drivers/clk/meson/a9-peripherals.c | 2089 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 2105 insertions(+)
>
> diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
> index b71299898197..5152868e2ee6 100644
> --- a/drivers/clk/meson/Kconfig
> +++ b/drivers/clk/meson/Kconfig
> @@ -132,6 +132,21 @@ config COMMON_CLK_A1_PERIPHERALS
>  	  device, A1 SoC Family. Say Y if you want A1 Peripherals clock
>  	  controller to work.
>  
> +config COMMON_CLK_A9_PERIPHERALS
> +	tristate "Amlogic A9 SoC peripherals clock controller support"
> +	depends on ARM64 || COMPILE_TEST
> +	default ARCH_MESON
> +	select COMMON_CLK_MESON_REGMAP
> +	select COMMON_CLK_MESON_CLKC_UTILS
> +	select COMMON_CLK_MESON_DUALDIV
> +	select COMMON_CLK_MESON_VID_PLL_DIV
> +	imply COMMON_CLK_SCMI
> +	imply COMMON_CLK_A9_PLL

As mentioned by Sashiko, This is problematic because the symbol does
exist yet. This should be removed for now. It can be added back when
support for the PLL controllers is added

I'm otherwise happy with this version.
If it is ok with you, I'll apply it with the line above removed.

> +	help
> +	  Support for the peripherals clock controller on Amlogic A311Y3 based
> +	  device, AKA A9. Peripherals are required by most peripheral to operate.
> +	  Say Y if you want A9 peripherals clock controller to work.
> +
>  config COMMON_CLK_A9_AO
>  	tristate "Amlogic A9 SoC AO clock controller support"
>  	depends on ARM64 || COMPILE_TEST
> diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
> index f89d027c282c..56b04254eb1a 100644
> --- a/drivers/clk/meson/Makefile
> +++ b/drivers/clk/meson/Makefile
> @@ -19,6 +19,7 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
>  obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
>  obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
>  obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
> +obj-$(CONFIG_COMMON_CLK_A9_PERIPHERALS) += a9-peripherals.o
>  obj-$(CONFIG_COMMON_CLK_A9_AO) += a9-aoclk.o
>  obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
>  obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o
> diff --git a/drivers/clk/meson/a9-peripherals.c b/drivers/clk/meson/a9-peripherals.c
> new file mode 100644
> index 000000000000..b77e35f48c1f
> --- /dev/null
> +++ b/drivers/clk/meson/a9-peripherals.c
> @@ -0,0 +1,2089 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +/*
> + * Copyright (C) 2026 Amlogic, Inc. All rights reserved
> + */
> +
> +#include <dt-bindings/clock/amlogic,a9-peripherals-clkc.h>
> +#include <linux/clk-provider.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include "clk-regmap.h"
> +#include "clk-dualdiv.h"
> +#include "meson-clkc-utils.h"
> +#include "vid-pll-div.h"
> +
> +#define SYS_CLK_EN0_REG0			0x30
> +#define SYS_CLK_EN0_REG1			0x34
> +#define SYS_CLK_EN0_REG2			0x38
> +#define SYS_CLK_EN0_REG3			0x3c
> +#define SD_EMMC_CLK_CTRL0			0x90
> +#define SD_EMMC_CLK_CTRL1			0x94
> +#define PWM_CLK_H_CTRL				0xbc
> +#define PWM_CLK_I_CTRL				0xc0
> +#define PWM_CLK_J_CTRL				0xc4
> +#define PWM_CLK_K_CTRL				0xc8
> +#define PWM_CLK_L_CTRL				0xcc
> +#define PWM_CLK_M_CTRL				0xd0
> +#define PWM_CLK_N_CTRL				0xd4
> +#define SPISG_CLK_CTRL				0x100
> +#define SPISG_CLK_CTRL1				0x104
> +#define SAR_CLK_CTRL				0x150
> +#define AMFC_CLK_CTRL				0x154
> +#define NNA_CLK_CTRL				0x15c
> +#define USB_CLK_CTRL				0x160
> +#define PCIE_TL_CLK_CTRL			0x164
> +#define CMPR_CLK_CTRL				0x168
> +#define DEWARP_CLK_CTRL				0x16c
> +#define SC_CLK_CTRL				0x170
> +#define DPTX_CLK_CTRL				0x178
> +#define ISP_CLK_CTRL				0x17c
> +#define CVE_CLK_CTRL				0x180
> +#define PP_CLK_CTRL				0x184
> +#define GLB_CLK_CTRL				0x188
> +#define USB_CLK_CTRL0				0x18c
> +#define USB_CLK_CTRL1				0x190
> +#define CAN_CLK_CTRL				0x194
> +#define CAN_CLK_CTRL1				0x198
> +#define I3C_CLK_CTRL				0x19c
> +#define TS_CLK_CTRL				0x1a0
> +#define ETH_CLK_CTRL				0x1a4
> +#define GEN_CLK_CTRL				0x1a8
> +#define CLK12_24_CTRL				0x1ac
> +#define MALI_CLK_CTRL				0x200
> +#define MALI_STACK_CLK_CTRL			0x204
> +#define DSPA_CLK_CTRL				0x220
> +#define HEVCF_CLK_CTRL				0x240
> +#define HCODEC_CLK_CTRL				0x244
> +#define VPU_CLK_CTRL				0x260
> +#define VAPB_CLK_CTRL				0x268
> +#define VPU_CLKB_CTRL				0x280
> +#define HDMI_CLK_CTRL				0x284
> +#define HTX_CLK_CTRL				0x28c
> +#define HTX_CLK_CTRL1				0x290
> +#define HRX_CLK_CTRL				0x294
> +#define HRX_CLK_CTRL1				0x298
> +#define HRX_CLK_CTRL2				0x29c
> +#define HRX_CLK_CTRL3				0x2a0
> +#define VID_LOCK_CLK_CTRL			0x2a4
> +#define VDIN_MEAS_CLK_CTRL			0x2a8
> +#define VID_PLL_CLK_DIV				0x2b0
> +#define VID_CLK_CTRL				0x2c0
> +#define VID_CLK_CTRL2				0x2c4
> +#define VID_CLK_DIV				0x2c8
> +#define VIID_CLK_DIV				0x2cc
> +#define VIID_CLK_CTRL				0x2d0
> +#define MIPI_CSI_PHY_CLK_CTRL			0x2e0
> +#define DSI_MEAS_CLK_CTRL			0x2f4
> +
> +#define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata, _table) \
> +	MESON_COMP_SEL(a9_, _name, _reg, _shift, _mask, _pdata, _table, 0, 0)
> +
> +#define A9_COMP_DIV(_name, _reg, _shift, _width) \
> +	MESON_COMP_DIV(a9_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT)
> +
> +#define A9_COMP_GATE(_name, _reg, _bit, _iflags) \
> +	MESON_COMP_GATE(a9_, _name, _reg, _bit, CLK_SET_RATE_PARENT | (_iflags))
> +
> +static const struct clk_parent_data a9_sys_pclk_parents = { .fw_name = "sys" };
> +
> +#define A9_SYS_PCLK(_name, _reg, _bit) \
> +	MESON_PCLK(a9_##_name, _reg, _bit, &a9_sys_pclk_parents, 0)
> +
> +static A9_SYS_PCLK(sys_am_axi,		SYS_CLK_EN0_REG0, 0);
> +static A9_SYS_PCLK(sys_dos,		SYS_CLK_EN0_REG0, 1);
> +static A9_SYS_PCLK(sys_mipi_dsi0,	SYS_CLK_EN0_REG0, 3);
> +static A9_SYS_PCLK(sys_eth_phy,		SYS_CLK_EN0_REG0, 4);
> +static A9_SYS_PCLK(sys_amfc,		SYS_CLK_EN0_REG0, 5);
> +static A9_SYS_PCLK(sys_mali,		SYS_CLK_EN0_REG0, 6);
> +static A9_SYS_PCLK(sys_nna,		SYS_CLK_EN0_REG0, 7);
> +static A9_SYS_PCLK(sys_eth_axi,		SYS_CLK_EN0_REG0, 8);
> +static A9_SYS_PCLK(sys_dp_apb,		SYS_CLK_EN0_REG0, 9);
> +static A9_SYS_PCLK(sys_edptx_apb,	SYS_CLK_EN0_REG0, 10);
> +static A9_SYS_PCLK(sys_u3hsg,		SYS_CLK_EN0_REG0, 11);
> +static A9_SYS_PCLK(sys_aucpu,		SYS_CLK_EN0_REG0, 14);
> +static A9_SYS_PCLK(sys_glb,		SYS_CLK_EN0_REG0, 15);
> +static A9_SYS_PCLK(sys_combo_dphy_apb,	SYS_CLK_EN0_REG0, 17);
> +static A9_SYS_PCLK(sys_hdmirx_apb,	SYS_CLK_EN0_REG0, 18);
> +static A9_SYS_PCLK(sys_hdmirx_pclk,	SYS_CLK_EN0_REG0, 19);
> +static A9_SYS_PCLK(sys_mipi_dsi0_phy,	SYS_CLK_EN0_REG0, 20);
> +static A9_SYS_PCLK(sys_can0,		SYS_CLK_EN0_REG0, 21);
> +static A9_SYS_PCLK(sys_can1,		SYS_CLK_EN0_REG0, 22);
> +static A9_SYS_PCLK(sys_sd_emmc_a,	SYS_CLK_EN0_REG0, 24);
> +static A9_SYS_PCLK(sys_sd_emmc_b,	SYS_CLK_EN0_REG0, 25);
> +static A9_SYS_PCLK(sys_sd_emmc_c,	SYS_CLK_EN0_REG0, 26);
> +static A9_SYS_PCLK(sys_sc,		SYS_CLK_EN0_REG0, 27);
> +static A9_SYS_PCLK(sys_acodec,		SYS_CLK_EN0_REG0, 28);
> +static A9_SYS_PCLK(sys_mipi_isp,	SYS_CLK_EN0_REG0, 29);
> +static A9_SYS_PCLK(sys_msr,		SYS_CLK_EN0_REG0, 30);
> +static A9_SYS_PCLK(sys_audio,		SYS_CLK_EN0_REG1, 0);
> +static A9_SYS_PCLK(sys_mipi_dsi1,	SYS_CLK_EN0_REG1, 1);
> +static A9_SYS_PCLK(sys_mipi_dsi1_phy,	SYS_CLK_EN0_REG1, 2);
> +static A9_SYS_PCLK(sys_eth,		SYS_CLK_EN0_REG1, 3);
> +static A9_SYS_PCLK(sys_eth_1g_mac,	SYS_CLK_EN0_REG1, 4);
> +static A9_SYS_PCLK(sys_uart_a,		SYS_CLK_EN0_REG1, 5);
> +static A9_SYS_PCLK(sys_uart_f,		SYS_CLK_EN0_REG1, 10);
> +static A9_SYS_PCLK(sys_ts_a55,		SYS_CLK_EN0_REG1, 11);
> +static A9_SYS_PCLK(sys_eth_1g_axi,	SYS_CLK_EN0_REG1, 12);
> +static A9_SYS_PCLK(sys_ts_dos,		SYS_CLK_EN0_REG1, 13);
> +static A9_SYS_PCLK(sys_u3drd_b,		SYS_CLK_EN0_REG1, 14);
> +static A9_SYS_PCLK(sys_ts_core,		SYS_CLK_EN0_REG1, 15);
> +static A9_SYS_PCLK(sys_ts_pll,		SYS_CLK_EN0_REG1, 16);
> +static A9_SYS_PCLK(sys_csi_dig_clkin,	SYS_CLK_EN0_REG1, 18);
> +static A9_SYS_PCLK(sys_cve,		SYS_CLK_EN0_REG1, 19);
> +static A9_SYS_PCLK(sys_ge2d,		SYS_CLK_EN0_REG1, 20);
> +static A9_SYS_PCLK(sys_spisg,		SYS_CLK_EN0_REG1, 21);
> +static A9_SYS_PCLK(sys_u2h,		SYS_CLK_EN0_REG1, 23);
> +static A9_SYS_PCLK(sys_pcie_mac_a,	SYS_CLK_EN0_REG1, 24);
> +static A9_SYS_PCLK(sys_u3drd_a,		SYS_CLK_EN0_REG1, 25);
> +static A9_SYS_PCLK(sys_u2drd,		SYS_CLK_EN0_REG1, 26);
> +static A9_SYS_PCLK(sys_pcie_phy,	SYS_CLK_EN0_REG1, 27);
> +static A9_SYS_PCLK(sys_pcie_mac_b,	SYS_CLK_EN0_REG1, 28);
> +static A9_SYS_PCLK(sys_periph,		SYS_CLK_EN0_REG1, 29);
> +static A9_SYS_PCLK(sys_pio,		SYS_CLK_EN0_REG2, 0);
> +static A9_SYS_PCLK(sys_i3c,		SYS_CLK_EN0_REG2, 1);
> +static A9_SYS_PCLK(sys_i2c_m_e,		SYS_CLK_EN0_REG2, 2);
> +static A9_SYS_PCLK(sys_i2c_m_f,		SYS_CLK_EN0_REG2, 3);
> +static A9_SYS_PCLK(sys_hdmitx_apb,	SYS_CLK_EN0_REG2, 4);
> +static A9_SYS_PCLK(sys_i2c_m_i,		SYS_CLK_EN0_REG2, 5);
> +static A9_SYS_PCLK(sys_i2c_m_g,		SYS_CLK_EN0_REG2, 6);
> +static A9_SYS_PCLK(sys_i2c_m_h,		SYS_CLK_EN0_REG2, 7);
> +static A9_SYS_PCLK(sys_hdmi20_aes,	SYS_CLK_EN0_REG2, 9);
> +static A9_SYS_PCLK(sys_csi2_host,	SYS_CLK_EN0_REG2, 16);
> +static A9_SYS_PCLK(sys_csi2_adapt,	SYS_CLK_EN0_REG2, 17);
> +static A9_SYS_PCLK(sys_dspa,		SYS_CLK_EN0_REG2, 21);
> +static A9_SYS_PCLK(sys_pp_dma,		SYS_CLK_EN0_REG2, 22);
> +static A9_SYS_PCLK(sys_pp_wrapper,	SYS_CLK_EN0_REG2, 23);
> +static A9_SYS_PCLK(sys_vpu_intr,	SYS_CLK_EN0_REG2, 25);
> +static A9_SYS_PCLK(sys_csi2_phy,	SYS_CLK_EN0_REG2, 27);
> +static A9_SYS_PCLK(sys_saradc,		SYS_CLK_EN0_REG2, 28);
> +static A9_SYS_PCLK(sys_pwm_j,		SYS_CLK_EN0_REG2, 30);
> +static A9_SYS_PCLK(sys_pwm_i,		SYS_CLK_EN0_REG2, 31);
> +static A9_SYS_PCLK(sys_pwm_h,		SYS_CLK_EN0_REG3, 0);
> +static A9_SYS_PCLK(sys_pwm_n,		SYS_CLK_EN0_REG3, 8);
> +static A9_SYS_PCLK(sys_pwm_m,		SYS_CLK_EN0_REG3, 9);
> +static A9_SYS_PCLK(sys_pwm_l,		SYS_CLK_EN0_REG3, 10);
> +static A9_SYS_PCLK(sys_pwm_k,		SYS_CLK_EN0_REG3, 11);
> +
> +/* Channel 5 is unconnected. */
> +static u32 a9_sd_emmc_parents_val_table[] = { 0, 1, 2, 3, 4, 6, 7 };
> +static const struct clk_parent_data a9_sd_emmc_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "hifi0", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "gp1", },
> +	{ .fw_name = "gp0", }
> +};
> +
> +static A9_COMP_SEL(sd_emmc_a, SD_EMMC_CLK_CTRL0, 9, 0x7, a9_sd_emmc_parents,
> +		   a9_sd_emmc_parents_val_table);
> +static A9_COMP_DIV(sd_emmc_a, SD_EMMC_CLK_CTRL0, 0, 7);
> +static A9_COMP_GATE(sd_emmc_a, SD_EMMC_CLK_CTRL0, 8, 0);
> +
> +static A9_COMP_SEL(sd_emmc_b, SD_EMMC_CLK_CTRL0, 25, 0x7, a9_sd_emmc_parents,
> +		   a9_sd_emmc_parents_val_table);
> +static A9_COMP_DIV(sd_emmc_b, SD_EMMC_CLK_CTRL0, 16, 7);
> +static A9_COMP_GATE(sd_emmc_b, SD_EMMC_CLK_CTRL0, 24, 0);
> +
> +static A9_COMP_SEL(sd_emmc_c, SD_EMMC_CLK_CTRL1, 9, 0x7, a9_sd_emmc_parents,
> +		   a9_sd_emmc_parents_val_table);
> +static A9_COMP_DIV(sd_emmc_c, SD_EMMC_CLK_CTRL1, 0, 7);
> +static A9_COMP_GATE(sd_emmc_c, SD_EMMC_CLK_CTRL1, 8, 0);
> +
> +static const struct clk_parent_data a9_pwm_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", }
> +};
> +
> +static A9_COMP_SEL(pwm_h, PWM_CLK_H_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_h, PWM_CLK_H_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_h, PWM_CLK_H_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_i, PWM_CLK_I_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_i, PWM_CLK_I_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_i, PWM_CLK_I_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_j, PWM_CLK_J_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_j, PWM_CLK_J_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_j, PWM_CLK_J_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_k, PWM_CLK_K_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_k, PWM_CLK_K_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_k, PWM_CLK_K_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_l, PWM_CLK_L_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_l, PWM_CLK_L_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_l, PWM_CLK_L_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_m, PWM_CLK_M_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_m, PWM_CLK_M_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_m, PWM_CLK_M_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pwm_n, PWM_CLK_N_CTRL, 9, 0x7, a9_pwm_parents, NULL);
> +static A9_COMP_DIV(pwm_n, PWM_CLK_N_CTRL, 0, 8);
> +static A9_COMP_GATE(pwm_n, PWM_CLK_N_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_spisg_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "sys", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", },
> +	{ .fw_name = "gp0", }
> +};
> +
> +static A9_COMP_SEL(spisg0, SPISG_CLK_CTRL, 9, 0x7, a9_spisg_parents, NULL);
> +static A9_COMP_DIV(spisg0, SPISG_CLK_CTRL, 0, 6);
> +static A9_COMP_GATE(spisg0, SPISG_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(spisg1, SPISG_CLK_CTRL, 25, 0x7, a9_spisg_parents, NULL);
> +static A9_COMP_DIV(spisg1, SPISG_CLK_CTRL, 16, 6);
> +static A9_COMP_GATE(spisg1, SPISG_CLK_CTRL, 24, 0);
> +
> +static A9_COMP_SEL(spisg2, SPISG_CLK_CTRL1, 9, 0x7, a9_spisg_parents, NULL);
> +static A9_COMP_DIV(spisg2, SPISG_CLK_CTRL1, 0, 6);
> +static A9_COMP_GATE(spisg2, SPISG_CLK_CTRL1, 8, 0);
> +
> +static const struct clk_parent_data a9_saradc_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "sys", }
> +};
> +
> +static A9_COMP_SEL(saradc, SAR_CLK_CTRL, 9, 0x7, a9_saradc_parents, NULL);
> +static A9_COMP_DIV(saradc, SAR_CLK_CTRL, 0, 8);
> +static A9_COMP_GATE(saradc, SAR_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_amfc_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "sys", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", }
> +};
> +
> +static A9_COMP_SEL(amfc, AMFC_CLK_CTRL, 9, 0x7, a9_amfc_parents, NULL);
> +static A9_COMP_DIV(amfc, AMFC_CLK_CTRL, 0, 6);
> +static A9_COMP_GATE(amfc, AMFC_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_nna_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "gp2", },
> +	{ .fw_name = "hifi0", }
> +};
> +
> +static A9_COMP_SEL(nna, NNA_CLK_CTRL, 9, 0x7, a9_nna_parents, NULL);
> +static A9_COMP_DIV(nna, NNA_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(nna, NNA_CLK_CTRL, 8, 0);
> +
> +/* Channel 5 and 6 are unconnected. */
> +static u32 a9_usb_250m_parents_val_table[] = { 0, 1, 2, 3, 4, 7 };
> +static const struct clk_parent_data a9_usb_250m_parents[] = {
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "fdiv7", },
> +	{ .fw_name = "fdiv2p5", }
> +};
> +
> +static A9_COMP_SEL(usb_250m, USB_CLK_CTRL, 9, 0x7, a9_usb_250m_parents,
> +		   a9_usb_250m_parents_val_table);
> +static A9_COMP_DIV(usb_250m, USB_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(usb_250m, USB_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_usb_48m_pre_parents[] = {
> +	{ .fw_name = "gp0", },
> +	{ .fw_name = "gp1", },
> +	{ .fw_name = "gp2", },
> +	{ .fw_name = "fdiv2", }
> +};
> +
> +static A9_COMP_SEL(usb_48m_pre, USB_CLK_CTRL, 25, 0x3, a9_usb_48m_pre_parents, NULL);
> +static A9_COMP_DIV(usb_48m_pre, USB_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(usb_48m_pre, USB_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_pcie_tl_parents[] = {
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "gp0", },
> +	{ .fw_name = "sys", },
> +	{ .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(pcie0_tl, PCIE_TL_CLK_CTRL, 9, 0x7, a9_pcie_tl_parents, NULL);
> +static A9_COMP_DIV(pcie0_tl, PCIE_TL_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(pcie0_tl, PCIE_TL_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(pcie1_tl, PCIE_TL_CLK_CTRL, 25, 0x7, a9_pcie_tl_parents, NULL);
> +static A9_COMP_DIV(pcie1_tl, PCIE_TL_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(pcie1_tl, PCIE_TL_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_cmpr_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", },
> +	{ .fw_name = "hifi0", },
> +	{ .fw_name = "gp1", }
> +};
> +
> +static A9_COMP_SEL(cmpr, CMPR_CLK_CTRL, 25, 0x7, a9_cmpr_parents, NULL);
> +static A9_COMP_DIV(cmpr, CMPR_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(cmpr, CMPR_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_dewarpa_parents[] = {
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", },
> +	{ .fw_name = "gp0", },
> +	{ .fw_name = "hifi0", },
> +	{ .fw_name = "gp1", }
> +};
> +
> +static A9_COMP_SEL(dewarpa, DEWARP_CLK_CTRL, 9, 0x7, a9_dewarpa_parents, NULL);
> +static A9_COMP_DIV(dewarpa, DEWARP_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(dewarpa, DEWARP_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_sc_parents[] = {
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(sc_pre, SC_CLK_CTRL, 9, 0x7, a9_sc_parents, NULL);
> +static A9_COMP_DIV(sc_pre, SC_CLK_CTRL, 0, 8);
> +static A9_COMP_GATE(sc_pre, SC_CLK_CTRL, 8, 0);
> +
> +static struct clk_regmap a9_sc = {
> +	.data = &(struct clk_regmap_div_data) {
> +		.offset = SC_CLK_CTRL,
> +		.shift = 16,
> +		.width = 4,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "sc",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_sc_pre.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_dptx_apb2_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "sys", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(dptx_apb2, DPTX_CLK_CTRL, 9, 0x7, a9_dptx_apb2_parents, NULL);
> +static A9_COMP_DIV(dptx_apb2, DPTX_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(dptx_apb2, DPTX_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_dptx_aud_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "sys", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", }
> +};
> +
> +static A9_COMP_SEL(dptx_aud, DPTX_CLK_CTRL, 25, 0x7, a9_dptx_aud_parents, NULL);
> +static A9_COMP_DIV(dptx_aud, DPTX_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(dptx_aud, DPTX_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_isp_parents[] = {
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "gp0", },
> +	{ .fw_name = "hifi0", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(isp, ISP_CLK_CTRL, 9, 0x7, a9_isp_parents, NULL);
> +static A9_COMP_DIV(isp, ISP_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(isp, ISP_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_cve_vge_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "hifi0", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "gp0", },
> +	{ .fw_name = "rtc", }
> +};
> +
> +static A9_COMP_SEL(cve, CVE_CLK_CTRL, 9, 0x7, a9_cve_vge_parents, NULL);
> +static A9_COMP_DIV(cve, CVE_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(cve, CVE_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(vge, CVE_CLK_CTRL, 25, 0x7, a9_cve_vge_parents, NULL);
> +static A9_COMP_DIV(vge, CVE_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(vge, CVE_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_pp_parents[] = {
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "gp0", },
> +	{ .fw_name = "sys", },
> +	{ .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(pp, PP_CLK_CTRL, 9, 0x7, a9_pp_parents, NULL);
> +static A9_COMP_DIV(pp, PP_CLK_CTRL, 0, 6);
> +static A9_COMP_GATE(pp, PP_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_dspa_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "gp2", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "hifi0", },
> +	{ .fw_name = "rtc", }
> +};
> +
> +static A9_COMP_SEL(dspa_0, DSPA_CLK_CTRL, 9, 0x7, a9_dspa_parents, NULL);
> +static A9_COMP_DIV(dspa_0, DSPA_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(dspa_0, DSPA_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(dspa_1, DSPA_CLK_CTRL, 25, 0x7, a9_dspa_parents, NULL);
> +static A9_COMP_DIV(dspa_1, DSPA_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(dspa_1, DSPA_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_dspa = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = DSPA_CLK_CTRL,
> +		.mask = 0x1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "dspa",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_dspa_0.hw,
> +			&a9_dspa_1.hw
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +/* Channel 6 is unconnected. */
> +static u32 a9_glb_parents_val_table[] = { 0, 1, 2, 3, 4, 5, 7 };
> +static const struct clk_parent_data a9_glb_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .hw = &a9_dspa.hw },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .hw = &a9_isp.hw },
> +	{ .fw_name = "rtc", }
> +};
> +
> +static A9_COMP_SEL(glb, GLB_CLK_CTRL, 9, 0x7, a9_glb_parents, a9_glb_parents_val_table);
> +static A9_COMP_DIV(glb, GLB_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(glb, GLB_CLK_CTRL, 8, 0);
> +
> +static struct clk_regmap a9_usb_48m_dualdiv_in = {
> +	.data = &(struct clk_regmap_gate_data) {
> +		.offset = USB_CLK_CTRL,
> +		.bit_idx = 31,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "usb_48m_dualdiv_in",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_usb_48m_pre.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static const struct meson_clk_dualdiv_param a9_usb_48m_dualdiv_div_table[] = {
> +	{ 733, 732, 8, 11, 1 },
> +	{ /* sentinel */ }
> +};
> +
> +static struct clk_regmap a9_usb_48m_dualdiv_div = {
> +	.data = &(struct meson_clk_dualdiv_data) {
> +		.n1 = {
> +			.reg_off = USB_CLK_CTRL0,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.n2 = {
> +			.reg_off = USB_CLK_CTRL0,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.m1 = {
> +			.reg_off = USB_CLK_CTRL1,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.m2 = {
> +			.reg_off = USB_CLK_CTRL1,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.dual = {
> +			.reg_off = USB_CLK_CTRL0,
> +			.shift   = 28,
> +			.width   = 1,
> +		},
> +		.table = a9_usb_48m_dualdiv_div_table,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "usb_48m_dualdiv_div",
> +		.ops = &meson_clk_dualdiv_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_usb_48m_dualdiv_in.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap a9_usb_48m_dualdiv_sel = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = USB_CLK_CTRL1,
> +		.mask = 0x1,
> +		.shift = 24,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "usb_48m_dualdiv_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_usb_48m_dualdiv_in.hw,
> +			&a9_usb_48m_dualdiv_div.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_usb_48m_dualdiv = {
> +	.data = &(struct clk_regmap_gate_data) {
> +		.offset = USB_CLK_CTRL0,
> +		.bit_idx = 30,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "usb_48m_dualdiv",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_usb_48m_dualdiv_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_usb_48m = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = USB_CLK_CTRL1,
> +		.mask = 0x3,
> +		.shift = 30,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "usb_48m",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_usb_48m_pre.hw,
> +			&a9_usb_48m_dualdiv.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +/* Channel 2 is unconnected. */
> +static u32 a9_can_pe_parents_val_table[] = { 0, 1, 3 };
> +static const struct clk_parent_data a9_can_pe_parents[] = {
> +	{ .fw_name = "sys", },
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(can0_pe, CAN_CLK_CTRL, 9, 0x7, a9_can_pe_parents, a9_can_pe_parents_val_table);
> +static A9_COMP_DIV(can0_pe, CAN_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(can0_pe, CAN_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(can1_pe, CAN_CLK_CTRL, 25, 0x7, a9_can_pe_parents, a9_can_pe_parents_val_table);
> +static A9_COMP_DIV(can1_pe, CAN_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(can1_pe, CAN_CLK_CTRL, 24, 0);
> +
> +static const struct clk_parent_data a9_can_filter_parents[] = {
> +	{ .fw_name = "sys", },
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(can0_filter, CAN_CLK_CTRL1, 9, 0x7, a9_can_filter_parents, NULL);
> +static A9_COMP_DIV(can0_filter, CAN_CLK_CTRL1, 0, 7);
> +static A9_COMP_GATE(can0_filter, CAN_CLK_CTRL1, 8, 0);
> +
> +static A9_COMP_SEL(can1_filter, CAN_CLK_CTRL1, 25, 0x7, a9_can_filter_parents, NULL);
> +static A9_COMP_DIV(can1_filter, CAN_CLK_CTRL1, 16, 7);
> +static A9_COMP_GATE(can1_filter, CAN_CLK_CTRL1, 24, 0);
> +
> +static const struct clk_parent_data a9_i3c_parents[] = {
> +	{ .fw_name = "sys", },
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(i3c, I3C_CLK_CTRL, 9, 0x7, a9_i3c_parents, NULL);
> +static A9_COMP_DIV(i3c, I3C_CLK_CTRL, 0, 8);
> +static A9_COMP_GATE(i3c, I3C_CLK_CTRL, 8, 0);
> +
> +static struct clk_regmap a9_ts_div = {
> +	.data = &(struct clk_regmap_div_data) {
> +		.offset = TS_CLK_CTRL,
> +		.shift = 0,
> +		.width = 8,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "ts_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_data = &(const struct clk_parent_data) {
> +			.fw_name = "xtal",
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap a9_ts = {
> +	.data = &(struct clk_regmap_gate_data) {
> +		.offset = TS_CLK_CTRL,
> +		.bit_idx = 8,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "ts",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_ts_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_fixed_factor a9_eth_125m_div = {
> +	.mult = 1,
> +	.div = 8,
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "eth_125m_div",
> +		.ops = &clk_fixed_factor_ops,
> +		.parent_data = &(const struct clk_parent_data) {
> +			.fw_name = "fdiv2",
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap a9_eth_125m = {
> +	.data = &(struct clk_regmap_gate_data) {
> +		.offset = ETH_CLK_CTRL,
> +		.bit_idx = 7,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "eth_125m",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_eth_125m_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +/*
> + * Channel 1, 2, 3, 4, 5 and 6 are unconnected,
> + * Channel 7(ext_rmii) connects external PAD. Do not automatically reparent.
> + */
> +static u32 a9_eth_rmii_parents_val_table[] = { 0, 7 };
> +static const struct clk_parent_data a9_eth_rmii_parents[] = {
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "ext_rmii", }
> +};
> +
> +static struct clk_regmap a9_eth_rmii_sel = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = ETH_CLK_CTRL,
> +		.mask = 0x7,
> +		.shift = 9,
> +		.table = a9_eth_rmii_parents_val_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "eth_rmii_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = a9_eth_rmii_parents,
> +		.num_parents = ARRAY_SIZE(a9_eth_rmii_parents),
> +		.flags = CLK_SET_RATE_NO_REPARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_eth_rmii_div = {
> +	.data = &(struct clk_regmap_div_data) {
> +		.offset = ETH_CLK_CTRL,
> +		.shift = 0,
> +		.width = 7,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "eth_rmii_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_eth_rmii_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_eth_rmii = {
> +	.data = &(struct clk_regmap_gate_data) {
> +		.offset = ETH_CLK_CTRL,
> +		.bit_idx = 8,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "eth_rmii",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_eth_rmii_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_vid_pll_div = {
> +	.data = &(struct meson_vid_pll_div_data){
> +		.val = {
> +			.reg_off = VID_PLL_CLK_DIV,
> +			.shift   = 0,
> +			.width   = 15,
> +		},
> +		.sel = {
> +			.reg_off = VID_PLL_CLK_DIV,
> +			.shift   = 16,
> +			.width   = 2,
> +		},
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "vid_pll_div",
> +		.ops = &meson_vid_pll_div_ro_ops,
> +		.parent_data = (const struct clk_parent_data []) {
> +			{ .fw_name = "hdmiout2", }
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap a9_vid_pll_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = VID_PLL_CLK_DIV,
> +		.mask = 0x1,
> +		.shift = 18,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "vid_pll_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = (const struct clk_parent_data []) {
> +			{ .hw = &a9_vid_pll_div.hw },
> +			{ .fw_name = "hdmiout2", }
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_vid_pll = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VID_PLL_CLK_DIV,
> +		.bit_idx = 19,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "vid_pll",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_vid_pll_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +/*
> + * Channel 12 (msr_clk) is managed by the clock measurement module and is not part of the clock
> + * tree. It depends on the measurement source selected through the measurement control registers.
> + *
> + * Channel 10, 11, 13, 14 and 16 are unconnected.
> + */
> +static u32 a9_gen_parents_val_table[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 17, 18,
> +					  19, 20, 21, 22, 23, 24, 25, 26};
> +static const struct clk_parent_data a9_gen_parents[] = {
> +	{ .fw_name = "xtal" },
> +	{ .fw_name = "rtc" },
> +	{ .fw_name = "sysplldiv16" },
> +	{ .fw_name = "ddr_test" },
> +	{ .hw = &a9_vid_pll.hw },
> +	{ .fw_name = "gp0" },
> +	{ .fw_name = "hifi1" },
> +	{ .fw_name = "hifi0" },
> +	{ .fw_name = "gp1" },
> +	{ .fw_name = "gp2" },
> +	{ .fw_name = "dsudiv16" },
> +	{ .fw_name = "cpudiv16" },
> +	{ .fw_name = "a78div16" },
> +	{ .fw_name = "fdiv2" },
> +	{ .fw_name = "fdiv2p5" },
> +	{ .fw_name = "fdiv3" },
> +	{ .fw_name = "fdiv4" },
> +	{ .fw_name = "fdiv5" },
> +	{ .fw_name = "fdiv7" },
> +	{ .fw_name = "mclk0" },
> +	{ .fw_name = "mclk1" }
> +};
> +
> +static A9_COMP_SEL(gen, GEN_CLK_CTRL, 12, 0x1f, a9_gen_parents, a9_gen_parents_val_table);
> +static A9_COMP_DIV(gen, GEN_CLK_CTRL, 0, 11);
> +static A9_COMP_GATE(gen, GEN_CLK_CTRL, 11, 0);
> +
> +static struct clk_regmap a9_24m_in = {
> +	.data = &(struct clk_regmap_gate_data) {
> +		.offset = CLK12_24_CTRL,
> +		.bit_idx = 11,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "24m_in",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_data = &(const struct clk_parent_data) {
> +			.fw_name = "xtal",
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap a9_12_24m = {
> +	.data = &(struct clk_regmap_div_data) {
> +		.offset = CLK12_24_CTRL,
> +		.shift = 10,
> +		.width = 1,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "12_24m",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_24m_in.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_mali_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "gp1", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", }
> +};
> +
> +static A9_COMP_SEL(mali_0, MALI_CLK_CTRL, 9, 0x7, a9_mali_parents, NULL);
> +static A9_COMP_DIV(mali_0, MALI_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(mali_0, MALI_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(mali_1, MALI_CLK_CTRL, 25, 0x7, a9_mali_parents, NULL);
> +static A9_COMP_DIV(mali_1, MALI_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(mali_1, MALI_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_mali = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = MALI_CLK_CTRL,
> +		.mask = 0x1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mali",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_mali_0.hw,
> +			&a9_mali_1.hw
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static A9_COMP_SEL(mali_stack_0, MALI_STACK_CLK_CTRL, 9, 0x7, a9_mali_parents, NULL);
> +static A9_COMP_DIV(mali_stack_0, MALI_STACK_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(mali_stack_0, MALI_STACK_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(mali_stack_1, MALI_STACK_CLK_CTRL, 25, 0x7, a9_mali_parents, NULL);
> +static A9_COMP_DIV(mali_stack_1, MALI_STACK_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(mali_stack_1, MALI_STACK_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_mali_stack = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = MALI_STACK_CLK_CTRL,
> +		.mask = 0x1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mali_stack",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_mali_stack_0.hw,
> +			&a9_mali_stack_1.hw
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_hevcf_parents[] = {
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", },
> +	{ .fw_name = "hifi0", },
> +	{ .fw_name = "gp1", },
> +	{ .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(hevcf_0, HEVCF_CLK_CTRL, 9, 0x7, a9_hevcf_parents, NULL);
> +static A9_COMP_DIV(hevcf_0, HEVCF_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(hevcf_0, HEVCF_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(hevcf_1, HEVCF_CLK_CTRL, 25, 0x7, a9_hevcf_parents, NULL);
> +static A9_COMP_DIV(hevcf_1, HEVCF_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(hevcf_1, HEVCF_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_hevcf = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = HEVCF_CLK_CTRL,
> +		.mask = 0x1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hevcf",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_hevcf_0.hw,
> +			&a9_hevcf_1.hw
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_hcodec_parents[] = {
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", },
> +	{ .fw_name = "hifi0", },
> +	{ .fw_name = "gp0", },
> +	{ .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(hcodec_0, HCODEC_CLK_CTRL, 9, 0x7, a9_hcodec_parents, NULL);
> +static A9_COMP_DIV(hcodec_0, HCODEC_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(hcodec_0, HCODEC_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(hcodec_1, HCODEC_CLK_CTRL, 25, 0x7, a9_hcodec_parents, NULL);
> +static A9_COMP_DIV(hcodec_1, HCODEC_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(hcodec_1, HCODEC_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_hcodec = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = HCODEC_CLK_CTRL,
> +		.mask = 0x1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hcodec",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_hcodec_0.hw,
> +			&a9_hcodec_1.hw
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_vpu_parents[] = {
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "vid1", },
> +	{ .fw_name = "fdiv2", },
> +	{ .hw = &a9_vid_pll.hw },
> +	{ .fw_name = "vid2", },
> +	{ .fw_name = "gp1", }
> +};
> +
> +static A9_COMP_SEL(vpu_0, VPU_CLK_CTRL, 9, 0x7, a9_vpu_parents, NULL);
> +static A9_COMP_DIV(vpu_0, VPU_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(vpu_0, VPU_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(vpu_1, VPU_CLK_CTRL, 25, 0x7, a9_vpu_parents, NULL);
> +static A9_COMP_DIV(vpu_1, VPU_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(vpu_1, VPU_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_vpu = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = VPU_CLK_CTRL,
> +		.mask = 0x1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "vpu",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_vpu_0.hw,
> +			&a9_vpu_1.hw
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_vapb_parents[] = {
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", },
> +	{ .fw_name = "fdiv2", },
> +	{ .hw = &a9_vid_pll.hw },
> +	{ .fw_name = "hifi0", },
> +	{ .fw_name = "fdiv2p5", }
> +};
> +
> +static A9_COMP_SEL(vapb_0, VAPB_CLK_CTRL, 9, 0x7, a9_vapb_parents, NULL);
> +static A9_COMP_DIV(vapb_0, VAPB_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(vapb_0, VAPB_CLK_CTRL, 8, CLK_SET_RATE_GATE);
> +
> +static A9_COMP_SEL(vapb_1, VAPB_CLK_CTRL, 25, 0x7, a9_vapb_parents, NULL);
> +static A9_COMP_DIV(vapb_1, VAPB_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(vapb_1, VAPB_CLK_CTRL, 24, CLK_SET_RATE_GATE);
> +
> +static struct clk_regmap a9_vapb = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = VAPB_CLK_CTRL,
> +		.mask = 0x1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "vapb",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_vapb_0.hw,
> +			&a9_vapb_1.hw
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_ge2d = {
> +	.data = &(struct clk_regmap_gate_data) {
> +		.offset = VAPB_CLK_CTRL,
> +		.bit_idx = 30,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "ge2d",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_vapb.hw,
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_vpu_clkb_tmp_parents[] = {
> +	{ .hw = &a9_vpu.hw },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", }
> +};
> +
> +static A9_COMP_SEL(vpu_clkb_tmp, VPU_CLKB_CTRL, 25, 0x7, a9_vpu_clkb_tmp_parents, NULL);
> +static A9_COMP_DIV(vpu_clkb_tmp, VPU_CLKB_CTRL, 16, 4);
> +static A9_COMP_GATE(vpu_clkb_tmp, VPU_CLKB_CTRL, 24, 0);
> +
> +static struct clk_regmap a9_vpu_clkb_div = {
> +	.data = &(struct clk_regmap_div_data) {
> +		.offset = VPU_CLKB_CTRL,
> +		.shift = 0,
> +		.width = 8,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "vpu_clkb_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_vpu_clkb_tmp.hw,
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap a9_vpu_clkb = {
> +	.data = &(struct clk_regmap_gate_data) {
> +		.offset = VPU_CLKB_CTRL,
> +		.bit_idx = 8,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "vpu_clkb",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_vpu_clkb_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_hdmi_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(hdmitx_sys, HDMI_CLK_CTRL, 9, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmitx_sys, HDMI_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(hdmitx_sys, HDMI_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(hdmitx_prif, HTX_CLK_CTRL, 9, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmitx_prif, HTX_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(hdmitx_prif, HTX_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(hdmitx_200m, HTX_CLK_CTRL, 25, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmitx_200m, HTX_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(hdmitx_200m, HTX_CLK_CTRL, 24, 0);
> +
> +static A9_COMP_SEL(hdmitx_aud, HTX_CLK_CTRL1, 9, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmitx_aud, HTX_CLK_CTRL1, 0, 7);
> +static A9_COMP_GATE(hdmitx_aud, HTX_CLK_CTRL1, 8, 0);
> +
> +static A9_COMP_SEL(hdmirx_5m, HRX_CLK_CTRL, 9, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmirx_5m, HRX_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(hdmirx_5m, HRX_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(hdmirx_2m, HRX_CLK_CTRL, 25, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmirx_2m, HRX_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(hdmirx_2m, HRX_CLK_CTRL, 24, 0);
> +
> +static A9_COMP_SEL(hdmirx_cfg, HRX_CLK_CTRL1, 9, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmirx_cfg, HRX_CLK_CTRL1, 0, 7);
> +static A9_COMP_GATE(hdmirx_cfg, HRX_CLK_CTRL1, 8, 0);
> +
> +static A9_COMP_SEL(hdmirx_hdcp2x, HRX_CLK_CTRL1, 25, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmirx_hdcp2x, HRX_CLK_CTRL1, 16, 7);
> +static A9_COMP_GATE(hdmirx_hdcp2x, HRX_CLK_CTRL1, 24, 0);
> +
> +static A9_COMP_SEL(hdmirx_acr_ref, HRX_CLK_CTRL2, 25, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmirx_acr_ref, HRX_CLK_CTRL2, 16, 7);
> +static A9_COMP_GATE(hdmirx_acr_ref, HRX_CLK_CTRL2, 24, 0);
> +
> +static A9_COMP_SEL(hdmirx_meter, HRX_CLK_CTRL3, 9, 0x7, a9_hdmi_parents, NULL);
> +static A9_COMP_DIV(hdmirx_meter, HRX_CLK_CTRL3, 0, 7);
> +static A9_COMP_GATE(hdmirx_meter, HRX_CLK_CTRL3, 8, 0);
> +
> +static struct clk_regmap a9_vid_pll_vclk = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = HDMI_CLK_CTRL,
> +		.mask = 0x1,
> +		.shift = 15,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "vid_pll_vclk",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = (const struct clk_parent_data []) {
> +			{ .hw = &a9_vid_pll.hw },
> +			{ .fw_name = "hdmipix", }
> +		},
> +		.num_parents = 2,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_vclk_parents[] = {
> +	{ .hw = &a9_vid_pll_vclk.hw },
> +	{ .fw_name = "pix0", },
> +	{ .fw_name = "vid1", },
> +	{ .fw_name = "pix1", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "vid2", }
> +};
> +
> +static struct clk_regmap a9_vclk0_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = VID_CLK_CTRL,
> +		.mask = 0x7,
> +		.shift = 16,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "vclk0_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = a9_vclk_parents,
> +		.num_parents = ARRAY_SIZE(a9_vclk_parents),
> +	},
> +};
> +
> +static struct clk_regmap a9_vclk0_in = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VID_CLK_DIV,
> +		.bit_idx = 16,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "vclk0_in",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) { &a9_vclk0_sel.hw },
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_vclk0_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = VID_CLK_DIV,
> +		.shift = 0,
> +		.width = 8,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "vclk0_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_vclk0_in.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_vclk0 = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VID_CLK_CTRL,
> +		.bit_idx = 19,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "vclk0",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) { &a9_vclk0_div.hw },
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +#define A9_VCLK_GATE(_name, _reg, _bit,  _parent)			\
> +struct clk_regmap a9_##_name##_en = {					\
> +	.data = &(struct clk_regmap_gate_data) {			\
> +		.offset = (_reg),					\
> +		.bit_idx = (_bit),					\
> +	},								\
> +	.hw.init = &(struct clk_init_data) {				\
> +		.name = #_name "_en",					\
> +		.ops = &clk_regmap_gate_ops,				\
> +		.parent_hws = (const struct clk_hw *[]) {		\
> +			&(_parent).hw					\
> +		},							\
> +		.num_parents = 1,					\
> +		.flags = CLK_SET_RATE_PARENT,				\
> +	},								\
> +}
> +
> +#define A9_VCLK_DIV(_name, _div)					\
> +struct clk_fixed_factor a9_##_name = {					\
> +	.mult = 1,							\
> +	.div = (_div),							\
> +	.hw.init = &(struct clk_init_data) {				\
> +		.name = #_name,						\
> +		.ops = &clk_fixed_factor_ops,				\
> +		.parent_hws = (const struct clk_hw *[]) {		\
> +			&a9_##_name##_en.hw				\
> +		},							\
> +		.num_parents = 1,					\
> +		.flags = CLK_SET_RATE_PARENT,				\
> +	},								\
> +}
> +
> +static A9_VCLK_GATE(vclk0_div1, VID_CLK_CTRL, 0, a9_vclk0);
> +static A9_VCLK_GATE(vclk0_div2, VID_CLK_CTRL, 1, a9_vclk0);
> +static A9_VCLK_DIV(vclk0_div2, 2);
> +static A9_VCLK_GATE(vclk0_div4, VID_CLK_CTRL, 2, a9_vclk0);
> +static A9_VCLK_DIV(vclk0_div4, 4);
> +static A9_VCLK_GATE(vclk0_div6, VID_CLK_CTRL, 3, a9_vclk0);
> +static A9_VCLK_DIV(vclk0_div6, 6);
> +static A9_VCLK_GATE(vclk0_div12, VID_CLK_CTRL, 4, a9_vclk0);
> +static A9_VCLK_DIV(vclk0_div12, 12);
> +
> +static struct clk_regmap a9_vclk1_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = VIID_CLK_CTRL,
> +		.mask = 0x7,
> +		.shift = 16,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "vclk1_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = a9_vclk_parents,
> +		.num_parents = ARRAY_SIZE(a9_vclk_parents),
> +	},
> +};
> +
> +static struct clk_regmap a9_vclk1_in = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VIID_CLK_DIV,
> +		.bit_idx = 16,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "vclk1_in",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) { &a9_vclk1_sel.hw },
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_vclk1_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = VIID_CLK_DIV,
> +		.shift = 0,
> +		.width = 8,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "vclk1_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_vclk1_in.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_vclk1 = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VIID_CLK_CTRL,
> +		.bit_idx = 19,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "vclk1",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) { &a9_vclk1_div.hw },
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static A9_VCLK_GATE(vclk1_div1, VIID_CLK_CTRL, 0, a9_vclk1);
> +static A9_VCLK_GATE(vclk1_div2, VIID_CLK_CTRL, 1, a9_vclk1);
> +static A9_VCLK_DIV(vclk1_div2, 2);
> +static A9_VCLK_GATE(vclk1_div4, VIID_CLK_CTRL, 2, a9_vclk1);
> +static A9_VCLK_DIV(vclk1_div4, 4);
> +static A9_VCLK_GATE(vclk1_div6, VIID_CLK_CTRL, 3, a9_vclk1);
> +static A9_VCLK_DIV(vclk1_div6, 6);
> +static A9_VCLK_GATE(vclk1_div12, VIID_CLK_CTRL, 4, a9_vclk1);
> +static A9_VCLK_DIV(vclk1_div12, 12);
> +
> +/* Channel 5, 6 and 7 are unconnected */
> +static u32 a9_vid_parents_val_table[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
> +static const struct clk_hw *a9_vid_parents[] = {
> +	&a9_vclk0_div1_en.hw,
> +	&a9_vclk0_div2.hw,
> +	&a9_vclk0_div4.hw,
> +	&a9_vclk0_div6.hw,
> +	&a9_vclk0_div12.hw,
> +	&a9_vclk1_div1_en.hw,
> +	&a9_vclk1_div2.hw,
> +	&a9_vclk1_div4.hw,
> +	&a9_vclk1_div6.hw,
> +	&a9_vclk1_div12.hw
> +};
> +
> +static struct clk_regmap a9_encoder0_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = VIID_CLK_DIV,
> +		.mask = 0xf,
> +		.shift = 12,
> +		.table = a9_vid_parents_val_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "encoder0_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = a9_vid_parents,
> +		.num_parents = ARRAY_SIZE(a9_vid_parents),
> +	},
> +};
> +
> +static struct clk_regmap a9_encoder0 = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VID_CLK_CTRL2,
> +		.bit_idx = 10,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "encoder0",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_encoder0_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_encoder1_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = VIID_CLK_DIV,
> +		.mask = 0xf,
> +		.shift = 8,
> +		.table = a9_vid_parents_val_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "encoder1_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = a9_vid_parents,
> +		.num_parents = ARRAY_SIZE(a9_vid_parents),
> +	},
> +};
> +
> +static struct clk_regmap a9_encoder1 = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VID_CLK_CTRL2,
> +		.bit_idx = 11,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "encoder1",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_encoder1_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_vid_lock_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .hw = &a9_encoder0.hw },
> +	{ .hw = &a9_encoder1.hw }
> +};
> +
> +static A9_COMP_SEL(vid_lock, VID_LOCK_CLK_CTRL, 9, 0x7, a9_vid_lock_parents, NULL);
> +static A9_COMP_DIV(vid_lock, VID_LOCK_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(vid_lock, VID_LOCK_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_vdin_meas_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", }
> +};
> +
> +static A9_COMP_SEL(vdin_meas, VDIN_MEAS_CLK_CTRL, 9, 0x7, a9_vdin_meas_parents, NULL);
> +static A9_COMP_DIV(vdin_meas, VDIN_MEAS_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(vdin_meas, VDIN_MEAS_CLK_CTRL, 8, 0);
> +
> +static struct clk_regmap a9_vdac_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = VIID_CLK_DIV,
> +		.mask = 0xf,
> +		.shift = 28,
> +		.table = a9_vid_parents_val_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "vdac_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = a9_vid_parents,
> +		.num_parents = ARRAY_SIZE(a9_vid_parents),
> +	},
> +};
> +
> +static struct clk_regmap a9_vdac = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VID_CLK_CTRL2,
> +		.bit_idx = 4,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "vdac",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_vdac_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_hdmitx0_pixel_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = HDMI_CLK_CTRL,
> +		.mask = 0xf,
> +		.shift = 16,
> +		.table = a9_vid_parents_val_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hdmitx0_pixel_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = a9_vid_parents,
> +		.num_parents = ARRAY_SIZE(a9_vid_parents),
> +	},
> +};
> +
> +static struct clk_regmap a9_hdmitx0_pixel = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VID_CLK_CTRL2,
> +		.bit_idx = 5,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "hdmitx0_pixel",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_hdmitx0_pixel_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_hdmitx0_fe_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = HDMI_CLK_CTRL,
> +		.mask = 0xf,
> +		.shift = 20,
> +		.table = a9_vid_parents_val_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hdmitx0_fe_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = a9_vid_parents,
> +		.num_parents = ARRAY_SIZE(a9_vid_parents),
> +	},
> +};
> +
> +static struct clk_regmap a9_hdmitx0_fe = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VID_CLK_CTRL2,
> +		.bit_idx = 9,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "hdmitx0_fe",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_hdmitx0_fe_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_hdmitx1_pixel_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = HDMI_CLK_CTRL,
> +		.mask = 0xf,
> +		.shift = 24,
> +		.table = a9_vid_parents_val_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hdmitx1_pixel_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = a9_vid_parents,
> +		.num_parents = ARRAY_SIZE(a9_vid_parents),
> +	},
> +};
> +
> +static struct clk_regmap a9_hdmitx1_pixel = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VID_CLK_CTRL2,
> +		.bit_idx = 12,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "hdmitx1_pixel",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_hdmitx1_pixel_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap a9_hdmitx1_fe_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = HDMI_CLK_CTRL,
> +		.mask = 0xf,
> +		.shift = 28,
> +		.table = a9_vid_parents_val_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hdmitx1_fe_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = a9_vid_parents,
> +		.num_parents = ARRAY_SIZE(a9_vid_parents),
> +	},
> +};
> +
> +static struct clk_regmap a9_hdmitx1_fe = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = VID_CLK_CTRL2,
> +		.bit_idx = 13,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "hdmitx1_fe",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&a9_hdmitx1_fe_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static const struct clk_parent_data a9_csi_phy_parents[] = {
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "gp0", },
> +	{ .fw_name = "hifi0", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "xtal", }
> +};
> +
> +static A9_COMP_SEL(csi_phy, MIPI_CSI_PHY_CLK_CTRL, 9, 0x7, a9_csi_phy_parents, NULL);
> +static A9_COMP_DIV(csi_phy, MIPI_CSI_PHY_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(csi_phy, MIPI_CSI_PHY_CLK_CTRL, 8, 0);
> +
> +static const struct clk_parent_data a9_dsi_meas_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .hw = &a9_vid_pll.hw },
> +	{ .fw_name = "gp0", },
> +	{ .fw_name = "vid1", },
> +	{ .fw_name = "vid2", }
> +};
> +
> +static A9_COMP_SEL(dsi0_meas, DSI_MEAS_CLK_CTRL, 9, 0x7, a9_dsi_meas_parents, NULL);
> +static A9_COMP_DIV(dsi0_meas, DSI_MEAS_CLK_CTRL, 0, 7);
> +static A9_COMP_GATE(dsi0_meas, DSI_MEAS_CLK_CTRL, 8, 0);
> +
> +static A9_COMP_SEL(dsi1_meas, DSI_MEAS_CLK_CTRL, 25, 0x7, a9_dsi_meas_parents, NULL);
> +static A9_COMP_DIV(dsi1_meas, DSI_MEAS_CLK_CTRL, 16, 7);
> +static A9_COMP_GATE(dsi1_meas, DSI_MEAS_CLK_CTRL, 24, 0);
> +
> +static struct clk_hw *a9_peripherals_hw_clks[] = {
> +	[CLKID_SYS_AM_AXI]		= &a9_sys_am_axi.hw,
> +	[CLKID_SYS_DOS]			= &a9_sys_dos.hw,
> +	[CLKID_SYS_MIPI_DSI0]		= &a9_sys_mipi_dsi0.hw,
> +	[CLKID_SYS_ETH_PHY]		= &a9_sys_eth_phy.hw,
> +	[CLKID_SYS_AMFC]		= &a9_sys_amfc.hw,
> +	[CLKID_SYS_MALI]		= &a9_sys_mali.hw,
> +	[CLKID_SYS_NNA]			= &a9_sys_nna.hw,
> +	[CLKID_SYS_ETH_AXI]		= &a9_sys_eth_axi.hw,
> +	[CLKID_SYS_DP_APB]		= &a9_sys_dp_apb.hw,
> +	[CLKID_SYS_EDPTX_APB]		= &a9_sys_edptx_apb.hw,
> +	[CLKID_SYS_U3HSG]		= &a9_sys_u3hsg.hw,
> +	[CLKID_SYS_AUCPU]		= &a9_sys_aucpu.hw,
> +	[CLKID_SYS_GLB]			= &a9_sys_glb.hw,
> +	[CLKID_SYS_COMBO_DPHY_APB]	= &a9_sys_combo_dphy_apb.hw,
> +	[CLKID_SYS_HDMIRX_APB]		= &a9_sys_hdmirx_apb.hw,
> +	[CLKID_SYS_HDMIRX_PCLK]		= &a9_sys_hdmirx_pclk.hw,
> +	[CLKID_SYS_MIPI_DSI0_PHY]	= &a9_sys_mipi_dsi0_phy.hw,
> +	[CLKID_SYS_CAN0]		= &a9_sys_can0.hw,
> +	[CLKID_SYS_CAN1]		= &a9_sys_can1.hw,
> +	[CLKID_SYS_SD_EMMC_A]		= &a9_sys_sd_emmc_a.hw,
> +	[CLKID_SYS_SD_EMMC_B]		= &a9_sys_sd_emmc_b.hw,
> +	[CLKID_SYS_SD_EMMC_C]		= &a9_sys_sd_emmc_c.hw,
> +	[CLKID_SYS_SC]			= &a9_sys_sc.hw,
> +	[CLKID_SYS_ACODEC]		= &a9_sys_acodec.hw,
> +	[CLKID_SYS_MIPI_ISP]		= &a9_sys_mipi_isp.hw,
> +	[CLKID_SYS_MSR]			= &a9_sys_msr.hw,
> +	[CLKID_SYS_AUDIO]		= &a9_sys_audio.hw,
> +	[CLKID_SYS_MIPI_DSI1]		= &a9_sys_mipi_dsi1.hw,
> +	[CLKID_SYS_MIPI_DSI1_PHY]	= &a9_sys_mipi_dsi1_phy.hw,
> +	[CLKID_SYS_ETH]			= &a9_sys_eth.hw,
> +	[CLKID_SYS_ETH_1G_MAC]		= &a9_sys_eth_1g_mac.hw,
> +	[CLKID_SYS_UART_A]		= &a9_sys_uart_a.hw,
> +	[CLKID_SYS_UART_F]		= &a9_sys_uart_f.hw,
> +	[CLKID_SYS_TS_A55]		= &a9_sys_ts_a55.hw,
> +	[CLKID_SYS_ETH_1G_AXI]		= &a9_sys_eth_1g_axi.hw,
> +	[CLKID_SYS_TS_DOS]		= &a9_sys_ts_dos.hw,
> +	[CLKID_SYS_U3DRD_B]		= &a9_sys_u3drd_b.hw,
> +	[CLKID_SYS_TS_CORE]		= &a9_sys_ts_core.hw,
> +	[CLKID_SYS_TS_PLL]		= &a9_sys_ts_pll.hw,
> +	[CLKID_SYS_CSI_DIG_CLKIN]	= &a9_sys_csi_dig_clkin.hw,
> +	[CLKID_SYS_CVE]			= &a9_sys_cve.hw,
> +	[CLKID_SYS_GE2D]		= &a9_sys_ge2d.hw,
> +	[CLKID_SYS_SPISG]		= &a9_sys_spisg.hw,
> +	[CLKID_SYS_U2H]			= &a9_sys_u2h.hw,
> +	[CLKID_SYS_PCIE_MAC_A]		= &a9_sys_pcie_mac_a.hw,
> +	[CLKID_SYS_U3DRD_A]		= &a9_sys_u3drd_a.hw,
> +	[CLKID_SYS_U2DRD]		= &a9_sys_u2drd.hw,
> +	[CLKID_SYS_PCIE_PHY]		= &a9_sys_pcie_phy.hw,
> +	[CLKID_SYS_PCIE_MAC_B]		= &a9_sys_pcie_mac_b.hw,
> +	[CLKID_SYS_PERIPH]		= &a9_sys_periph.hw,
> +	[CLKID_SYS_PIO]			= &a9_sys_pio.hw,
> +	[CLKID_SYS_I3C]			= &a9_sys_i3c.hw,
> +	[CLKID_SYS_I2C_M_E]		= &a9_sys_i2c_m_e.hw,
> +	[CLKID_SYS_I2C_M_F]		= &a9_sys_i2c_m_f.hw,
> +	[CLKID_SYS_HDMITX_APB]		= &a9_sys_hdmitx_apb.hw,
> +	[CLKID_SYS_I2C_M_I]		= &a9_sys_i2c_m_i.hw,
> +	[CLKID_SYS_I2C_M_G]		= &a9_sys_i2c_m_g.hw,
> +	[CLKID_SYS_I2C_M_H]		= &a9_sys_i2c_m_h.hw,
> +	[CLKID_SYS_HDMI20_AES]		= &a9_sys_hdmi20_aes.hw,
> +	[CLKID_SYS_CSI2_HOST]		= &a9_sys_csi2_host.hw,
> +	[CLKID_SYS_CSI2_ADAPT]		= &a9_sys_csi2_adapt.hw,
> +	[CLKID_SYS_DSPA]		= &a9_sys_dspa.hw,
> +	[CLKID_SYS_PP_DMA]		= &a9_sys_pp_dma.hw,
> +	[CLKID_SYS_PP_WRAPPER]		= &a9_sys_pp_wrapper.hw,
> +	[CLKID_SYS_VPU_INTR]		= &a9_sys_vpu_intr.hw,
> +	[CLKID_SYS_CSI2_PHY]		= &a9_sys_csi2_phy.hw,
> +	[CLKID_SYS_SARADC]		= &a9_sys_saradc.hw,
> +	[CLKID_SYS_PWM_J]		= &a9_sys_pwm_j.hw,
> +	[CLKID_SYS_PWM_I]		= &a9_sys_pwm_i.hw,
> +	[CLKID_SYS_PWM_H]		= &a9_sys_pwm_h.hw,
> +	[CLKID_SYS_PWM_N]		= &a9_sys_pwm_n.hw,
> +	[CLKID_SYS_PWM_M]		= &a9_sys_pwm_m.hw,
> +	[CLKID_SYS_PWM_L]		= &a9_sys_pwm_l.hw,
> +	[CLKID_SYS_PWM_K]		= &a9_sys_pwm_k.hw,
> +	[CLKID_SD_EMMC_A_SEL]		= &a9_sd_emmc_a_sel.hw,
> +	[CLKID_SD_EMMC_A_DIV]		= &a9_sd_emmc_a_div.hw,
> +	[CLKID_SD_EMMC_A]		= &a9_sd_emmc_a.hw,
> +	[CLKID_SD_EMMC_B_SEL]		= &a9_sd_emmc_b_sel.hw,
> +	[CLKID_SD_EMMC_B_DIV]		= &a9_sd_emmc_b_div.hw,
> +	[CLKID_SD_EMMC_B]		= &a9_sd_emmc_b.hw,
> +	[CLKID_SD_EMMC_C_SEL]		= &a9_sd_emmc_c_sel.hw,
> +	[CLKID_SD_EMMC_C_DIV]		= &a9_sd_emmc_c_div.hw,
> +	[CLKID_SD_EMMC_C]		= &a9_sd_emmc_c.hw,
> +	[CLKID_PWM_H_SEL]		= &a9_pwm_h_sel.hw,
> +	[CLKID_PWM_H_DIV]		= &a9_pwm_h_div.hw,
> +	[CLKID_PWM_H]			= &a9_pwm_h.hw,
> +	[CLKID_PWM_I_SEL]		= &a9_pwm_i_sel.hw,
> +	[CLKID_PWM_I_DIV]		= &a9_pwm_i_div.hw,
> +	[CLKID_PWM_I]			= &a9_pwm_i.hw,
> +	[CLKID_PWM_J_SEL]		= &a9_pwm_j_sel.hw,
> +	[CLKID_PWM_J_DIV]		= &a9_pwm_j_div.hw,
> +	[CLKID_PWM_J]			= &a9_pwm_j.hw,
> +	[CLKID_PWM_K_SEL]		= &a9_pwm_k_sel.hw,
> +	[CLKID_PWM_K_DIV]		= &a9_pwm_k_div.hw,
> +	[CLKID_PWM_K]			= &a9_pwm_k.hw,
> +	[CLKID_PWM_L_SEL]		= &a9_pwm_l_sel.hw,
> +	[CLKID_PWM_L_DIV]		= &a9_pwm_l_div.hw,
> +	[CLKID_PWM_L]			= &a9_pwm_l.hw,
> +	[CLKID_PWM_M_SEL]		= &a9_pwm_m_sel.hw,
> +	[CLKID_PWM_M_DIV]		= &a9_pwm_m_div.hw,
> +	[CLKID_PWM_M]			= &a9_pwm_m.hw,
> +	[CLKID_PWM_N_SEL]		= &a9_pwm_n_sel.hw,
> +	[CLKID_PWM_N_DIV]		= &a9_pwm_n_div.hw,
> +	[CLKID_PWM_N]			= &a9_pwm_n.hw,
> +	[CLKID_SPISG0_SEL]		= &a9_spisg0_sel.hw,
> +	[CLKID_SPISG0_DIV]		= &a9_spisg0_div.hw,
> +	[CLKID_SPISG0]			= &a9_spisg0.hw,
> +	[CLKID_SPISG1_SEL]		= &a9_spisg1_sel.hw,
> +	[CLKID_SPISG1_DIV]		= &a9_spisg1_div.hw,
> +	[CLKID_SPISG1]			= &a9_spisg1.hw,
> +	[CLKID_SPISG2_SEL]		= &a9_spisg2_sel.hw,
> +	[CLKID_SPISG2_DIV]		= &a9_spisg2_div.hw,
> +	[CLKID_SPISG2]			= &a9_spisg2.hw,
> +	[CLKID_SARADC_SEL]		= &a9_saradc_sel.hw,
> +	[CLKID_SARADC_DIV]		= &a9_saradc_div.hw,
> +	[CLKID_SARADC]			= &a9_saradc.hw,
> +	[CLKID_AMFC_SEL]		= &a9_amfc_sel.hw,
> +	[CLKID_AMFC_DIV]		= &a9_amfc_div.hw,
> +	[CLKID_AMFC]			= &a9_amfc.hw,
> +	[CLKID_NNA_SEL]			= &a9_nna_sel.hw,
> +	[CLKID_NNA_DIV]			= &a9_nna_div.hw,
> +	[CLKID_NNA]			= &a9_nna.hw,
> +	[CLKID_USB_250M_SEL]		= &a9_usb_250m_sel.hw,
> +	[CLKID_USB_250M_DIV]		= &a9_usb_250m_div.hw,
> +	[CLKID_USB_250M]		= &a9_usb_250m.hw,
> +	[CLKID_USB_48M_PRE_SEL]		= &a9_usb_48m_pre_sel.hw,
> +	[CLKID_USB_48M_PRE_DIV]		= &a9_usb_48m_pre_div.hw,
> +	[CLKID_USB_48M_PRE]		= &a9_usb_48m_pre.hw,
> +	[CLKID_PCIE0_TL_SEL]		= &a9_pcie0_tl_sel.hw,
> +	[CLKID_PCIE0_TL_DIV]		= &a9_pcie0_tl_div.hw,
> +	[CLKID_PCIE0_TL]		= &a9_pcie0_tl.hw,
> +	[CLKID_PCIE1_TL_SEL]		= &a9_pcie1_tl_sel.hw,
> +	[CLKID_PCIE1_TL_DIV]		= &a9_pcie1_tl_div.hw,
> +	[CLKID_PCIE1_TL]		= &a9_pcie1_tl.hw,
> +	[CLKID_CMPR_SEL]		= &a9_cmpr_sel.hw,
> +	[CLKID_CMPR_DIV]		= &a9_cmpr_div.hw,
> +	[CLKID_CMPR]			= &a9_cmpr.hw,
> +	[CLKID_DEWARPA_SEL]		= &a9_dewarpa_sel.hw,
> +	[CLKID_DEWARPA_DIV]		= &a9_dewarpa_div.hw,
> +	[CLKID_DEWARPA]			= &a9_dewarpa.hw,
> +	[CLKID_SC_PRE_SEL]		= &a9_sc_pre_sel.hw,
> +	[CLKID_SC_PRE_DIV]		= &a9_sc_pre_div.hw,
> +	[CLKID_SC_PRE]			= &a9_sc_pre.hw,
> +	[CLKID_SC]			= &a9_sc.hw,
> +	[CLKID_DPTX_APB2_SEL]		= &a9_dptx_apb2_sel.hw,
> +	[CLKID_DPTX_APB2_DIV]		= &a9_dptx_apb2_div.hw,
> +	[CLKID_DPTX_APB2]		= &a9_dptx_apb2.hw,
> +	[CLKID_DPTX_AUD_SEL]		= &a9_dptx_aud_sel.hw,
> +	[CLKID_DPTX_AUD_DIV]		= &a9_dptx_aud_div.hw,
> +	[CLKID_DPTX_AUD]		= &a9_dptx_aud.hw,
> +	[CLKID_ISP_SEL]			= &a9_isp_sel.hw,
> +	[CLKID_ISP_DIV]			= &a9_isp_div.hw,
> +	[CLKID_ISP]			= &a9_isp.hw,
> +	[CLKID_CVE_SEL]			= &a9_cve_sel.hw,
> +	[CLKID_CVE_DIV]			= &a9_cve_div.hw,
> +	[CLKID_CVE]			= &a9_cve.hw,
> +	[CLKID_VGE_SEL]			= &a9_vge_sel.hw,
> +	[CLKID_VGE_DIV]			= &a9_vge_div.hw,
> +	[CLKID_VGE]			= &a9_vge.hw,
> +	[CLKID_PP_SEL]			= &a9_pp_sel.hw,
> +	[CLKID_PP_DIV]			= &a9_pp_div.hw,
> +	[CLKID_PP]			= &a9_pp.hw,
> +	[CLKID_GLB_SEL]			= &a9_glb_sel.hw,
> +	[CLKID_GLB_DIV]			= &a9_glb_div.hw,
> +	[CLKID_GLB]			= &a9_glb.hw,
> +	[CLKID_USB_48M_DUALDIV_IN]	= &a9_usb_48m_dualdiv_in.hw,
> +	[CLKID_USB_48M_DUALDIV_DIV]	= &a9_usb_48m_dualdiv_div.hw,
> +	[CLKID_USB_48M_DUALDIV_SEL]	= &a9_usb_48m_dualdiv_sel.hw,
> +	[CLKID_USB_48M_DUALDIV]		= &a9_usb_48m_dualdiv.hw,
> +	[CLKID_USB_48M]			= &a9_usb_48m.hw,
> +	[CLKID_CAN0_PE_SEL]		= &a9_can0_pe_sel.hw,
> +	[CLKID_CAN0_PE_DIV]		= &a9_can0_pe_div.hw,
> +	[CLKID_CAN0_PE]			= &a9_can0_pe.hw,
> +	[CLKID_CAN1_PE_SEL]		= &a9_can1_pe_sel.hw,
> +	[CLKID_CAN1_PE_DIV]		= &a9_can1_pe_div.hw,
> +	[CLKID_CAN1_PE]			= &a9_can1_pe.hw,
> +	[CLKID_CAN0_FILTER_SEL]		= &a9_can0_filter_sel.hw,
> +	[CLKID_CAN0_FILTER_DIV]		= &a9_can0_filter_div.hw,
> +	[CLKID_CAN0_FILTER]		= &a9_can0_filter.hw,
> +	[CLKID_CAN1_FILTER_SEL]		= &a9_can1_filter_sel.hw,
> +	[CLKID_CAN1_FILTER_DIV]		= &a9_can1_filter_div.hw,
> +	[CLKID_CAN1_FILTER]		= &a9_can1_filter.hw,
> +	[CLKID_I3C_SEL]			= &a9_i3c_sel.hw,
> +	[CLKID_I3C_DIV]			= &a9_i3c_div.hw,
> +	[CLKID_I3C]			= &a9_i3c.hw,
> +	[CLKID_TS_DIV]			= &a9_ts_div.hw,
> +	[CLKID_TS]			= &a9_ts.hw,
> +	[CLKID_ETH_125M_DIV]		= &a9_eth_125m_div.hw,
> +	[CLKID_ETH_125M]		= &a9_eth_125m.hw,
> +	[CLKID_ETH_RMII_SEL]		= &a9_eth_rmii_sel.hw,
> +	[CLKID_ETH_RMII_DIV]		= &a9_eth_rmii_div.hw,
> +	[CLKID_ETH_RMII]		= &a9_eth_rmii.hw,
> +	[CLKID_GEN_SEL]			= &a9_gen_sel.hw,
> +	[CLKID_GEN_DIV]			= &a9_gen_div.hw,
> +	[CLKID_GEN]			= &a9_gen.hw,
> +	[CLKID_CLK24M_IN]		= &a9_24m_in.hw,
> +	[CLKID_CLK12_24M]		= &a9_12_24m.hw,
> +	[CLKID_MALI_0_SEL]		= &a9_mali_0_sel.hw,
> +	[CLKID_MALI_0_DIV]		= &a9_mali_0_div.hw,
> +	[CLKID_MALI_0]			= &a9_mali_0.hw,
> +	[CLKID_MALI_1_SEL]		= &a9_mali_1_sel.hw,
> +	[CLKID_MALI_1_DIV]		= &a9_mali_1_div.hw,
> +	[CLKID_MALI_1]			= &a9_mali_1.hw,
> +	[CLKID_MALI]			= &a9_mali.hw,
> +	[CLKID_MALI_STACK_0_SEL]	= &a9_mali_stack_0_sel.hw,
> +	[CLKID_MALI_STACK_0_DIV]	= &a9_mali_stack_0_div.hw,
> +	[CLKID_MALI_STACK_0]		= &a9_mali_stack_0.hw,
> +	[CLKID_MALI_STACK_1_SEL]	= &a9_mali_stack_1_sel.hw,
> +	[CLKID_MALI_STACK_1_DIV]	= &a9_mali_stack_1_div.hw,
> +	[CLKID_MALI_STACK_1]		= &a9_mali_stack_1.hw,
> +	[CLKID_MALI_STACK]		= &a9_mali_stack.hw,
> +	[CLKID_DSPA_0_SEL]		= &a9_dspa_0_sel.hw,
> +	[CLKID_DSPA_0_DIV]		= &a9_dspa_0_div.hw,
> +	[CLKID_DSPA_0]			= &a9_dspa_0.hw,
> +	[CLKID_DSPA_1_SEL]		= &a9_dspa_1_sel.hw,
> +	[CLKID_DSPA_1_DIV]		= &a9_dspa_1_div.hw,
> +	[CLKID_DSPA_1]			= &a9_dspa_1.hw,
> +	[CLKID_DSPA]			= &a9_dspa.hw,
> +	[CLKID_HEVCF_0_SEL]		= &a9_hevcf_0_sel.hw,
> +	[CLKID_HEVCF_0_DIV]		= &a9_hevcf_0_div.hw,
> +	[CLKID_HEVCF_0]			= &a9_hevcf_0.hw,
> +	[CLKID_HEVCF_1_SEL]		= &a9_hevcf_1_sel.hw,
> +	[CLKID_HEVCF_1_DIV]		= &a9_hevcf_1_div.hw,
> +	[CLKID_HEVCF_1]			= &a9_hevcf_1.hw,
> +	[CLKID_HEVCF]			= &a9_hevcf.hw,
> +	[CLKID_HCODEC_0_SEL]		= &a9_hcodec_0_sel.hw,
> +	[CLKID_HCODEC_0_DIV]		= &a9_hcodec_0_div.hw,
> +	[CLKID_HCODEC_0]		= &a9_hcodec_0.hw,
> +	[CLKID_HCODEC_1_SEL]		= &a9_hcodec_1_sel.hw,
> +	[CLKID_HCODEC_1_DIV]		= &a9_hcodec_1_div.hw,
> +	[CLKID_HCODEC_1]		= &a9_hcodec_1.hw,
> +	[CLKID_HCODEC]			= &a9_hcodec.hw,
> +	[CLKID_VPU_0_SEL]		= &a9_vpu_0_sel.hw,
> +	[CLKID_VPU_0_DIV]		= &a9_vpu_0_div.hw,
> +	[CLKID_VPU_0]			= &a9_vpu_0.hw,
> +	[CLKID_VPU_1_SEL]		= &a9_vpu_1_sel.hw,
> +	[CLKID_VPU_1_DIV]		= &a9_vpu_1_div.hw,
> +	[CLKID_VPU_1]			= &a9_vpu_1.hw,
> +	[CLKID_VPU]			= &a9_vpu.hw,
> +	[CLKID_VAPB_0_SEL]		= &a9_vapb_0_sel.hw,
> +	[CLKID_VAPB_0_DIV]		= &a9_vapb_0_div.hw,
> +	[CLKID_VAPB_0]			= &a9_vapb_0.hw,
> +	[CLKID_VAPB_1_SEL]		= &a9_vapb_1_sel.hw,
> +	[CLKID_VAPB_1_DIV]		= &a9_vapb_1_div.hw,
> +	[CLKID_VAPB_1]			= &a9_vapb_1.hw,
> +	[CLKID_VAPB]			= &a9_vapb.hw,
> +	[CLKID_GE2D]			= &a9_ge2d.hw,
> +	[CLKID_VPU_CLKB_TMP_SEL]	= &a9_vpu_clkb_tmp_sel.hw,
> +	[CLKID_VPU_CLKB_TMP_DIV]	= &a9_vpu_clkb_tmp_div.hw,
> +	[CLKID_VPU_CLKB_TMP]		= &a9_vpu_clkb_tmp.hw,
> +	[CLKID_VPU_CLKB_DIV]		= &a9_vpu_clkb_div.hw,
> +	[CLKID_VPU_CLKB]		= &a9_vpu_clkb.hw,
> +	[CLKID_HDMITX_SYS_SEL]		= &a9_hdmitx_sys_sel.hw,
> +	[CLKID_HDMITX_SYS_DIV]		= &a9_hdmitx_sys_div.hw,
> +	[CLKID_HDMITX_SYS]		= &a9_hdmitx_sys.hw,
> +	[CLKID_HDMITX_PRIF_SEL]		= &a9_hdmitx_prif_sel.hw,
> +	[CLKID_HDMITX_PRIF_DIV]		= &a9_hdmitx_prif_div.hw,
> +	[CLKID_HDMITX_PRIF]		= &a9_hdmitx_prif.hw,
> +	[CLKID_HDMITX_200M_SEL]		= &a9_hdmitx_200m_sel.hw,
> +	[CLKID_HDMITX_200M_DIV]		= &a9_hdmitx_200m_div.hw,
> +	[CLKID_HDMITX_200M]		= &a9_hdmitx_200m.hw,
> +	[CLKID_HDMITX_AUD_SEL]		= &a9_hdmitx_aud_sel.hw,
> +	[CLKID_HDMITX_AUD_DIV]		= &a9_hdmitx_aud_div.hw,
> +	[CLKID_HDMITX_AUD]		= &a9_hdmitx_aud.hw,
> +	[CLKID_HDMIRX_5M_SEL]		= &a9_hdmirx_5m_sel.hw,
> +	[CLKID_HDMIRX_5M_DIV]		= &a9_hdmirx_5m_div.hw,
> +	[CLKID_HDMIRX_5M]		= &a9_hdmirx_5m.hw,
> +	[CLKID_HDMIRX_2M_SEL]		= &a9_hdmirx_2m_sel.hw,
> +	[CLKID_HDMIRX_2M_DIV]		= &a9_hdmirx_2m_div.hw,
> +	[CLKID_HDMIRX_2M]		= &a9_hdmirx_2m.hw,
> +	[CLKID_HDMIRX_CFG_SEL]		= &a9_hdmirx_cfg_sel.hw,
> +	[CLKID_HDMIRX_CFG_DIV]		= &a9_hdmirx_cfg_div.hw,
> +	[CLKID_HDMIRX_CFG]		= &a9_hdmirx_cfg.hw,
> +	[CLKID_HDMIRX_HDCP2X_SEL]	= &a9_hdmirx_hdcp2x_sel.hw,
> +	[CLKID_HDMIRX_HDCP2X_DIV]	= &a9_hdmirx_hdcp2x_div.hw,
> +	[CLKID_HDMIRX_HDCP2X]		= &a9_hdmirx_hdcp2x.hw,
> +	[CLKID_HDMIRX_ACR_REF_SEL]	= &a9_hdmirx_acr_ref_sel.hw,
> +	[CLKID_HDMIRX_ACR_REF_DIV]	= &a9_hdmirx_acr_ref_div.hw,
> +	[CLKID_HDMIRX_ACR_REF]		= &a9_hdmirx_acr_ref.hw,
> +	[CLKID_HDMIRX_METER_SEL]	= &a9_hdmirx_meter_sel.hw,
> +	[CLKID_HDMIRX_METER_DIV]	= &a9_hdmirx_meter_div.hw,
> +	[CLKID_HDMIRX_METER]		= &a9_hdmirx_meter.hw,
> +	[CLKID_VID_LOCK_SEL]		= &a9_vid_lock_sel.hw,
> +	[CLKID_VID_LOCK_DIV]		= &a9_vid_lock_div.hw,
> +	[CLKID_VID_LOCK]		= &a9_vid_lock.hw,
> +	[CLKID_VDIN_MEAS_SEL]		= &a9_vdin_meas_sel.hw,
> +	[CLKID_VDIN_MEAS_DIV]		= &a9_vdin_meas_div.hw,
> +	[CLKID_VDIN_MEAS]		= &a9_vdin_meas.hw,
> +	[CLKID_VID_PLL_DIV]		= &a9_vid_pll_div.hw,
> +	[CLKID_VID_PLL_SEL]		= &a9_vid_pll_sel.hw,
> +	[CLKID_VID_PLL]			= &a9_vid_pll.hw,
> +	[CLKID_VID_PLL_VCLK]		= &a9_vid_pll_vclk.hw,
> +	[CLKID_VCLK0_SEL]		= &a9_vclk0_sel.hw,
> +	[CLKID_VCLK0_IN]		= &a9_vclk0_in.hw,
> +	[CLKID_VCLK0_DIV]		= &a9_vclk0_div.hw,
> +	[CLKID_VCLK0]			= &a9_vclk0.hw,
> +	[CLKID_VCLK0_DIV1_EN]		= &a9_vclk0_div1_en.hw,
> +	[CLKID_VCLK0_DIV2_EN]		= &a9_vclk0_div2_en.hw,
> +	[CLKID_VCLK0_DIV2]		= &a9_vclk0_div2.hw,
> +	[CLKID_VCLK0_DIV4_EN]		= &a9_vclk0_div4_en.hw,
> +	[CLKID_VCLK0_DIV4]		= &a9_vclk0_div4.hw,
> +	[CLKID_VCLK0_DIV6_EN]		= &a9_vclk0_div6_en.hw,
> +	[CLKID_VCLK0_DIV6]		= &a9_vclk0_div6.hw,
> +	[CLKID_VCLK0_DIV12_EN]		= &a9_vclk0_div12_en.hw,
> +	[CLKID_VCLK0_DIV12]		= &a9_vclk0_div12.hw,
> +	[CLKID_VCLK1_SEL]		= &a9_vclk1_sel.hw,
> +	[CLKID_VCLK1_IN]		= &a9_vclk1_in.hw,
> +	[CLKID_VCLK1_DIV]		= &a9_vclk1_div.hw,
> +	[CLKID_VCLK1]			= &a9_vclk1.hw,
> +	[CLKID_VCLK1_DIV1_EN]		= &a9_vclk1_div1_en.hw,
> +	[CLKID_VCLK1_DIV2_EN]		= &a9_vclk1_div2_en.hw,
> +	[CLKID_VCLK1_DIV2]		= &a9_vclk1_div2.hw,
> +	[CLKID_VCLK1_DIV4_EN]		= &a9_vclk1_div4_en.hw,
> +	[CLKID_VCLK1_DIV4]		= &a9_vclk1_div4.hw,
> +	[CLKID_VCLK1_DIV6_EN]		= &a9_vclk1_div6_en.hw,
> +	[CLKID_VCLK1_DIV6]		= &a9_vclk1_div6.hw,
> +	[CLKID_VCLK1_DIV12_EN]		= &a9_vclk1_div12_en.hw,
> +	[CLKID_VCLK1_DIV12]		= &a9_vclk1_div12.hw,
> +	[CLKID_VDAC_SEL]		= &a9_vdac_sel.hw,
> +	[CLKID_VDAC]			= &a9_vdac.hw,
> +	[CLKID_ENCODER0_SEL]		= &a9_encoder0_sel.hw,
> +	[CLKID_ENCODER0]		= &a9_encoder0.hw,
> +	[CLKID_ENCODER1_SEL]		= &a9_encoder1_sel.hw,
> +	[CLKID_ENCODER1]		= &a9_encoder1.hw,
> +	[CLKID_HDMITX0_PIXEL_SEL]	= &a9_hdmitx0_pixel_sel.hw,
> +	[CLKID_HDMITX0_PIXEL]		= &a9_hdmitx0_pixel.hw,
> +	[CLKID_HDMITX0_FE_SEL]		= &a9_hdmitx0_fe_sel.hw,
> +	[CLKID_HDMITX0_FE]		= &a9_hdmitx0_fe.hw,
> +	[CLKID_HDMITX1_PIXEL_SEL]	= &a9_hdmitx1_pixel_sel.hw,
> +	[CLKID_HDMITX1_PIXEL]		= &a9_hdmitx1_pixel.hw,
> +	[CLKID_HDMITX1_FE_SEL]		= &a9_hdmitx1_fe_sel.hw,
> +	[CLKID_HDMITX1_FE]		= &a9_hdmitx1_fe.hw,
> +	[CLKID_CSI_PHY_SEL]		= &a9_csi_phy_sel.hw,
> +	[CLKID_CSI_PHY_DIV]		= &a9_csi_phy_div.hw,
> +	[CLKID_CSI_PHY]			= &a9_csi_phy.hw,
> +	[CLKID_DSI0_MEAS_SEL]		= &a9_dsi0_meas_sel.hw,
> +	[CLKID_DSI0_MEAS_DIV]		= &a9_dsi0_meas_div.hw,
> +	[CLKID_DSI0_MEAS]		= &a9_dsi0_meas.hw,
> +	[CLKID_DSI1_MEAS_SEL]		= &a9_dsi1_meas_sel.hw,
> +	[CLKID_DSI1_MEAS_DIV]		= &a9_dsi1_meas_div.hw,
> +	[CLKID_DSI1_MEAS]		= &a9_dsi1_meas.hw,
> +};
> +
> +static const struct meson_clkc_data a9_peripherals_clkc_data = {
> +	.hw_clks = {
> +		.hws = a9_peripherals_hw_clks,
> +		.num = ARRAY_SIZE(a9_peripherals_hw_clks),
> +	},
> +};
> +
> +static const struct of_device_id a9_peripherals_clkc_match_table[] = {
> +	{
> +		.compatible = "amlogic,a9-peripherals-clkc",
> +		.data = &a9_peripherals_clkc_data,
> +	},
> +	{ /* sentinel */ }
> +};
> +
> +MODULE_DEVICE_TABLE(of, a9_peripherals_clkc_match_table);
> +
> +static struct platform_driver a9_peripherals_clkc_driver = {
> +	.probe		= meson_clkc_mmio_probe,
> +	.driver		= {
> +		.name	= "a9-peripherals-clkc",
> +		.of_match_table = a9_peripherals_clkc_match_table,
> +	},
> +};
> +module_platform_driver(a9_peripherals_clkc_driver);
> +
> +MODULE_DESCRIPTION("Amlogic A9 Peripherals Clock Controller driver");
> +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("CLK_MESON");

-- 
Jerome


^ permalink raw reply

* [PATCH v2] Bluetooth: Properly disable remote wakeup for MT7922/MT7925 on Ryzen platform
From: Rong Zhang @ 2026-07-01 15:43 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: Luiz Augusto von Dentz, Chris Lu (陸稚泓),
	Will-CY Lee (李政穎),
	SS Wu (巫憲欣), linux-bluetooth, linux-kernel,
	linux-arm-kernel, linux-mediatek, Rong Zhang

It is reported that a remote wakeup could cause MT7922/MT7925's btusb
interface completely unresponsive. Resetting the xHCI root hub doesn't
help at all, and recovering from such a state needs a power cycle.

All reports seen to be relevant to Ryzen-based laptops. These NICs are
usually used as OEM components thanks to some sort of reference designs.
Their popularity on other platforms is unclear. While there is still a
chance that the quirk may exist on other platforms, be cautious and only
apply the quirk to direct children of Ryzen platforms's root hubs for
the time being. In most cases the root hub is on the SoC or PCH, which
needs the quirk. Unfortunately, this can't distinguish root hubs on PCIe
add-in cards. Such roughness should be acceptable, as PCIe USB
controller add-in cards are less commonly used nowadays. On the other
hand, applying the quirk doesn't hurt any functionalities either, as the
device can still be used as a wakeup source if desired. Theoretically,
we could retrieve the root hub's PCI vendor ID with some hierarchy
magic, but that's too intrusive...

Meanwhile, though device_set_wakeup_capable(false) is the correct fix
for other NICs with fake remote wakeup capabilities, doing so for
MT7922/MT7925 effectively prevents it from being used as wakeup
sources as per userspace requests. Hence, return -EBUSY on runtime
suspend to prevent the interface from being autosuspended while it's
still opened, which has the same effect as
device_set_wakeup_capable(false), since disabling remote wakeup simply
causes the USB core to gate runtime autosuspend as well due to
needs_remote_wakeup == 1. The interface can be safely autosuspended as
long as remote wakeup is disabled, i.e., after closing the HCI device.

Specifically, the interface may still take the advantage of remote
wakeup in order to wake up the system from sleep if userspace has
enabled it as a wakeup source.

Fixes: e31d761628ad ("Bluetooth: btmtk: Disable remote wakeup for MT7922/MT7925")
Signed-off-by: Rong Zhang <i@rong.moe>
---
Changes in v2:
- Only apply the quirk to to direct children of Ryzen platforms's root
  hubs
  - Theoretically, we could retrieve the root hub's PCI vendor ID with
    some hierarchy magic to further limit the range down to only root
    hubs on the SoC or PCH, but that's too intrusive -- the hierarchy
    magic really made me nervous once I saw what I have wrote, so I gave
    it up
- Link to v1: https://patch.msgid.link/20260629-btmtk-ryzen-remote-wakeup-v1-1-1d2f1cee6d22@rong.moe
---
 drivers/bluetooth/btmtk.c | 10 -------
 drivers/bluetooth/btusb.c | 73 ++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 69 insertions(+), 14 deletions(-)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 02a96342e964..4614434dd57b 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -1381,16 +1381,6 @@ int btmtk_usb_setup(struct hci_dev *hdev)
 		break;
 	case 0x7922:
 	case 0x7925:
-		/*
-		 * A remote wakeup could cause the device completely unresponsive, and
-		 * recovering from such a state needs a power cycle.
-		 *
-		 * Since the remote wakeup capability is super broken, just disable it
-		 * to get rid of the troubles. The device can still be autosuspended
-		 * when the bluetooth interface is closed.
-		 */
-		device_set_wakeup_capable(&btmtk_data->udev->dev, false);
-		fallthrough;
 	case 0x7961:
 	case 0x7902:
 	case 0x6639:
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 08c0a99a62c5..eef6e3b43bf9 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -6,6 +6,7 @@
  *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
  */
 
+#include <linux/cpufeature.h>
 #include <linux/dmi.h>
 #include <linux/module.h>
 #include <linux/usb.h>
@@ -957,6 +958,7 @@ struct qca_dump_info {
 #define BTUSB_USE_ALT3_FOR_WBS	15
 #define BTUSB_ALT6_CONTINUOUS_TX	16
 #define BTUSB_HW_SSR_ACTIVE	17
+#define BTUSB_WAKEUP_BROKEN	18
 
 struct btusb_data {
 	struct hci_dev       *hdev;
@@ -2936,10 +2938,25 @@ static int btusb_send_frame_mtk(struct hci_dev *hdev, struct sk_buff *skb)
 	}
 }
 
+static inline bool platform_is_ryzen(void)
+{
+#ifdef CONFIG_X86
+	return boot_cpu_has(X86_FEATURE_ZEN);
+#else
+	return false;
+#endif
+}
+
+static inline bool is_direct_child_of_root_hub(struct usb_device *udev)
+{
+	return udev->parent == udev->bus->root_hub;
+}
+
 static int btusb_mtk_setup(struct hci_dev *hdev)
 {
 	struct btusb_data *data = hci_get_drvdata(hdev);
 	struct btmtk_data *btmtk_data = hci_get_priv(hdev);
+	int err;
 
 	/* MediaTek WMT vendor cmd requiring below USB resources to
 	 * complete the handshake.
@@ -2956,7 +2973,40 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
 		btusb_mtk_claim_iso_intf(data);
 	}
 
-	return btmtk_usb_setup(hdev);
+	err = btmtk_usb_setup(hdev);
+	if (err)
+		return err;
+
+	switch (btmtk_data->dev_id) {
+	case 0x7922:
+	case 0x7925:
+		/*
+		 * All reports seen to be relevant to Ryzen-based laptops. These
+		 * NICs are usually used as OEM components thanks to some sort
+		 * of reference designs.
+		 *
+		 * Their popularity on other platforms is unclear. While there
+		 * is still a chance that the quirk may exist on other
+		 * platforms, be cautious and only apply the quirk to direct
+		 * children of Ryzen platforms's root hubs for the time being.
+		 *
+		 * In most cases the root hub is on the SoC or PCH, which needs
+		 * the quirk. Unfortunately, this can't distinguish root hubs on
+		 * PCIe add-in cards. Such roughness should be acceptable, as
+		 * PCIe USB controller add-in cards are less commonly used
+		 * nowadays. On the other hand, applying the quirk doesn't hurt
+		 * any functionalities either, as the device can still be used
+		 * as a wakeup source if desired.
+		 *
+		 * Theoretically, we could retrieve the root hub's PCI vendor ID
+		 * with some hierarchy magic, but that's too intrusive...
+		 */
+		if (platform_is_ryzen() && is_direct_child_of_root_hub(data->udev))
+			set_bit(BTUSB_WAKEUP_BROKEN, &data->flags);
+		break;
+	}
+
+	return 0;
 }
 
 static int btusb_mtk_shutdown(struct hci_dev *hdev)
@@ -4532,11 +4582,26 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
 
 	BT_DBG("intf %p", intf);
 
-	/* Don't auto-suspend if there are connections or discovery in
-	 * progress; external suspend calls shall never fail.
+	/*
+	 * It is reported that remote wakeup events could sometimes cause some
+	 * adapters completely unresponsive. Resetting the xHCI root hub doesn't
+	 * help at all, and recovering from such a state needs a power cycle.
+	 * Since disabling remote wakeup simply causes the USB core to gate
+	 * runtime autosuspend as well due to needs_remote_wakeup == 1, let's do
+	 * this ourselves to make our life easier. The interface can be safely
+	 * autosuspended as long as remote wakeup is disabled, i.e., after
+	 * closing the HCI device.
+	 *
+	 * Don't auto-suspend if there are connections or discovery in progress.
+	 *
+	 * External suspend calls shall never fail. Specifically, a device with
+	 * broken remote wakeup may still take the advantage of remote wakeup in
+	 * order to wake up the system from sleep if userspace has enabled it as
+	 * a wakeup source.
 	 */
 	if (PMSG_IS_AUTO(message) &&
-	    (hci_conn_count(data->hdev) || hci_discovery_active(data->hdev)))
+	    ((test_bit(BTUSB_WAKEUP_BROKEN, &data->flags) && data->intf->needs_remote_wakeup) ||
+	     hci_conn_count(data->hdev) || hci_discovery_active(data->hdev)))
 		return -EBUSY;
 
 	if (data->suspend_count++)

---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 230ba8c9-btmtk-ryzen-remote-wakeup-055a407682ef

Thanks,
Rong



^ permalink raw reply related

* [PATCH v7 07/11] arm64: dts: ti: k3-am62a-ti-ipc-firmware: Move wkup reserved memory
From: Markus Schneider-Pargmann (TI) @ 2026-07-01 12:39 UTC (permalink / raw)
  To: Nishanth Menon, Vignesh Raghavendra, Tero Kristo, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt, Judith Mendez,
	Daniel Schultz, Andrew Davis, Siddharth Vadapalli, Paresh Bhagat,
	Bryan Brattlof, Jai Luthra, Devarsh Thakkar, Beleswar Padhi,
	Francesco Dolcini, Stefano Radaelli
  Cc: Vishal Mahaveer, Kevin Hilman, Sebin Francis, Kendall Willis,
	Akashdeep Kaur, linux-arm-kernel, devicetree, linux-kernel, llvm,
	Hari Nagalla, Markus Schneider-Pargmann (TI)
In-Reply-To: <20260701-topic-am62a-ioddr-dt-v6-19-v7-0-e9db8b16821a@baylibre.com>

Move the reserved memory regions used for wkup_r5fss0_core0 to the
k3-am62a-ti-ipc-firmware.dtsi. These are all the same for the other
boards as well, so we can combine them here similar to what is already
done for the mcu_r5fss0_core0 memory regions.

It also moves the bootph-pre-ram flags from k3-am62d2-evm.dts into the
firmware dtsi so that all boards inherit them.

Signed-off-by: Markus Schneider-Pargmann (TI) <msp@baylibre.com>
---
 arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi     | 12 ------------
 arch/arm64/boot/dts/ti/k3-am62a-ti-ipc-firmware.dtsi | 14 ++++++++++++++
 arch/arm64/boot/dts/ti/k3-am62a7-sk.dts              | 12 ------------
 arch/arm64/boot/dts/ti/k3-am62d2-evm.dts             | 17 -----------------
 4 files changed, 14 insertions(+), 41 deletions(-)

diff --git a/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
index e13da7c95a30459e7649f284689039b89a95f651..228ffa4be4be7b32e43a06d807d3fee073d203dc 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a-phycore-som.dtsi
@@ -59,18 +59,6 @@ linux,cma {
 			linux,cma-default;
 		};
 
-		wkup_r5fss0_core0_dma_memory_region: memory@9c800000 {
-			compatible = "shared-dma-pool";
-			reg = <0x00 0x9c800000 0x00 0x100000>;
-			no-map;
-		};
-
-		wkup_r5fss0_core0_memory_region: memory@9c900000 {
-			compatible = "shared-dma-pool";
-			reg = <0x00 0x9c900000 0x00 0x01d00000>;
-			no-map;
-		};
-
 		secure_tfa_ddr: tfa@9e780000 {
 			reg = <0x00 0x9e780000 0x00 0x80000>;
 			alignment = <0x1000>;
diff --git a/arch/arm64/boot/dts/ti/k3-am62a-ti-ipc-firmware.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-ti-ipc-firmware.dtsi
index 06d4e815b1670beafb8852b76a3f6a79295ce8ca..682b1c9f3071ddf23044c1fde1e88f2b901ec64c 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a-ti-ipc-firmware.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a-ti-ipc-firmware.dtsi
@@ -29,6 +29,19 @@ mcu_r5fss0_core0_memory_region: memory@9b900000 {
 		reg = <0x00 0x9b900000 0x00 0xf00000>;
 		no-map;
 	};
+
+	wkup_r5fss0_core0_dma_memory_region: memory@9c800000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0x9c800000 0x00 0x100000>;
+		no-map;
+	};
+
+	wkup_r5fss0_core0_memory_region: memory@9c900000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0x9c900000 0x00 0x01d00000>;
+		no-map;
+		bootph-pre-ram;
+	};
 };
 
 &mailbox0_cluster0 {
@@ -67,6 +80,7 @@ &wkup_r5fss0_core0 {
 	memory-region = <&wkup_r5fss0_core0_dma_memory_region>,
 			<&wkup_r5fss0_core0_memory_region>;
 	memory-region-names = "dma", "firmware";
+	bootph-pre-ram;
 	status = "okay";
 };
 
diff --git a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
index 08c73cae26c73993a613372110bfd5611c403846..27801c22a550330b52c4424f919d80f10dc76403 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
@@ -53,18 +53,6 @@ linux,cma {
 			linux,cma-default;
 		};
 
-		wkup_r5fss0_core0_dma_memory_region: memory@9c800000 {
-			compatible = "shared-dma-pool";
-			reg = <0x00 0x9c800000 0x00 0x100000>;
-			no-map;
-		};
-
-		wkup_r5fss0_core0_memory_region: memory@9c900000 {
-			compatible = "shared-dma-pool";
-			reg = <0x00 0x9c900000 0x00 0x01d00000>;
-			no-map;
-		};
-
 		secure_tfa_ddr: tfa@9e780000 {
 			reg = <0x00 0x9e780000 0x00 0x80000>;
 			alignment = <0x1000>;
diff --git a/arch/arm64/boot/dts/ti/k3-am62d2-evm.dts b/arch/arm64/boot/dts/ti/k3-am62d2-evm.dts
index 463a3f6130b8f2927a032137e87c01df446cffda..dd6937789a9c6b7c92ef5ad1fcc3ae94a90e2353 100644
--- a/arch/arm64/boot/dts/ti/k3-am62d2-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62d2-evm.dts
@@ -59,19 +59,6 @@ secure_tfa_ddr: tfa@80000000 {
 			no-map;
 		};
 
-		wkup_r5fss0_core0_dma_memory_region: memory@9c800000 {
-			compatible = "shared-dma-pool";
-			reg = <0x00 0x9c800000 0x00 0x100000>;
-			no-map;
-		};
-
-		wkup_r5fss0_core0_memory_region: memory@9c900000 {
-			compatible = "shared-dma-pool";
-			reg = <0x00 0x9c900000 0x00 0x01d00000>;
-			no-map;
-			bootph-pre-ram;
-		};
-
 		secure_ddr: optee@9e800000 {
 			reg = <0x00 0x9e800000 0x00 0x01800000>; /* for OP-TEE */
 			no-map;
@@ -776,10 +763,6 @@ partition@3fc0000 {
 	};
 };
 
-&wkup_r5fss0_core0 {
-	bootph-pre-ram;
-};
-
 &mcu_r5fss0_core0 {
 	firmware-name = "am62d-mcu-r5f0_0-fw";
 };

-- 
2.53.0



^ permalink raw reply related

* [PATCH] iommu/arm-smmu-v3: Shrink command/event/PRI queues in kdump kernel
From: Kiryl Shutsemau (Meta) @ 2026-07-01 15:45 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel
  Cc: Jason Gunthorpe, Nicolin Chen, Kyle McMartin, Breno Leitao,
	Usama Arif, linux-arm-kernel, iommu, linux-kernel,
	Kiryl Shutsemau (Meta)

The command, event and PRI queues are sized from the maxima the hardware
advertises in IDR1, which can be several megabytes each. On systems with
many SMMUv3 instances that cost is paid per instance and adds up to tens
of megabytes of coherent DMA in the capture kernel.

A kdump capture kernel runs from a small crashkernel reservation and only
has to drive the few devices used to save the dump, so deep queues serve
no purpose. The queues carry invalidation commands and fault records, not
DMA data, so dump throughput is unaffected; a shallower queue only bounds
how many commands may be in flight before a sync, which does not matter for
the capture kernel's small device count and modest I/O.

Clamp every queue to a single page when is_kdump_kernel() is true. Doing
it in arm_smmu_init_one_queue() covers the command, event and PRI queues
in one place. The command queue still holds at least one batch plus a sync
(256 entries on a 4K-page kernel, well above CMDQ_BATCH_ENTRIES), so
command batching keeps working.

Suggested-by: Kyle McMartin <jkkm@meta.com>
Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index e8d7dbe495f0..6ec3ef5ee0da 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4414,6 +4414,20 @@ int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
 {
 	size_t qsz;
 
+	/*
+	 * A kdump capture kernel runs from a small crashkernel reservation and
+	 * only has to drive the few devices used to save the dump, so there is
+	 * no point sizing the queues for the (multi-megabyte) maxima the
+	 * hardware advertises. Clamp each queue to a single page. ent_sz_shift
+	 * is the log2 of the entry size in bytes (dwords * 8).
+	 */
+	if (is_kdump_kernel()) {
+		u32 ent_sz_shift = ilog2(dwords) + 3;
+
+		q->llq.max_n_shift = min_t(u32, q->llq.max_n_shift,
+					   PAGE_SHIFT - ent_sz_shift);
+	}
+
 	do {
 		qsz = ((1 << q->llq.max_n_shift) * dwords) << 3;
 		q->base = dmam_alloc_coherent(smmu->dev, qsz, &q->base_dma,
-- 
2.54.0



^ permalink raw reply related

* [PATCH] dt-bindings: dma: mediatek,uart-dma: add support for MT8189 SoC
From: Louis-Alexis Eyraud @ 2026-07-01 15:47 UTC (permalink / raw)
  To: Sean Wang, Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Long Cheng
  Cc: kernel, dmaengine, linux-arm-kernel, linux-mediatek, devicetree,
	linux-kernel, Louis-Alexis Eyraud

Add the compatible string for the APDMA IP found in MT8189 SoC,
that supports 35-bits addressing as MT6985 SoC.

Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
---
 Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml b/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml
index 3708518fe7fc..bba20e88a6dc 100644
--- a/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml
+++ b/Documentation/devicetree/bindings/dma/mediatek,uart-dma.yaml
@@ -40,6 +40,7 @@ properties:
       - items:
           - enum:
               - mediatek,mt6991-uart-dma
+              - mediatek,mt8189-uart-dma
               - mediatek,mt8196-uart-dma
           - const: mediatek,mt6985-uart-dma
       - enum:

---
base-commit: ba7c57499e5999aeae8dd4f954eb2600589d80aa
change-id: 20260701-mt8189-dt-bindings-uart-dma-f8fdbe856ee8

Best regards,
-- 
Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>



^ permalink raw reply related

* Re: (subset) [PATCH v5 0/2] media: nxp: imx8-isi: Add virtual channel and frame descriptor support
From: Frank Li @ 2026-07-01 15:51 UTC (permalink / raw)
  To: Bryan O'Donoghue
  Cc: Laurent Pinchart, Mauro Carvalho Chehab, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Guoniu Zhou, Frank Li,
	Aisheng Dong, linux-media, imx, linux-arm-kernel, linux-kernel,
	Guoniu Zhou
In-Reply-To: <24be88f8-156a-432f-8d2a-4b0417e042c7@kernel.org>

On Tue, Jun 30, 2026 at 11:20:53PM +0100, Bryan O'Donoghue wrote:
> On 30/06/2026 17:20, Frank Li wrote:
> > On Mon, Jun 29, 2026 at 11:23:02PM +0300, Laurent Pinchart wrote:
> > > On Mon, Jun 29, 2026 at 03:42:31PM -0400, Frank.Li@oss.nxp.com wrote:
> > > > From: Frank Li <Frank.Li@nxp.com>
> > > >
> > > >
> > > > On Thu, 21 May 2026 17:10:03 +0800, Guoniu Zhou wrote:
> > > > > This patch series enhances the i.MX ISI driver's with virtual channel
> > > > > support and adds frame descriptor capabilities to the crossbar subdevice.
> > > >
> > > > Applied, thanks!
> > > >
> > > > [1/2] media: imx8-isi: crossbar: Add get_frame_desc operation
> > > >        commit: 3e15a3510908c990ee352aa206d5f9c23d4b216e
> > >
> > > Is this a mistake ? Patch 1/2 has no R-b tag, and you're not listed as
> > > maintainer for this driver.
> >
> > Sorry, I missed checking Maintainer files, in media summit, agree on I pick
> > imx's media drivers, but forget finalize the file\dir list. Can you help
> > summery which files\dir I should take care?
> >
> > If you have concern about this patch, I can drop it.
> >
> > Frank
> You should set yourself up here:
> https://patchwork.linuxtv.org/project/linux-media/list/

I just register it.

"Registration successful!

A confirmation email has been sent to frank.li@kernel.org. You'll need to visit the link provided in that email to confirm your registration."

I have not recieved such confirm email. Anything wrong?

Frank


>
> That way you can coordinate with other maintainers on which files get
> reviewed by whom, see what the RB and ci status is.
>
> Its pretty essential.
>
> ---
> bod


^ permalink raw reply

* [PATCH v1 1/1] arm64: dts: imx95-var-dart: wm8904: Add INL1 as DMICDAT1
From: Stefano Radaelli @ 2026-07-01 15:53 UTC (permalink / raw)
  To: linux-kernel, devicetree, imx, linux-arm-kernel
  Cc: pierluigi.p, Stefano Radaelli, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, Alexander Herfurtner

From: Stefano Radaelli <stefano.r@variscite.com>

On the DART-MX95 platform, INL1/DMICDAT1 is used as the DMIC data line.

Add the wlf,in1l-as-dmicdat1 property to reflect this configuration.
This enables the internal MUX to switch between the ADC and DMIC as the
capture input.

Co-developed-by: Alexander Herfurtner <alexander.h@variscite.com>
Signed-off-by: Alexander Herfurtner <alexander.h@variscite.com>
Signed-off-by: Stefano Radaelli <stefano.r@variscite.com>
---
 arch/arm64/boot/dts/freescale/imx95-var-dart.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx95-var-dart.dtsi b/arch/arm64/boot/dts/freescale/imx95-var-dart.dtsi
index a20fadacaa6d..d43270a1d907 100644
--- a/arch/arm64/boot/dts/freescale/imx95-var-dart.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx95-var-dart.dtsi
@@ -158,6 +158,8 @@ wm8904: audio-codec@1a {
 				   /bits/ 16 <0x04af 0x324b 0x0010 0x050e>;
 		/* GPIO1 = DMIC_CLK, don't touch others */
 		wlf,gpio-cfg = <0x0018>, <0xffff>, <0xffff>, <0xffff>;
+		/* DMIC is connected to IN1L */
+		wlf,in1l-as-dmicdat1;
 	};
 };
 
-- 
2.47.3



^ permalink raw reply related

* [PATCH 06/10] drm/mediatek: mtk_dsi: Add support for MT8189
From: AngeloGioacchino Del Regno @ 2026-07-01 12:19 UTC (permalink / raw)
  To: chunkuang.hu
  Cc: p.zabel, maarten.lankhorst, mripard, tzimmermann, airlied, simona,
	robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
	jitao.shi, dri-devel, linux-mediatek, devicetree, linux-kernel,
	linux-arm-kernel, kernel, justin.yeh, jason-jh.lin
In-Reply-To: <20260701121950.19454-1-angelogioacchino.delregno@collabora.com>

Add support for the DSI IP found in the MT8189 SoC: this one is
similar to the IPs found in the most recent already supported SoCs
with the only difference being that it supports a higher link rate
of 2.5Gbps instead of 1.5Gbps.

To support the higher rate, add a new "max_link_rate_mbps" member
to the mtk_dsi_driver_data, assign the correct one to all of the
supported SoCs, other than to the newly introduced MT8189, and
use it in the .mode_valid() callback in place of the hardcoded
1.5Gbps value.

Since .mode_valid() is supposed to run just for resolution changes
the link rate was expressed in Mbps and gets multiplied on the fly
to save some bits.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/gpu/drm/mediatek/mtk_dsi.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 37c34413130b..ba96c12a8ceb 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -235,6 +235,8 @@ struct mtk_dsi_driver_data {
 	const u16 *reg_main;
 	const u16 *reg_adv;
 
+	const u16 max_link_rate_mbps;
+
 	bool has_size_ctl;
 	bool cmdq_long_packet_ctl;
 	bool support_per_frame_lp;
@@ -1066,13 +1068,20 @@ mtk_dsi_bridge_mode_valid(struct drm_bridge *bridge,
 			  const struct drm_display_mode *mode)
 {
 	struct mtk_dsi *dsi = bridge_to_dsi(bridge);
+	const struct mtk_dsi_driver_data *data = dsi->driver_data;
+	u64 wanted_link_rate, max_link_rate;
 	int bpp;
 
 	bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
 	if (bpp < 0)
 		return MODE_ERROR;
 
-	if (mode->clock * bpp / dsi->lanes > 1500000)
+	wanted_link_rate = mode->clock * bpp;
+	max_link_rate = data->max_link_rate_mbps;
+	max_link_rate *= dsi->lanes;
+	max_link_rate *= KILO;
+
+	if (wanted_link_rate > max_link_rate)
 		return MODE_CLOCK_HIGH;
 
 	if (dsi->dsc) {
@@ -1499,28 +1508,42 @@ static void mtk_dsi_remove(struct platform_device *pdev)
 static const struct mtk_dsi_driver_data mt8173_dsi_driver_data = {
 	.reg_main = mtk_dsi_regs_main_v1,
 	.reg_adv = mtk_dsi_regs_mt8173,
+	.max_link_rate_mbps = 1500,
 };
 
 static const struct mtk_dsi_driver_data mt2701_dsi_driver_data = {
 	.reg_main = mtk_dsi_regs_main_v1,
 	.reg_adv = mtk_dsi_regs_mt2701,
+	.max_link_rate_mbps = 1500,
 };
 
 static const struct mtk_dsi_driver_data mt8183_dsi_driver_data = {
 	.reg_main = mtk_dsi_regs_main_v1,
 	.reg_adv = mtk_dsi_regs_mt8183,
+	.max_link_rate_mbps = 1500,
 	.has_size_ctl = true,
 };
 
 static const struct mtk_dsi_driver_data mt8186_dsi_driver_data = {
 	.reg_main = mtk_dsi_regs_main_v1,
 	.reg_adv = mtk_dsi_regs_mt8186,
+	.max_link_rate_mbps = 1500,
 	.has_size_ctl = true,
 };
 
 static const struct mtk_dsi_driver_data mt8188_dsi_driver_data = {
 	.reg_main = mtk_dsi_regs_main_v1,
 	.reg_adv = mtk_dsi_regs_mt8186,
+	.max_link_rate_mbps = 1500,
+	.has_size_ctl = true,
+	.cmdq_long_packet_ctl = true,
+	.support_per_frame_lp = true,
+};
+
+static const struct mtk_dsi_driver_data mt8189_dsi_driver_data = {
+	.reg_main = mtk_dsi_regs_main_v1,
+	.reg_adv = mtk_dsi_regs_mt8186,
+	.max_link_rate_mbps = 2500,
 	.has_size_ctl = true,
 	.cmdq_long_packet_ctl = true,
 	.support_per_frame_lp = true,
@@ -1532,6 +1555,7 @@ static const struct of_device_id mtk_dsi_of_match[] = {
 	{ .compatible = "mediatek,mt8183-dsi", .data = &mt8183_dsi_driver_data },
 	{ .compatible = "mediatek,mt8186-dsi", .data = &mt8186_dsi_driver_data },
 	{ .compatible = "mediatek,mt8188-dsi", .data = &mt8188_dsi_driver_data },
+	{ .compatible = "mediatek,mt8189-dsi", .data = &mt8189_dsi_driver_data },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mtk_dsi_of_match);
-- 
2.54.0



^ permalink raw reply related

* [PATCH 05/10] drm/mediatek: mtk_dsi: Transfer register offsets to per-SoC const
From: AngeloGioacchino Del Regno @ 2026-07-01 12:19 UTC (permalink / raw)
  To: chunkuang.hu
  Cc: p.zabel, maarten.lankhorst, mripard, tzimmermann, airlied, simona,
	robh, krzk+dt, conor+dt, matthias.bgg, angelogioacchino.delregno,
	jitao.shi, dri-devel, linux-mediatek, devicetree, linux-kernel,
	linux-arm-kernel, kernel, justin.yeh, jason-jh.lin
In-Reply-To: <20260701121950.19454-1-angelogioacchino.delregno@collabora.com>

As of now, the all of the supported SoCs have small differences in
the register offsets for their version of the DSI IP, at least for
the VM_CMD_CON, SHADOW_DEBUG and CMDQ offsets.

As a preparation for introducing support for newer generation DSI
IPs, having even more differences in the register offsets (but not
in the layout of their fields, nor in the actual programming), as
found on Dimensity 9400 MT6991, Kompanio Ultra MT8196 and Genio
Pro 5100 MT8894, transfer all the register offsets to two const
arrays, splitting the DSI IP version specific registers from the
SoC specific ones (as those depend on interfacing with CMDQ and
other IPs external to DSI, but internal to the SoC, and embedded
in DSI).

This change brings no functional difference, as it only changes
how the register offsets are retrieved and nothing else.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/gpu/drm/mediatek/mtk_dsi.c | 378 +++++++++++++++++++----------
 1 file changed, 253 insertions(+), 125 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 56c69f80a2ef..37c34413130b 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2015 MediaTek Inc.
+ * Copyright (c) 2026 Collabora Ltd.
+ *                    AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
  */
 
 #include <linux/bitfield.h>
@@ -34,11 +36,11 @@
 #include "mtk_disp_drv.h"
 #include "mtk_drm_drv.h"
 
-#define DSI_START		0x00
+/* DSI_START */
 
-#define DSI_INTEN		0x08
+/* DSI_INTEN */
 
-#define DSI_INTSTA		0x0c
+/* DSI_INTSTA */
 #define LPRX_RD_RDY_INT_FLAG		BIT(0)
 #define CMD_DONE_INT_FLAG		BIT(1)
 #define TE_RDY_INT_FLAG			BIT(2)
@@ -46,12 +48,13 @@
 #define EXT_TE_RDY_INT_FLAG		BIT(4)
 #define DSI_BUSY			BIT(31)
 
-#define DSI_CON_CTRL		0x10
+/* DSI_CON_CTRL */
 #define DSI_RESET			BIT(0)
 #define DSI_EN				BIT(1)
 #define DPHY_RESET			BIT(2)
+#define CMDMODE_WAIT_DATA_EVERY_LINE_EN	BIT(24)
 
-#define DSI_MODE_CTRL		0x14
+/* DSI_MODE_CTRL */
 #define MODE				(3)
 #define CMD_MODE			0
 #define SYNC_PULSE_MODE			1
@@ -60,7 +63,7 @@
 #define FRM_MODE			BIT(16)
 #define MIX_MODE			BIT(17)
 
-#define DSI_TXRX_CTRL		0x18
+/* DSI_TXRX_CTRL */
 #define VC_NUM				BIT(1)
 #define LANE_NUM			GENMASK(5, 2)
 #define DIS_EOT				BIT(6)
@@ -71,7 +74,7 @@
 #define MAX_RTN_SIZE			GENMASK(15, 12)
 #define HSTX_CKLP_EN			BIT(16)
 
-#define DSI_PSCTRL		0x1c
+/* DSI_PSCTRL */
 #define DSI_PS_WC			GENMASK(13, 0)
 #define DSI_PS_SEL			GENMASK(19, 16)
 #define PACKED_PS_16BIT_RGB565		0
@@ -80,64 +83,64 @@
 #define PACKED_PS_24BIT_RGB888		3
 #define COMPRESSED_PS_DSC		5
 
-#define DSI_VSA_NL		0x20
-#define DSI_VBP_NL		0x24
-#define DSI_VFP_NL		0x28
-#define DSI_VACT_NL		0x2C
+/* DSI_VSA_NL */
+/* DSI_VBP_NL */
+/* DSI_VFP_NL */
+/* DSI_VACT_NL */
 #define VACT_NL				GENMASK(14, 0)
-#define DSI_SIZE_CON		0x38
-#define DSI_HEIGHT				GENMASK(30, 16)
-#define DSI_WIDTH				GENMASK(14, 0)
-#define DSI_HSA_WC		0x50
-#define DSI_HBP_WC		0x54
-#define DSI_HFP_WC		0x58
-#define HFP_HS_VB_PS_WC		GENMASK(30, 16)
+/* DSI_SIZE_CON */
+#define DSI_HEIGHT			GENMASK(30, 16)
+#define DSI_WIDTH			GENMASK(14, 0)
+/* DSI_HSA_WC */
+/* DSI_HBP_WC */
+/* DSI_HFP_WC */
+#define HFP_HS_VB_PS_WC			GENMASK(30, 16)
 #define HFP_HS_EN			BIT(31)
 
-#define DSI_CMDQ_SIZE		0x60
+/* DSI_CMDQ_SIZE */
 #define CMDQ_SIZE			0x3f
-#define CMDQ_SIZE_SEL		BIT(15)
+#define CMDQ_SIZE_SEL			BIT(15)
 
-#define DSI_HSTX_CKL_WC		0x64
+/* DSI_HSTX_CKL_WC */
 #define HSTX_CKL_WC			GENMASK(15, 2)
 
-#define DSI_RX_DATA0		0x74
-#define DSI_RX_DATA1		0x78
-#define DSI_RX_DATA2		0x7c
-#define DSI_RX_DATA3		0x80
+/* DSI_RX_DATA0 */
+/* DSI_RX_DATA1 */
+/* DSI_RX_DATA2 */
+/* DSI_RX_DATA3 */
 
-#define DSI_RACK		0x84
+/* DSI_RACK */
 #define RACK				BIT(0)
 
-#define DSI_PHY_LCCON		0x104
+/* DSI_PHY_LCCON */
 #define LC_HS_TX_EN			BIT(0)
 #define LC_ULPM_EN			BIT(1)
 #define LC_WAKEUP_EN			BIT(2)
 
-#define DSI_PHY_LD0CON		0x108
+/* DSI_PHY_LD0CON */
 #define LD0_HS_TX_EN			BIT(0)
 #define LD0_ULPM_EN			BIT(1)
 #define LD0_WAKEUP_EN			BIT(2)
 
-#define DSI_PHY_TIMECON0	0x110
+/* DSI_PHY_TIMECON0 */
 #define LPX				GENMASK(7, 0)
 #define HS_PREP				GENMASK(15, 8)
 #define HS_ZERO				GENMASK(23, 16)
 #define HS_TRAIL			GENMASK(31, 24)
 
-#define DSI_PHY_TIMECON1	0x114
+/* DSI_PHY_TIMECON1 */
 #define TA_GO				GENMASK(7, 0)
 #define TA_SURE				GENMASK(15, 8)
 #define TA_GET				GENMASK(23, 16)
 #define DA_HS_EXIT			GENMASK(31, 24)
 
-#define DSI_PHY_TIMECON2	0x118
+/* DSI_PHY_TIMECON2 */
 #define CONT_DET			GENMASK(7, 0)
 #define DA_HS_SYNC			GENMASK(15, 8)
 #define CLK_ZERO			GENMASK(23, 16)
 #define CLK_TRAIL			GENMASK(31, 24)
 
-#define DSI_PHY_TIMECON3	0x11c
+/* DSI_PHY_TIMECON3 */
 #define CLK_HS_PREP			GENMASK(7, 0)
 #define CLK_HS_POST			GENMASK(15, 8)
 #define CLK_HS_EXIT			GENMASK(23, 16)
@@ -168,6 +171,45 @@
 	(type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
 	(type == MIPI_DSI_DCS_READ))
 
+enum mtk_dsi_main_regidx {
+	DSI_START,
+	DSI_INTEN,
+	DSI_INTSTA,
+	DSI_CON_CTRL,
+	DSI_MODE_CTRL,
+	DSI_TXRX_CTRL,
+	DSI_PSCTRL,
+	DSI_VSA_NL,
+	DSI_VBP_NL,
+	DSI_VFP_NL,
+	DSI_VACT_NL,
+	DSI_SIZE_CON,
+	DSI_HSA_WC,
+	DSI_HBP_WC,
+	DSI_HFP_WC,
+	DSI_CMDQ_SIZE,
+	DSI_HSTX_CKL_WC,
+	DSI_RX_DATA0,
+	DSI_RX_DATA1,
+	DSI_RX_DATA2,
+	DSI_RX_DATA3,
+	DSI_RACK,
+	DSI_PHY_LCCON,
+	DSI_PHY_LD0CON,
+	DSI_PHY_TIMECON0,
+	DSI_PHY_TIMECON1,
+	DSI_PHY_TIMECON2,
+	DSI_PHY_TIMECON3,
+	DSI_MAIN_REG_MAX
+};
+
+enum mtk_dsi_adv_regidx {
+	DSI_VM_CMD_CON,
+	DSI_SHADOW_DEBUG,
+	DSI_CMDQ,
+	DSI_ADV_REG_MAX
+};
+
 struct mtk_phy_timing {
 	u32 lpx;
 	u32 da_hs_prepare;
@@ -190,10 +232,9 @@ struct mtk_phy_timing {
 struct phy;
 
 struct mtk_dsi_driver_data {
-	const u32 reg_cmdq_off;
-	const u32 reg_vm_cmd_off;
-	const u32 reg_shadow_dbg_off;
-	bool has_shadow_ctl;
+	const u16 *reg_main;
+	const u16 *reg_adv;
+
 	bool has_size_ctl;
 	bool cmdq_long_packet_ctl;
 	bool support_per_frame_lp;
@@ -231,6 +272,61 @@ struct mtk_dsi {
 	const struct mtk_dsi_driver_data *driver_data;
 };
 
+static const u16 mtk_dsi_regs_main_v1[DSI_MAIN_REG_MAX] = {
+	[DSI_START] = 0x00,
+	[DSI_INTEN] = 0x08,
+	[DSI_INTSTA] = 0x0c,
+	[DSI_CON_CTRL] = 0x10,
+	[DSI_MODE_CTRL] = 0x14,
+	[DSI_TXRX_CTRL] = 0x18,
+	[DSI_PSCTRL] = 0x1c,
+	[DSI_VSA_NL] = 0x20,
+	[DSI_VBP_NL] = 0x24,
+	[DSI_VFP_NL] = 0x28,
+	[DSI_VACT_NL] = 0x2c,
+	[DSI_SIZE_CON] = 0x38,
+	[DSI_HSA_WC] = 0x50,
+	[DSI_HBP_WC] = 0x54,
+	[DSI_HFP_WC] = 0x58,
+	[DSI_CMDQ_SIZE] = 0x60,
+	[DSI_HSTX_CKL_WC] = 0x64,
+	[DSI_RX_DATA0] = 0x74,
+	[DSI_RX_DATA1] = 0x78,
+	[DSI_RX_DATA2] = 0x7c,
+	[DSI_RX_DATA3] = 0x80,
+	[DSI_RACK] = 0x84,
+	[DSI_PHY_LCCON] = 0x104,
+	[DSI_PHY_LD0CON] = 0x108,
+	[DSI_PHY_TIMECON0] = 0x110,
+	[DSI_PHY_TIMECON1] = 0x114,
+	[DSI_PHY_TIMECON2] = 0x118,
+	[DSI_PHY_TIMECON3] = 0x11c,
+};
+
+static const u16 mtk_dsi_regs_mt2701[DSI_ADV_REG_MAX] = {
+	[DSI_VM_CMD_CON] = 0x130,
+	[DSI_SHADOW_DEBUG] = 0,
+	[DSI_CMDQ] = 0x180,
+};
+
+static const u16 mtk_dsi_regs_mt8173[DSI_ADV_REG_MAX] = {
+	[DSI_VM_CMD_CON] = 0x130,
+	[DSI_SHADOW_DEBUG] = 0,
+	[DSI_CMDQ] = 0x200,
+};
+
+static const u16 mtk_dsi_regs_mt8183[DSI_ADV_REG_MAX] = {
+	[DSI_VM_CMD_CON] = 0x130,
+	[DSI_SHADOW_DEBUG] = 0x190,
+	[DSI_CMDQ] = 0x200,
+};
+
+static const u16 mtk_dsi_regs_mt8186[DSI_ADV_REG_MAX] = {
+	[DSI_VM_CMD_CON] = 0x200,
+	[DSI_SHADOW_DEBUG] = 0xc00,
+	[DSI_CMDQ] = 0xd00,
+};
+
 static inline struct mtk_dsi *bridge_to_dsi(struct drm_bridge *b)
 {
 	return container_of(b, struct mtk_dsi, bridge);
@@ -253,6 +349,7 @@ static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi)
 	u32 timcon0, timcon1, timcon2, timcon3;
 	u32 data_rate_mhz = DIV_ROUND_UP(dsi->data_rate, HZ_PER_MHZ);
 	struct mtk_phy_timing *timing = &dsi->phy_timing;
+	const u16 *reg_main = dsi->driver_data->reg_main;
 
 	timing->lpx = (60 * data_rate_mhz / (8 * 1000)) + 1;
 	timing->da_hs_prepare = (80 * data_rate_mhz + 4 * 1000) / 8000;
@@ -289,76 +386,97 @@ static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi)
 		  FIELD_PREP(CLK_HS_POST, timing->clk_hs_post) |
 		  FIELD_PREP(CLK_HS_EXIT, timing->clk_hs_exit);
 
-	writel(timcon0, dsi->regs + DSI_PHY_TIMECON0);
-	writel(timcon1, dsi->regs + DSI_PHY_TIMECON1);
-	writel(timcon2, dsi->regs + DSI_PHY_TIMECON2);
-	writel(timcon3, dsi->regs + DSI_PHY_TIMECON3);
+	writel(timcon0, dsi->regs + reg_main[DSI_PHY_TIMECON0]);
+	writel(timcon1, dsi->regs + reg_main[DSI_PHY_TIMECON1]);
+	writel(timcon2, dsi->regs + reg_main[DSI_PHY_TIMECON2]);
+	writel(timcon3, dsi->regs + reg_main[DSI_PHY_TIMECON3]);
 }
 
 static void mtk_dsi_enable(struct mtk_dsi *dsi)
 {
-	mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, DSI_EN);
+	const u16 *reg_main = dsi->driver_data->reg_main;
+
+	mtk_dsi_mask(dsi, reg_main[DSI_CON_CTRL], DSI_EN, DSI_EN);
 }
 
 static void mtk_dsi_disable(struct mtk_dsi *dsi)
 {
-	mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, 0);
+	const u16 *reg_main = dsi->driver_data->reg_main;
+
+	mtk_dsi_mask(dsi, reg_main[DSI_CON_CTRL], DSI_EN, 0);
 }
 
 static void mtk_dsi_reset_engine(struct mtk_dsi *dsi)
 {
-	mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, DSI_RESET);
-	mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, 0);
+	const u16 *reg_main = dsi->driver_data->reg_main;
+
+	mtk_dsi_mask(dsi, reg_main[DSI_CON_CTRL], DSI_RESET, DSI_RESET);
+	mtk_dsi_mask(dsi, reg_main[DSI_CON_CTRL], DSI_RESET, 0);
 }
 
 static void mtk_dsi_reset_dphy(struct mtk_dsi *dsi)
 {
-	mtk_dsi_mask(dsi, DSI_CON_CTRL, DPHY_RESET, DPHY_RESET);
-	mtk_dsi_mask(dsi, DSI_CON_CTRL, DPHY_RESET, 0);
+	const u16 *reg_main = dsi->driver_data->reg_main;
+
+	mtk_dsi_mask(dsi, reg_main[DSI_CON_CTRL], DPHY_RESET, DPHY_RESET);
+	mtk_dsi_mask(dsi, reg_main[DSI_CON_CTRL], DPHY_RESET, 0);
 }
 
 static void mtk_dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi)
 {
-	mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
-	mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0);
+	const u16 *reg_main = dsi->driver_data->reg_main;
+
+	mtk_dsi_mask(dsi, reg_main[DSI_PHY_LCCON], LC_HS_TX_EN, 0);
+	mtk_dsi_mask(dsi, reg_main[DSI_PHY_LCCON], LC_ULPM_EN, 0);
 }
 
 static void mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi)
 {
-	mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0);
-	mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, LC_WAKEUP_EN);
-	mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, 0);
+	const u16 *reg_main = dsi->driver_data->reg_main;
+
+	mtk_dsi_mask(dsi, reg_main[DSI_PHY_LCCON], LC_ULPM_EN, 0);
+	mtk_dsi_mask(dsi, reg_main[DSI_PHY_LCCON], LC_WAKEUP_EN, LC_WAKEUP_EN);
+	mtk_dsi_mask(dsi, reg_main[DSI_PHY_LCCON], LC_WAKEUP_EN, 0);
 }
 
 static void mtk_dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi)
 {
-	mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_HS_TX_EN, 0);
-	mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0);
+	const u16 *reg_main = dsi->driver_data->reg_main;
+
+	mtk_dsi_mask(dsi, reg_main[DSI_PHY_LD0CON], LD0_HS_TX_EN, 0);
+	mtk_dsi_mask(dsi, reg_main[DSI_PHY_LD0CON], LD0_ULPM_EN, 0);
 }
 
 static void mtk_dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi)
 {
-	mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0);
-	mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, LD0_WAKEUP_EN);
-	mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, 0);
+	const u16 *reg_main = dsi->driver_data->reg_main;
+
+	mtk_dsi_mask(dsi, reg_main[DSI_PHY_LD0CON], LD0_ULPM_EN, 0);
+	mtk_dsi_mask(dsi, reg_main[DSI_PHY_LD0CON], LD0_WAKEUP_EN, LD0_WAKEUP_EN);
+	mtk_dsi_mask(dsi, reg_main[DSI_PHY_LD0CON], LD0_WAKEUP_EN, 0);
 }
 
 static bool mtk_dsi_clk_hs_state(struct mtk_dsi *dsi)
 {
-	return readl(dsi->regs + DSI_PHY_LCCON) & LC_HS_TX_EN;
+	const u16 *regoff = dsi->driver_data->reg_main;
+
+	return readl(dsi->regs + regoff[DSI_PHY_LCCON]) & LC_HS_TX_EN;
 }
 
 static void mtk_dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter)
 {
+	const u16 *reg_main = dsi->driver_data->reg_main;
+
 	if (enter && !mtk_dsi_clk_hs_state(dsi))
-		mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, LC_HS_TX_EN);
+		mtk_dsi_mask(dsi, reg_main[DSI_PHY_LCCON], LC_HS_TX_EN, LC_HS_TX_EN);
 	else if (!enter && mtk_dsi_clk_hs_state(dsi))
-		mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
+		mtk_dsi_mask(dsi, reg_main[DSI_PHY_LCCON], LC_HS_TX_EN, 0);
 }
 
 static void mtk_dsi_set_mode(struct mtk_dsi *dsi)
 {
-	u32 vid_mode = CMD_MODE;
+	const u16 *reg_main = dsi->driver_data->reg_main;
+	u32 vid_mode;
 
 	if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
 		if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
@@ -367,19 +485,24 @@ static void mtk_dsi_set_mode(struct mtk_dsi *dsi)
 			vid_mode = SYNC_PULSE_MODE;
 		else
 			vid_mode = SYNC_EVENT_MODE;
+	} else {
+		vid_mode = CMD_MODE;
 	}
 
-	writel(vid_mode, dsi->regs + DSI_MODE_CTRL);
+	writel(vid_mode, dsi->regs + reg_main[DSI_MODE_CTRL]);
 }
 
 static void mtk_dsi_set_vm_cmd(struct mtk_dsi *dsi)
 {
-	mtk_dsi_mask(dsi, dsi->driver_data->reg_vm_cmd_off, VM_CMD_EN, VM_CMD_EN);
-	mtk_dsi_mask(dsi, dsi->driver_data->reg_vm_cmd_off, TS_VFP_EN, TS_VFP_EN);
+	const u16 *reg_adv = dsi->driver_data->reg_adv;
+
+	mtk_dsi_mask(dsi, reg_adv[DSI_VM_CMD_CON], VM_CMD_EN, VM_CMD_EN);
+	mtk_dsi_mask(dsi, reg_adv[DSI_VM_CMD_CON], TS_VFP_EN, TS_VFP_EN);
 }
 
 static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi)
 {
+	const u16 *reg_main = dsi->driver_data->reg_main;
 	u32 regval, tmp_reg = 0;
 	u8 i;
 
@@ -395,11 +518,13 @@ static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi)
 	if (dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET)
 		regval |= DIS_EOT;
 
-	writel(regval, dsi->regs + DSI_TXRX_CTRL);
+	writel(regval, dsi->regs + reg_main[DSI_TXRX_CTRL]);
 }
 
 static void mtk_dsi_ps_control(struct mtk_dsi *dsi, bool config_vact)
 {
+	const struct mtk_dsi_driver_data *data = dsi->driver_data;
+	const u16 *reg_main = dsi->driver_data->reg_main;
 	u32 dsi_buf_bpp, ps_val, ps_wc, size_val, vact_nl;
 
 	if (dsi->format == MIPI_DSI_FMT_RGB565)
@@ -437,12 +562,12 @@ static void mtk_dsi_ps_control(struct mtk_dsi *dsi, bool config_vact)
 
 	if (config_vact) {
 		vact_nl = FIELD_PREP(VACT_NL, dsi->vm.vactive);
-		writel(vact_nl, dsi->regs + DSI_VACT_NL);
-		writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC);
+		writel(vact_nl, dsi->regs + reg_main[DSI_VACT_NL]);
+		writel(ps_wc, dsi->regs + reg_main[DSI_HSTX_CKL_WC]);
 	}
-	writel(ps_val, dsi->regs + DSI_PSCTRL);
+	writel(ps_val, dsi->regs + reg_main[DSI_PSCTRL]);
 
-	if (dsi->driver_data->has_size_ctl) {
+	if (data->has_size_ctl) {
 		size_val = FIELD_PREP(DSI_HEIGHT, dsi->vm.vactive);
 		if (dsi->dsc)
 			size_val |= FIELD_PREP(DSI_WIDTH,
@@ -451,12 +576,13 @@ static void mtk_dsi_ps_control(struct mtk_dsi *dsi, bool config_vact)
 		else
 			size_val |= FIELD_PREP(DSI_WIDTH, dsi->vm.hactive);
 
-		writel(size_val, dsi->regs + DSI_SIZE_CON);
+		writel(size_val, dsi->regs + reg_main[DSI_SIZE_CON]);
 	}
 }
 
 static void mtk_dsi_config_vdo_timing_per_frame_lp(struct mtk_dsi *dsi)
 {
+	const u16 *reg_main = dsi->driver_data->reg_main;
 	u32 horizontal_sync_active_byte;
 	u32 horizontal_backporch_byte;
 	u32 horizontal_frontporch_byte;
@@ -511,20 +637,21 @@ static void mtk_dsi_config_vdo_timing_per_frame_lp(struct mtk_dsi *dsi)
 			   ps_wc), dsi->lanes) + da_hs_trail + 1) * dsi->lanes / 6 - 1;
 
 	hstx_cklp_wc = FIELD_PREP(HSTX_CKL_WC, (hstx_cklp_wc_min + hstx_cklp_wc_max) / 2);
-	writel(hstx_cklp_wc, dsi->regs + DSI_HSTX_CKL_WC);
+	writel(hstx_cklp_wc, dsi->regs + reg_main[DSI_HSTX_CKL_WC]);
 
 	hs_vb_ps_wc = ps_wc - (dsi->phy_timing.lpx + dsi->phy_timing.da_hs_exit +
 		      dsi->phy_timing.da_hs_prepare + dsi->phy_timing.da_hs_zero + 2) * dsi->lanes;
 	horizontal_frontporch_byte |= FIELD_PREP(HFP_HS_EN, 1) |
 				      FIELD_PREP(HFP_HS_VB_PS_WC, hs_vb_ps_wc);
 
-	writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC);
-	writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC);
-	writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC);
+	writel(horizontal_sync_active_byte, dsi->regs + reg_main[DSI_HSA_WC]);
+	writel(horizontal_backporch_byte, dsi->regs + reg_main[DSI_HBP_WC]);
+	writel(horizontal_frontporch_byte, dsi->regs + reg_main[DSI_HFP_WC]);
 }
 
 static void mtk_dsi_config_vdo_timing_per_line_lp(struct mtk_dsi *dsi)
 {
+	const u16 *reg_main = dsi->driver_data->reg_main;
 	u32 horizontal_sync_active_byte;
 	u32 horizontal_backporch_byte;
 	u32 horizontal_frontporch_byte;
@@ -582,9 +709,9 @@ static void mtk_dsi_config_vdo_timing_per_line_lp(struct mtk_dsi *dsi)
 			(vm->hactive * dsi_tmp_buf_bpp + 2) % dsi->lanes;
 	}
 
-	writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC);
-	writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC);
-	writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC);
+	writel(horizontal_sync_active_byte, dsi->regs + reg_main[DSI_HSA_WC]);
+	writel(horizontal_backporch_byte, dsi->regs + reg_main[DSI_HBP_WC]);
+	writel(horizontal_frontporch_byte, dsi->regs + reg_main[DSI_HFP_WC]);
 }
 
 static int mtk_dsi_set_dsc_params(struct mtk_dsi *dsi)
@@ -625,14 +752,16 @@ static int mtk_dsi_set_dsc_params(struct mtk_dsi *dsi)
 
 static int mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
 {
+	const struct mtk_dsi_driver_data *data = dsi->driver_data;
+	const u16 *reg_main = data->reg_main;
 	struct videomode *vm = &dsi->vm;
 
-	writel(vm->vsync_len, dsi->regs + DSI_VSA_NL);
-	writel(vm->vback_porch, dsi->regs + DSI_VBP_NL);
-	writel(vm->vfront_porch, dsi->regs + DSI_VFP_NL);
-	writel(vm->vactive, dsi->regs + DSI_VACT_NL);
+	writel(vm->vsync_len, dsi->regs + reg_main[DSI_VSA_NL]);
+	writel(vm->vback_porch, dsi->regs + reg_main[DSI_VBP_NL]);
+	writel(vm->vfront_porch, dsi->regs + reg_main[DSI_VFP_NL]);
+	writel(vm->vactive, dsi->regs + reg_main[DSI_VACT_NL]);
 
-	if (dsi->driver_data->support_per_frame_lp)
+	if (data->support_per_frame_lp)
 		mtk_dsi_config_vdo_timing_per_frame_lp(dsi);
 	else
 		mtk_dsi_config_vdo_timing_per_line_lp(dsi);
@@ -647,25 +776,25 @@ static int mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
 
 static void mtk_dsi_start(struct mtk_dsi *dsi)
 {
-	writel(0, dsi->regs + DSI_START);
-	writel(1, dsi->regs + DSI_START);
+	writel(0, dsi->regs + dsi->driver_data->reg_main[DSI_START]);
+	writel(1, dsi->regs + dsi->driver_data->reg_main[DSI_START]);
 }
 
 static void mtk_dsi_stop(struct mtk_dsi *dsi)
 {
-	writel(0, dsi->regs + DSI_START);
+	writel(0, dsi->regs + dsi->driver_data->reg_main[DSI_START]);
 }
 
 static void mtk_dsi_set_cmd_mode(struct mtk_dsi *dsi)
 {
-	writel(CMD_MODE, dsi->regs + DSI_MODE_CTRL);
+	writel(CMD_MODE, dsi->regs + dsi->driver_data->reg_main[DSI_MODE_CTRL]);
 }
 
 static void mtk_dsi_set_interrupt_enable(struct mtk_dsi *dsi)
 {
 	u32 inten = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG;
 
-	writel(inten, dsi->regs + DSI_INTEN);
+	writel(inten, dsi->regs + dsi->driver_data->reg_main[DSI_INTEN]);
 }
 
 static void mtk_dsi_irq_data_set(struct mtk_dsi *dsi, u32 irq_bit)
@@ -699,19 +828,20 @@ static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
 
 static irqreturn_t mtk_dsi_irq(int irq, void *dev_id)
 {
-	struct mtk_dsi *dsi = dev_id;
 	u32 status, tmp;
-	u32 flag = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG;
+	struct mtk_dsi *dsi = dev_id;
+	const u16 *reg_main = dsi->driver_data->reg_main;
+	const u32 flag = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG;
 
-	status = readl(dsi->regs + DSI_INTSTA) & flag;
+	status = readl(dsi->regs + dsi->driver_data->reg_main[DSI_INTSTA]) & flag;
 
 	if (status) {
 		do {
-			mtk_dsi_mask(dsi, DSI_RACK, RACK, RACK);
-			tmp = readl(dsi->regs + DSI_INTSTA);
+			mtk_dsi_mask(dsi, reg_main[DSI_RACK], RACK, RACK);
+			tmp = readl(dsi->regs + reg_main[DSI_INTSTA]);
 		} while (tmp & DSI_BUSY);
 
-		mtk_dsi_mask(dsi, DSI_INTSTA, status, 0);
+		mtk_dsi_mask(dsi, reg_main[DSI_INTSTA], status, 0);
 		mtk_dsi_irq_data_set(dsi, status);
 		wake_up_interruptible(&dsi->irq_wait_queue);
 	}
@@ -749,9 +879,10 @@ static void mtk_dsi_lane_ready(struct mtk_dsi *dsi)
 
 static int mtk_dsi_poweron(struct mtk_dsi *dsi)
 {
+	const struct mtk_dsi_driver_data *data = dsi->driver_data;
 	struct device *dev = dsi->host.dev;
-	int ret;
 	u32 bit_per_pixel;
+	int ret;
 
 	if (++dsi->refcount != 1)
 		return 0;
@@ -788,9 +919,10 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
 
 	mtk_dsi_enable(dsi);
 
-	if (dsi->driver_data->has_shadow_ctl)
+	/* Bypass shadow and force commit only if the register is present */
+	if (data->reg_adv[DSI_SHADOW_DEBUG])
 		writel(FORCE_COMMIT | BYPASS_SHADOW,
-		       dsi->regs + dsi->driver_data->reg_shadow_dbg_off);
+		       dsi->regs + data->reg_adv[DSI_SHADOW_DEBUG]);
 
 	mtk_dsi_reset_engine(dsi);
 	mtk_dsi_phy_timconfig(dsi);
@@ -839,7 +971,7 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
 	mtk_dsi_lane0_ulp_mode_enter(dsi);
 	mtk_dsi_clk_ulp_mode_enter(dsi);
 	/* set the lane number as 0 to pull down mipi */
-	writel(0, dsi->regs + DSI_TXRX_CTRL);
+	writel(0, dsi->regs + dsi->driver_data->reg_main[DSI_TXRX_CTRL]);
 
 	mtk_dsi_disable(dsi);
 
@@ -1122,11 +1254,12 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
 
 static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
 {
+	const struct mtk_dsi_driver_data *data = dsi->driver_data;
 	int ret;
 	u32 val;
 
-	ret = readl_poll_timeout(dsi->regs + DSI_INTSTA, val, !(val & DSI_BUSY),
-				 4, 2000000);
+	ret = readl_poll_timeout(dsi->regs + data->reg_main[DSI_INTSTA],
+				 val, !(val & DSI_BUSY), 4, 2000000);
 	if (ret) {
 		DRM_WARN("polling dsi wait not busy timeout!\n");
 
@@ -1160,10 +1293,12 @@ static u32 mtk_dsi_recv_cnt(u8 type, u8 *read_data)
 
 static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg)
 {
+	const struct mtk_dsi_driver_data *data = dsi->driver_data;
 	const char *tx_buf = msg->tx_buf;
-	u8 config, cmdq_size, cmdq_off, type = msg->type;
+	const u8 type = msg->type;
 	u32 reg_val, cmdq_mask, i;
-	u32 reg_cmdq_off = dsi->driver_data->reg_cmdq_off;
+	u8 cmdq_size, cmdq_off;
+	u8 config;
 
 	if (MTK_DSI_HOST_IS_READ(type))
 		config = BTA;
@@ -1186,15 +1321,15 @@ static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg)
 	}
 
 	for (i = 0; i < msg->tx_len; i++)
-		mtk_dsi_mask(dsi, (reg_cmdq_off + cmdq_off + i) & (~0x3U),
+		mtk_dsi_mask(dsi, (data->reg_adv[DSI_CMDQ] + cmdq_off + i) & (~0x3U),
 			     (0xffUL << (((i + cmdq_off) & 3U) * 8U)),
 			     tx_buf[i] << (((i + cmdq_off) & 3U) * 8U));
 
-	mtk_dsi_mask(dsi, reg_cmdq_off, cmdq_mask, reg_val);
-	mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, cmdq_size);
-	if (dsi->driver_data->cmdq_long_packet_ctl) {
+	mtk_dsi_mask(dsi, data->reg_adv[DSI_CMDQ], cmdq_mask, reg_val);
+	mtk_dsi_mask(dsi, data->reg_main[DSI_CMDQ_SIZE], CMDQ_SIZE, cmdq_size);
+	if (data->cmdq_long_packet_ctl) {
 		/* Disable setting cmdq_size automatically for long packets */
-		mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE_SEL, CMDQ_SIZE_SEL);
+		mtk_dsi_mask(dsi, data->reg_main[DSI_CMDQ_SIZE], CMDQ_SIZE_SEL, CMDQ_SIZE_SEL);
 	}
 }
 
@@ -1223,7 +1358,7 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
 	u32 dsi_mode;
 	int ret, i;
 
-	dsi_mode = readl(dsi->regs + DSI_MODE_CTRL);
+	dsi_mode = readl(dsi->regs + dsi->driver_data->reg_main[DSI_MODE_CTRL]);
 	if (dsi_mode & MODE) {
 		mtk_dsi_stop(dsi);
 		ret = mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500);
@@ -1252,7 +1387,8 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
 	}
 
 	for (i = 0; i < 16; i++)
-		*(read_data + i) = readb(dsi->regs + DSI_RX_DATA0 + i);
+		*(read_data + i) = readb(dsi->regs +
+					 dsi->driver_data->reg_main[DSI_RX_DATA0 + i]);
 
 	recv_cnt = mtk_dsi_recv_cnt(read_data[0], read_data);
 
@@ -1361,38 +1497,30 @@ static void mtk_dsi_remove(struct platform_device *pdev)
 }
 
 static const struct mtk_dsi_driver_data mt8173_dsi_driver_data = {
-	.reg_cmdq_off = 0x200,
-	.reg_vm_cmd_off = 0x130,
-	.reg_shadow_dbg_off = 0x190
+	.reg_main = mtk_dsi_regs_main_v1,
+	.reg_adv = mtk_dsi_regs_mt8173,
 };
 
 static const struct mtk_dsi_driver_data mt2701_dsi_driver_data = {
-	.reg_cmdq_off = 0x180,
-	.reg_vm_cmd_off = 0x130,
-	.reg_shadow_dbg_off = 0x190
+	.reg_main = mtk_dsi_regs_main_v1,
+	.reg_adv = mtk_dsi_regs_mt2701,
 };
 
 static const struct mtk_dsi_driver_data mt8183_dsi_driver_data = {
-	.reg_cmdq_off = 0x200,
-	.reg_vm_cmd_off = 0x130,
-	.reg_shadow_dbg_off = 0x190,
-	.has_shadow_ctl = true,
+	.reg_main = mtk_dsi_regs_main_v1,
+	.reg_adv = mtk_dsi_regs_mt8183,
 	.has_size_ctl = true,
 };
 
 static const struct mtk_dsi_driver_data mt8186_dsi_driver_data = {
-	.reg_cmdq_off = 0xd00,
-	.reg_vm_cmd_off = 0x200,
-	.reg_shadow_dbg_off = 0xc00,
-	.has_shadow_ctl = true,
+	.reg_main = mtk_dsi_regs_main_v1,
+	.reg_adv = mtk_dsi_regs_mt8186,
 	.has_size_ctl = true,
 };
 
 static const struct mtk_dsi_driver_data mt8188_dsi_driver_data = {
-	.reg_cmdq_off = 0xd00,
-	.reg_vm_cmd_off = 0x200,
-	.reg_shadow_dbg_off = 0xc00,
-	.has_shadow_ctl = true,
+	.reg_main = mtk_dsi_regs_main_v1,
+	.reg_adv = mtk_dsi_regs_mt8186,
 	.has_size_ctl = true,
 	.cmdq_long_packet_ctl = true,
 	.support_per_frame_lp = true,
-- 
2.54.0



^ permalink raw reply related

* Re: [PATCH 2/3] can: rockchip: add RK3588 CAN-FD support
From: Heiko Stübner @ 2026-07-01 16:02 UTC (permalink / raw)
  To: Marc Kleine-Budde, 💫.220
  Cc: linux-can, mailhol, kernel, robh, krzk+dt, conor+dt, devicetree,
	linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <tencent_AF88C27E354DFF34B132BC0906236A01A408@qq.com>

Am Mittwoch, 1. Juli 2026, 14:29:22 Mitteleuropäische Sommerzeit schrieb 💫.220:
> Hi Heiko, Marc,
> 
> thanks for the review.
> 
> > please use a real name, not an alias.
> 
> I will use my real name in future revisions.
> 
> > Funnily enough, we seem to have worked on the same topic
> > at the same time :-)
> >
> > https://lore.kernel.org/lkml/20260630164336.3444550-1-heiko@sntech.de/
> 
> I missed Heiko's series before sending mine, sorry for the noise.
> (But it really is a very interesting coincidence.)
> Since the series overlap, I am happy to base further work on Heiko's
> series, or to let Heiko fold the RK3588 RX_FIFO_CNT bitfield change into
> his v2 if that is preferred.

I don't think we need two people working on this and you did the better
investigation into the differences, so you should get the credit :-)

So I guess my preference would be to:
- pick up the erratum 6 into your patch
- add my haikou patch to the series - that way we also get a user
- handle Krzysztof's comment from
  https://lore.kernel.org/linux-rockchip/20260701-sensible-cryptic-ocelot-58035b@quoll/

  as both our bindings have the same structure, so I guess it should be

    oneOf:
       - enum:
             rockchip,rk3568v2-canfd
             rockchip,rk3588v2-canfd
       - items:
           - const: rockchip,rk3568v3-canfd
           - const: rockchip,rk3568v2-canfd

And submit that as v2.


> For RX_FIFO_CNT, I found the bitfield difference by reading Rockchip's
> vendor kernel 6.1 driver and comparing the CAN support for RK3568 and
> RK3588. The vendor driver uses different RX FIFO count bitfields for the
> two SoCs, and my testing on RK3588v2 also indicates that bits 7:5 are
> needed. I can add a short note about this in the commit message or
> code comment.

It's already in the commit message, so that should be fine


> One more question about RKCANFD_QUIRK_CANFD_BROKEN: in my RK3588v2 test
> setup the two known CAN-FD trigger frames did not cause an Error
> Interrupt or Error-Warning. I also ran a 12 hour CAN-FD stress test with
> can0/can1 directly connected, 200 MHz CAN clock, 500 kbit/s nominal
> bitrate and 1 Mbit/s data bitrate. That test included periodic
> transmission of the two CANFD_BROKEN frames, variable DLC CAN-FD frames,
> CAN-FD+BRS+EFF load, and a canfdtest run with 19,417,129 frames without
> data mismatch.
> 
> Would it make sense to leave RKCANFD_QUIRK_CANFD_BROKEN disabled for
> RK3588v2, or have you seen this issue on RK3588 as well?

I was more going by the fact that even Rockchip removed every mention of
the -FD from all documentation, so was assuming it still being broken as
before. But if it actually works, then personally I'm more than fine with
enabling CAN-FD :-D .

I guess Marc might have more insight where the FD issue triggered on
the RK3568.


Heiko




^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox