mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Paul Barker <paul.barker.ct@bp.renesas.com>
To: Thierry Bultel <thierry.bultel.yh@bp.renesas.com>,
	Geert Uytterhoeven <geert+renesas@glider.be>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@kernel.org>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	Magnus Damm <magnus.damm@gmail.com>
Cc: linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org
Subject: Re: [PATCH 06/14] clk: renesas: Add support for RZ/T2H family clock
Date: Tue, 4 Feb 2025 16:14:29 +0000	[thread overview]
Message-ID: <f52b6bda-1606-44da-bc5e-6fcfdfbaa3ae@bp.renesas.com> (raw)
In-Reply-To: <20250129165122.2980-7-thierry.bultel.yh@bp.renesas.com>


[-- Attachment #1.1.1: Type: text/plain, Size: 11989 bytes --]

Hi Thierry,

On 29/01/2025 16:37, Thierry Bultel wrote:
> Add the CPG driver for T2H family.
> 
> Signed-off-by: Thierry Bultel <thierry.bultel.yh@bp.renesas.com>
> ---
>  drivers/clk/renesas/Kconfig     |   4 +
>  drivers/clk/renesas/Makefile    |   1 +
>  drivers/clk/renesas/rzt2h-cpg.c | 549 ++++++++++++++++++++++++++++++++
>  drivers/clk/renesas/rzt2h-cpg.h | 201 ++++++++++++
>  4 files changed, 755 insertions(+)
>  create mode 100644 drivers/clk/renesas/rzt2h-cpg.c
>  create mode 100644 drivers/clk/renesas/rzt2h-cpg.h

[snip]

> diff --git a/drivers/clk/renesas/rzt2h-cpg.c b/drivers/clk/renesas/rzt2h-cpg.c
> new file mode 100644
> index 000000000000..79dacbd2b186
> --- /dev/null
> +++ b/drivers/clk/renesas/rzt2h-cpg.c

[snip]

> +struct pll_clk {
> +	void __iomem *base;
> +	struct rzt2h_cpg_priv *priv;
> +	struct clk_hw hw;
> +	unsigned int conf;
> +	unsigned int type;
> +};
> +#define to_pll(_hw)	container_of(_hw, struct pll_clk, hw)

Please add a blank line between these definitions.

> +
> +static struct clk
> +*rzt2h_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec,

The '*' is part of the type so should be on the previous line. i.e.

    static struct clk *
    rzt2h_cpg_clk_src_twocell_get(...)

> +			       void *data)
> +{
> +	unsigned int clkidx = clkspec->args[1];
> +	struct rzt2h_cpg_priv *priv = data;
> +	struct device *dev = priv->dev;
> +	const char *type;
> +	struct clk *clk;
> +
> +	switch (clkspec->args[0]) {
> +	case CPG_CORE:
> +		type = "core";
> +		if (clkidx > priv->last_dt_core_clk) {
> +			dev_err(dev, "Invalid %s clock index %u\n", type, clkidx);
> +			return ERR_PTR(-EINVAL);
> +		}
> +		clk = priv->clks[clkidx];
> +		break;
> +
> +	case CPG_MOD:
> +		type = "module";
> +		if (clkidx >= priv->num_mod_clks) {
> +			dev_err(dev, "Invalid %s clock index %u\n", type,
> +				clkidx);
> +			return ERR_PTR(-EINVAL);
> +		}
> +		clk = priv->clks[priv->num_core_clks + clkidx];
> +		break;
> +
> +	default:
> +		dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	if (IS_ERR(clk))
> +		dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx,
> +			PTR_ERR(clk));
> +	else
> +		dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n",
> +			clkspec->args[0], clkspec->args[1], clk,
> +			clk_get_rate(clk));
> +	return clk;
> +}
> +
> +static void __init
> +rzt2h_cpg_register_core_clk(const struct cpg_core_clk *core,
> +			    const struct rzt2h_cpg_info *info,
> +			    struct rzt2h_cpg_priv *priv)
> +{
> +	struct clk *clk = ERR_PTR(-EOPNOTSUPP), *parent;
> +	unsigned int id = core->id, div = core->div;
> +	struct device *dev = priv->dev;
> +	const char *parent_name;
> +
> +	WARN_DEBUG(id >= priv->num_core_clks);
> +	WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
> +
> +	/* Skip NULLified clock */
> +	if (!core->name)
> +		return;
> +
> +	switch (core->type) {
> +	case CLK_TYPE_IN:
> +		clk = of_clk_get_by_name(priv->dev->of_node, core->name);
> +		break;
> +	case CLK_TYPE_FF:
> +		WARN_DEBUG(core->parent >= priv->num_core_clks);
> +		parent = priv->clks[core->parent];
> +		if (IS_ERR(parent)) {
> +			clk = parent;
> +			goto fail;
> +		}
> +
> +		parent_name = __clk_get_name(parent);
> +		clk = clk_register_fixed_factor(NULL, core->name,
> +						parent_name, CLK_SET_RATE_PARENT,
> +						core->mult, div);
> +		break;
> +	case CLK_TYPE_DIV:
> +		if (core->sel_base > 0)
> +			clk = rzt2h_cpg_div_clk_register(core,
> +							 priv->cpg_base1, priv);
> +		else
> +			clk = rzt2h_cpg_div_clk_register(core,
> +							 priv->cpg_base0, priv);
> +		break;
> +	case CLK_TYPE_MUX:
> +		clk = rzt2h_cpg_mux_clk_register(core, priv->cpg_base0, priv);
> +		break;
> +	default:
> +		goto fail;

I would prefer `clk = ERR_PTR(-EOPNOTSUPP);` here instead of at the top
of the function so that it's easier to see at a glance what is
happening.

> +	}
> +
> +	if (IS_ERR_OR_NULL(clk))
> +		goto fail;
> +
> +	priv->clks[id] = clk;
> +	return;
> +
> +fail:
> +	dev_err(dev, "Failed to register %s clock %s: %ld\n", "core",
> +		core->name, PTR_ERR(clk));
> +}
> +
> +/**
> + * struct mstp_clock - MSTP gating clock
> + *
> + * @hw: handle between common and hardware-specific interfaces
> + * @priv: CPG/MSTP private data
> + * @sibling: pointer to the other coupled clock
> + * @baseaddr: register base address
> + * @enabled: soft state of the clock, if it is coupled with another clock
> + * @off: register offset
> + * @bit: ON/MON bit
> + */
> +struct mstp_clock {
> +	struct rzt2h_cpg_priv *priv;
> +	struct mstp_clock *sibling;
> +	void __iomem *baseaddr;
> +	struct clk_hw hw;
> +	bool enabled;
> +	u32 off;
> +	u8 bit;
> +};
> +#define to_mod_clock(_hw) container_of(_hw, struct mstp_clock, hw)
> +static int rzt2h_mod_clock_is_enabled(struct clk_hw *hw)

Please add blank lines between these three definitions.

> +{
> +	struct mstp_clock *clock = to_mod_clock(hw);
> +	struct rzt2h_cpg_priv *priv = clock->priv;
> +	u32 bitmask = BIT(clock->bit);
> +	u32 value;
> +
> +	if (!clock->off) {
> +		dev_dbg(priv->dev, "%pC does not support ON/OFF\n",  hw->clk);
> +		return 1;
> +	}
> +	value = readl(clock->baseaddr + clock->off);
> +
> +	/* For all Module Stop registers, read bit meaning is as such:
> +	 * 0: Release from the module-stop state
> +	 * 1: Transition to the module-stop state is made
> +	*/
> +
> +	return !(value & bitmask);
> +}
> +
> +static const struct clk_ops rzt2h_mod_clock_ops = {
> +	.is_enabled = rzt2h_mod_clock_is_enabled,
> +};
> +
> +static void __init
> +rzt2h_cpg_register_mod_clk(const struct rzt2h_mod_clk *mod,
> +			   const struct rzt2h_cpg_info *info,
> +			   struct rzt2h_cpg_priv *priv)
> +{
> +	struct mstp_clock *clock = NULL;
> +	struct device *dev = priv->dev;
> +	unsigned int id = mod->id;
> +	struct clk_init_data init;
> +	struct clk *parent, *clk;
> +	const char *parent_name;
> +	unsigned int i;
> +
> +	WARN_DEBUG(id < priv->num_core_clks);
> +	WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks);
> +	WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks);
> +	WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
> +
> +	/* Skip NULLified clock */
> +	if (!mod->name)
> +		return;
> +
> +	parent = priv->clks[mod->parent];
> +	if (IS_ERR(parent)) {
> +		clk = parent;
> +		goto fail;
> +	}
> +
> +	clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL);
> +	if (!clock) {
> +		clk = ERR_PTR(-ENOMEM);
> +		goto fail;
> +	}
> +
> +	init.name = mod->name;
> +	init.ops = &rzt2h_mod_clock_ops;
> +	init.flags = CLK_SET_RATE_PARENT;
> +	for (i = 0; i < info->num_crit_mod_clks; i++)
> +		if (id == info->crit_mod_clks[i]) {
> +			dev_dbg(dev, "CPG %s setting CLK_IS_CRITICAL\n",
> +				mod->name);
> +			init.flags |= CLK_IS_CRITICAL;
> +			break;
> +		}
> +
> +	parent_name = __clk_get_name(parent);
> +	init.parent_names = &parent_name;
> +	init.num_parents = 1;
> +
> +	clock->off = mod->addr;
> +	clock->bit = mod->bit;
> +	clock->baseaddr = mod->sel_base ? priv->cpg_base1 : priv->cpg_base0;
> +	clock->priv = priv;
> +	clock->hw.init = &init;

Both init and parent_name are local variables and can't be used after we
return from this function. So we mustn't store pointers to them into
objects that have a longer lifetime.

Could we add init and parent_name members to struct mstp_clock, then use
clock->init and clock->parent_name instead of the local variables?

> +
> +	clk = devm_clk_register(dev, &clock->hw);
> +	if (IS_ERR(clk))
> +		goto fail;
> +
> +	priv->clks[id] = clk;
> +
> +	return;
> +
> +fail:
> +	dev_err(dev, "Failed to register %s clock %s: %ld\n", "module",
> +		mod->name, PTR_ERR(clk));
> +}
> +
> +static bool rzt2h_cpg_is_pm_clk(const struct of_phandle_args *clkspec)
> +{
> +	if (clkspec->args_count != 2)
> +		return false;
> +
> +	switch (clkspec->args[0]) {
> +	case CPG_MOD:
> +		return true;
> +
> +	default:
> +		return false;
> +	}

Can we replace this switch statement with:

    return (clkspec->args[0] == CPG_MOD);

> +}
> +
> +static int rzt2h_cpg_attach_dev(struct generic_pm_domain *unused, struct device *dev)
> +{
> +	struct device_node *np = dev->of_node;
> +	struct of_phandle_args clkspec;
> +	unsigned int i = 0;
> +	bool once = true;
> +	struct clk *clk;
> +	int error;
> +
> +	while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
> +					   &clkspec)) {
> +		if (!rzt2h_cpg_is_pm_clk(&clkspec)) {
> +			of_node_put(clkspec.np);
> +			continue;
> +		}
> +
> +		if (once) {

Can we just use `if (!i)` here and drop the `once` variable?

> +			once = false;
> +			error = pm_clk_create(dev);
> +			if (error) {
> +				of_node_put(clkspec.np);
> +				goto err;
> +			}
> +		}
> +		clk = of_clk_get_from_provider(&clkspec);
> +		of_node_put(clkspec.np);
> +		if (IS_ERR(clk)) {
> +			error = PTR_ERR(clk);
> +			goto fail_destroy;
> +		}
> +		error = pm_clk_add_clk(dev, clk);
> +		if (error) {
> +			dev_err(dev, "pm_clk_add_clk failed %d\n", error);
> +			goto fail_put;
> +		}
> +		i++;
> +	}
> +
> +	return 0;
> +
> +fail_put:
> +	clk_put(clk);
> +
> +fail_destroy:
> +	pm_clk_destroy(dev);
> +err:
> +	return error;
> +}

[snip]

> +static const struct of_device_id rzt2h_cpg_match[] = {
> +#ifdef CONFIG_CLK_R9A09G077
> +	{
> +		.compatible = "renesas,r9a09g077-cpg",
> +		.data = &r9a09g077_cpg_info,
> +	},
> +#endif

CONFIG_CLK_R9A09G077 and r9a09g077_cpg_info are not defined until the
subsequent patch. We should move this entry to the next patch, and leave
this array empty here.

For comparison see how the RZ/V2H CPG driver was added in the following
commits:

    dd22e5621749 ("clk: renesas: Add family-specific clock driver for RZ/V2H(P)")
    36932cbc3e6c ("clk: renesas: Add RZ/V2H(P) CPG driver")

> +	{ /* sentinel */ }
> +};

[snip]

> diff --git a/drivers/clk/renesas/rzt2h-cpg.h b/drivers/clk/renesas/rzt2h-cpg.h
> new file mode 100644
> index 000000000000..d9d28608e4c3
> --- /dev/null
> +++ b/drivers/clk/renesas/rzt2h-cpg.h

[snip]

> +/**
> + * struct rzt2_cpg_info - SoC-specific CPG Description
> + *
> + * @core_clks: Array of Core Clock definitions
> + * @num_core_clks: Number of entries in core_clks[]
> + * @last_dt_core_clk: ID of the last Core Clock exported to DT
> + * @num_total_core_clks: Total number of Core Clocks (exported + internal)
> + *
> + * @mod_clks: Array of Module Clock definitions
> + * @num_mod_clks: Number of entries in mod_clks[]
> + * @num_hw_mod_clks: Number of Module Clocks supported by the hardware
> + *
> + * @resets: Array of Module Reset definitions
> + * @num_resets: Number of entries in resets[]
> + *
> + * @crit_mod_clks: Array with Module Clock IDs of critical clocks that
> + *                 should not be disabled without a knowledgeable driver
> + * @num_crit_mod_clks: Number of entries in crit_mod_clks[]
> + */
> +struct rzt2h_cpg_info {
> +	/* Core Clocks */
> +	const struct cpg_core_clk *core_clks;
> +	unsigned int num_core_clks;
> +	unsigned int last_dt_core_clk;
> +	unsigned int num_total_core_clks;
> +
> +	/* Module Clocks */
> +	const struct rzt2h_mod_clk *mod_clks;
> +	unsigned int num_mod_clks;
> +	unsigned int num_hw_mod_clks;
> +
> +	/* Resets */
> +	const struct rzt2h_reset *resets;
> +	unsigned int num_resets;
> +
> +	/* Critical Module Clocks that should not be disabled */
> +	const unsigned int *crit_mod_clks;
> +	unsigned int num_crit_mod_clks;

It looks like resets and crit_mod_clks are not populated in this initial
patch series. We can drop support for both of these from this patch
series.

> +};
> +
> +extern const struct rzt2h_cpg_info r9a09g077_cpg_info;
> +
> +#endif

-- 
Paul Barker

[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3577 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 236 bytes --]

  reply	other threads:[~2025-02-04 16:14 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20250129165122.2980-1-thierry.bultel.yh@bp.renesas.com>
2025-01-29 16:37 ` [PATCH 01/14] dt-bindings: soc: Document Renesas RZ/T2H (R9A09G077) SoC Thierry Bultel
2025-01-29 18:28   ` Krzysztof Kozlowski
2025-02-10 12:52   ` Geert Uytterhoeven
2025-01-29 16:37 ` [PATCH 02/14] dt-bindings: serial: Document sci bindings for the Renesas RZ/T2H (a.k.a r9a09g077) SoC Thierry Bultel
2025-01-29 18:31   ` Krzysztof Kozlowski
2025-01-30  8:09     ` Krzysztof Kozlowski
2025-01-30  8:11   ` Krzysztof Kozlowski
2025-02-10 13:14   ` Geert Uytterhoeven
2025-02-10 13:19     ` Biju Das
2025-02-10 14:15       ` Geert Uytterhoeven
2025-02-10 14:26         ` Biju Das
2025-02-10 14:35           ` Geert Uytterhoeven
2025-02-10 14:42             ` Biju Das
2025-02-10 14:46               ` Biju Das
2025-02-10 14:48                 ` Geert Uytterhoeven
2025-01-29 16:37 ` [PATCH 03/14] dt-bindings: soc: Document the Renesas RZ/T2H Evaluation board for the R9A09G077 SoC Thierry Bultel
2025-01-29 18:31   ` Krzysztof Kozlowski
2025-01-30  8:11   ` Krzysztof Kozlowski
2025-02-10 13:21   ` Geert Uytterhoeven
2025-01-29 16:37 ` [PATCH 04/14] dt-bindings: clock: Document cpg bindings for the Renesas RZ/T2H SoC Thierry Bultel
2025-01-29 18:34   ` Krzysztof Kozlowski
2025-02-10 13:39   ` Geert Uytterhoeven
2025-01-29 16:37 ` [PATCH 05/14] soc: renesas: Add RZ/T2H (R9A09G077) config option Thierry Bultel
2025-02-10 13:40   ` Geert Uytterhoeven
2025-01-29 16:37 ` [PATCH 06/14] clk: renesas: Add support for RZ/T2H family clock Thierry Bultel
2025-02-04 16:14   ` Paul Barker [this message]
2025-02-10 14:06   ` Geert Uytterhoeven
2025-01-29 16:37 ` [PATCH 07/14] clk: renesas: Add support for R9A09G077 SoC Thierry Bultel
2025-02-04 16:44   ` Paul Barker
2025-01-29 16:37 ` [PATCH 08/14] serial: sh-sci: Fix a comment about SCIFA Thierry Bultel
2025-01-30  8:38   ` Geert Uytterhoeven
2025-02-04 16:51   ` Paul Barker
2025-01-29 16:37 ` [PATCH 09/14] serial: sh-sci: Introduced function pointers Thierry Bultel
2025-01-30  8:38   ` Geert Uytterhoeven
2025-02-04 18:04   ` Paul Barker
2025-02-10 14:45   ` Geert Uytterhoeven
2025-02-10 15:36     ` Geert Uytterhoeven
2025-01-29 16:37 ` [PATCH 10/14] serial: sh-sci: Introduced sci_of_data Thierry Bultel
2025-01-30  8:39   ` Geert Uytterhoeven
2025-02-10 15:48   ` Geert Uytterhoeven
2025-01-29 16:37 ` [PATCH 11/14] serial: sh-sci: Add support for RZ/T2H SCI Thierry Bultel
2025-02-10 15:30   ` Geert Uytterhoeven
2025-01-29 16:37 ` [PATCH 12/14] arm64: dts: renesas: Add initial support for renesas RZ/T2H SoC Thierry Bultel
2025-01-29 18:36   ` Krzysztof Kozlowski
2025-02-10 15:52   ` Geert Uytterhoeven
2025-01-29 16:37 ` [PATCH 13/14] arm64: dts: renesas: Add initial support for renesas RZ/T2H eval board Thierry Bultel
2025-01-29 18:37   ` Krzysztof Kozlowski
2025-02-10 15:54   ` Geert Uytterhoeven
2025-01-29 16:37 ` [PATCH 14/14] defconfig: Enable RZ/T2H Soc and RZ_SCI Thierry Bultel
2025-01-29 18:40   ` Krzysztof Kozlowski
2025-01-30  8:40   ` Geert Uytterhoeven

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f52b6bda-1606-44da-bc5e-6fcfdfbaa3ae@bp.renesas.com \
    --to=paul.barker.ct@bp.renesas.com \
    --cc=geert+renesas@glider.be \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=magnus.damm@gmail.com \
    --cc=mturquette@baylibre.com \
    --cc=p.zabel@pengutronix.de \
    --cc=sboyd@kernel.org \
    --cc=thierry.bultel.yh@bp.renesas.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®