Commit 6cc859ca authored by Biju Das's avatar Biju Das Committed by Geert Uytterhoeven
Browse files

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: default avatarBiju 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: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
parent 1561380e
Loading
Loading
Loading
Loading
+93 −0
Original line number Diff line number Diff line
@@ -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;
	}
+10 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#define CPG_PL3_SSEL		(0x408)
#define CPG_PL6_SSEL		(0x414)
#define CPG_PL6_ETH_SSEL	(0x418)
#define CPG_OTHERFUNC1_REG	(0xBE8)

#define CPG_SIPLL5_STBY_RESETB		BIT(0)
#define CPG_SIPLL5_STBY_RESETB_WEN	BIT(16)
@@ -35,6 +36,8 @@
#define CPG_SIPLL5_CLK4_RESV_LSB	(0xFF)
#define CPG_SIPLL5_MON_PLL5_LOCK	BIT(4)

#define CPG_OTHERFUNC1_REG_RES0_ON_WEN	BIT(16)

#define CPG_CLKSTATUS_SELSDHI0_STS	BIT(28)
#define CPG_CLKSTATUS_SELSDHI1_STS	BIT(29)

@@ -59,6 +62,7 @@
		(((offset) << 20) | ((bitpos) << 12) | ((size) << 8))

#define SEL_PLL3_3	SEL_PLL_PACK(CPG_PL3_SSEL, 8, 1)
#define SEL_PLL5_4	SEL_PLL_PACK(CPG_OTHERFUNC1_REG, 0, 1)
#define SEL_PLL6_2	SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1)
#define SEL_GPU2	SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1)

@@ -107,6 +111,9 @@ enum clk_types {

	/* Clock for SIPLL5 */
	CLK_TYPE_SIPLL5,

	/* Clock for PLL5_4 clock source selector */
	CLK_TYPE_PLL5_4_MUX,
};

#define DEF_TYPE(_name, _id, _type...) \
@@ -132,6 +139,9 @@ enum clk_types {
		 .parent_names = _parent_names, .num_parents = _num_parents)
#define DEF_PLL5_FOUTPOSTDIV(_name, _id, _parent) \
	DEF_TYPE(_name, _id, CLK_TYPE_SIPLL5, .parent = _parent)
#define DEF_PLL5_4_MUX(_name, _id, _conf, _parent_names, _num_parents) \
	DEF_TYPE(_name, _id, CLK_TYPE_PLL5_4_MUX, .conf = _conf, \
		 .parent_names = _parent_names, .num_parents = _num_parents)

/**
 * struct rzg2l_mod_clk - Module Clocks definitions