[PATCH v2 6/9] clk: renesas: rzg2l: Add support for RZ/G3L DSI mux
From: Biju
Date: Tue Aug 11 2026 - 14:33:04 EST
From: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
Add support for RZ/G3L DSI mux that supports 2 duty cycles.
Signed-off-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
---
v1->v2:
* Dropped rzg3l_cpg_dsi_smux_get_duty_cycle().
* Updated Mux flags with CLK_DUTY_CYCLE_PARENT and
CLK_SET_RATE_NO_REPARENT
* Determine rate now forward to clk_mux_ops.determine_rate().
* Dropped the duty cycle macros.
* Dropped struct rzg3l_dsi_mux_clk and to_plldsi_clk_mux.
---
drivers/clk/renesas/rzg2l-cpg.c | 84 +++++++++++++++++++++++++++++++++
drivers/clk/renesas/rzg2l-cpg.h | 10 ++++
2 files changed, 94 insertions(+)
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index d3d4e618466c..33cfea1b798a 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -1493,6 +1493,87 @@ static const struct clk_ops rzg3l_cpg_pll_ops = {
.recalc_rate = rzg3s_cpg_pll_clk_recalc_rate,
};
+static u8 rzg3l_cpg_dsi_smux_get_parent(struct clk_hw *hw)
+{
+ return clk_mux_ops.get_parent(hw);
+}
+
+static int rzg3l_cpg_dsi_smux_set_parent(struct clk_hw *hw, u8 index)
+{
+ return clk_mux_ops.set_parent(hw, index);
+}
+
+static int rzg3l_cpg_dsi_smux_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return clk_mux_ops.determine_rate(hw, req);
+}
+
+static int rzg3l_cpg_dsi_smux_set_duty_cycle(struct clk_hw *hw,
+ struct clk_duty *duty)
+{
+ struct clk_hw *parent_hw;
+ u8 parent_idx;
+
+ /*
+ * Select parent based on requested duty cycle:
+ * - If duty > 50% (num/den > 1/2), select LVDS path (parent 0)
+ * - Otherwise, select DSI/RGB path (parent 1)
+ */
+ if (duty->num * 2 > duty->den)
+ parent_idx = 0;
+ else
+ parent_idx = 1;
+
+ if (parent_idx >= clk_hw_get_num_parents(hw))
+ return -EINVAL;
+
+ parent_hw = clk_hw_get_parent_by_index(hw, parent_idx);
+ if (!parent_hw)
+ return -EINVAL;
+
+ return clk_hw_set_parent(hw, parent_hw);
+}
+
+static const struct clk_ops rzg3l_cpg_dsi_smux_ops = {
+ .determine_rate = rzg3l_cpg_dsi_smux_determine_rate,
+ .get_parent = rzg3l_cpg_dsi_smux_get_parent,
+ .set_parent = rzg3l_cpg_dsi_smux_set_parent,
+ .set_duty_cycle = rzg3l_cpg_dsi_smux_set_duty_cycle,
+};
+
+static struct clk * __init
+rzg3l_cpg_dsi_mux_clk_register(const struct cpg_core_clk *core,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct clk_mux *mux_data;
+ struct clk_init_data init;
+ int ret;
+
+ mux_data = devm_kzalloc(priv->dev, sizeof(*mux_data), GFP_KERNEL);
+ if (!mux_data)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = core->name;
+ init.ops = &rzg3l_cpg_dsi_smux_ops;
+ init.flags = core->core_flags | CLK_SET_RATE_PARENT;
+ init.parent_names = core->parent_names;
+ init.num_parents = core->num_parents;
+
+ mux_data->reg = priv->base + GET_REG_OFFSET(core->conf);
+ mux_data->shift = GET_SHIFT(core->conf);
+ mux_data->mask = clk_div_mask(GET_WIDTH(core->conf));
+ mux_data->flags = core->mux_flags;
+ mux_data->lock = &priv->rmw_lock;
+ mux_data->hw.init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, &mux_data->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return mux_data->hw.clk;
+}
+
static inline bool
rzg3l_dsi_compute_pll_parameters(struct rzg3l_plldsi_parameters *pars,
struct rzg3l_plldsi_parameters *p,
@@ -1805,6 +1886,9 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
case CLK_TYPE_G3L_PLLDSI:
clk = rzg2l_cpg_pll_clk_register(core, priv, &rzg3l_cpg_plldsi_ops);
break;
+ case CLK_TYPE_G3L_DSI_MUX:
+ clk = rzg3l_cpg_dsi_mux_clk_register(core, priv);
+ break;
default:
goto fail;
}
diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
index 22cca4795301..1591fce2a329 100644
--- a/drivers/clk/renesas/rzg2l-cpg.h
+++ b/drivers/clk/renesas/rzg2l-cpg.h
@@ -151,6 +151,9 @@ enum clk_types {
/* Clock for G3L LVDS divider */
CLK_TYPE_G3L_LVDS_DIV,
+
+ /* Clock for G3L DSI clock source selector */
+ CLK_TYPE_G3L_DSI_MUX,
};
#define DEF_TYPE(_name, _id, _type...) \
@@ -204,6 +207,13 @@ enum clk_types {
.parent_names = _parent_names, \
.num_parents = ARRAY_SIZE(_parent_names), \
.mux_flags = CLK_MUX_READ_ONLY)
+#define DEF_G3L_SEL_DSI_MUX(_name, _id, _conf, _parent_names) \
+ DEF_TYPE(_name, _id, CLK_TYPE_G3L_DSI_MUX, .conf = _conf, \
+ .parent_names = _parent_names, \
+ .num_parents = ARRAY_SIZE(_parent_names), \
+ .core_flags = CLK_SET_RATE_PARENT | CLK_DUTY_CYCLE_PARENT | \
+ CLK_SET_RATE_NO_REPARENT, \
+ .mux_flags = CLK_MUX_HIWORD_MASK)
#define DEF_SD_MUX(_name, _id, _conf, _sconf, _parent_names, _mtable, _clk_flags, _notifier) \
DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, .sconf = _sconf, \
.parent_names = _parent_names, \
--
2.43.0