summaryrefslogtreecommitdiffstats
path: root/drivers/clk/renesas/rzg2l-cpg.c
diff options
context:
space:
mode:
authorBiju Das <biju.das.jz@bp.renesas.com>2022-04-30 13:41:49 +0200
committerGeert Uytterhoeven <geert+renesas@glider.be>2022-05-05 12:10:21 +0200
commit6cc859cae9aa8c42e8347e2806232bdffeb1b33d (patch)
treecddfa732f740cf19681215f34424b31f32c5f058 /drivers/clk/renesas/rzg2l-cpg.c
parentclk: renesas: rzg2l: Add FOUTPOSTDIV clk support (diff)
downloadlinux-6cc859cae9aa8c42e8347e2806232bdffeb1b33d.tar.xz
linux-6cc859cae9aa8c42e8347e2806232bdffeb1b33d.zip
clk: renesas: rzg2l: Add PLL5_4 clk mux support
Add PLL5_4 clk mux support to select clock from clock sources FOUTPOSTDIV and FOUT1PH0. Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> Link: https://lore.kernel.org/r/20220430114156.6260-3-biju.das.jz@bp.renesas.com Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Diffstat (limited to 'drivers/clk/renesas/rzg2l-cpg.c')
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index d1ede40b5210..ec2ccfd316f9 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -304,6 +304,96 @@ rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params,
return foutpostdiv_rate;
}
+struct pll5_mux_hw_data {
+ struct clk_hw hw;
+ u32 conf;
+ unsigned long rate;
+ struct rzg2l_cpg_priv *priv;
+};
+
+#define to_pll5_mux_hw_data(_hw) container_of(_hw, struct pll5_mux_hw_data, hw)
+
+static int rzg2l_cpg_pll5_4_clk_mux_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_hw *parent;
+ struct pll5_mux_hw_data *hwdata = to_pll5_mux_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = hwdata->priv;
+
+ parent = clk_hw_get_parent_by_index(hw, priv->mux_dsi_div_params.clksrc);
+ req->best_parent_hw = parent;
+ req->best_parent_rate = req->rate;
+
+ return 0;
+}
+
+static int rzg2l_cpg_pll5_4_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct pll5_mux_hw_data *hwdata = to_pll5_mux_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = hwdata->priv;
+
+ /*
+ * FOUTPOSTDIV--->|
+ * | | -->MUX -->DIV_DSIA_B -->M3 -->VCLK
+ * |--FOUT1PH0-->|
+ *
+ * Based on the dot clock, the DSI divider clock calculates the parent
+ * rate and clk source for the MUX. It propagates that info to
+ * pll5_4_clk_mux which sets the clock source for DSI divider clock.
+ */
+
+ writel(CPG_OTHERFUNC1_REG_RES0_ON_WEN | index,
+ priv->base + CPG_OTHERFUNC1_REG);
+
+ return 0;
+}
+
+static u8 rzg2l_cpg_pll5_4_clk_mux_get_parent(struct clk_hw *hw)
+{
+ struct pll5_mux_hw_data *hwdata = to_pll5_mux_hw_data(hw);
+ struct rzg2l_cpg_priv *priv = hwdata->priv;
+
+ return readl(priv->base + GET_REG_OFFSET(hwdata->conf));
+}
+
+static const struct clk_ops rzg2l_cpg_pll5_4_clk_mux_ops = {
+ .determine_rate = rzg2l_cpg_pll5_4_clk_mux_determine_rate,
+ .set_parent = rzg2l_cpg_pll5_4_clk_mux_set_parent,
+ .get_parent = rzg2l_cpg_pll5_4_clk_mux_get_parent,
+};
+
+static struct clk * __init
+rzg2l_cpg_pll5_4_mux_clk_register(const struct cpg_core_clk *core,
+ struct rzg2l_cpg_priv *priv)
+{
+ struct pll5_mux_hw_data *clk_hw_data;
+ struct clk_init_data init;
+ struct clk_hw *clk_hw;
+ int ret;
+
+ clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
+ if (!clk_hw_data)
+ return ERR_PTR(-ENOMEM);
+
+ clk_hw_data->priv = priv;
+ clk_hw_data->conf = core->conf;
+
+ init.name = core->name;
+ init.ops = &rzg2l_cpg_pll5_4_clk_mux_ops;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.num_parents = core->num_parents;
+ init.parent_names = core->parent_names;
+
+ clk_hw = &clk_hw_data->hw;
+ clk_hw->init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, clk_hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return clk_hw->clk;
+}
+
struct sipll5 {
struct clk_hw hw;
u32 conf;
@@ -640,6 +730,9 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
case CLK_TYPE_SD_MUX:
clk = rzg2l_cpg_sd_mux_clk_register(core, priv->base, priv);
break;
+ case CLK_TYPE_PLL5_4_MUX:
+ clk = rzg2l_cpg_pll5_4_mux_clk_register(core, priv);
+ break;
default:
goto fail;
}