Re: [PATCH 6.1.y-cip 13/85] clk: renesas: rzv2h: Add MSTOP support

Pavel Machek
2025-03-20T09:03:07Z

[-- Attachment #1: Type: text/plain, Size: 3883 bytes --]

Hi!

> From: Biju Das <biju.das.jz@bp.renesas.com>
>
> commit 9b6e63a777ea5fb85bf24f9cb5ba902eed4f1f2f upstream.
>
> Add MSTOP support to control buses for the individual units on RZ/V2H.
> Use per-bit (instead of group-based) configuration and atomic counters,
> to ensure precise control over individual MSTOP bits, and to prevent
> issues with shared dependencies between module clocks.
>
> Co-developed-by: Biju Das <biju.das.jz@bp.renesas.com>

> +++ b/drivers/clk/renesas/r9a09g057-cpg.c
> +static void rzv2h_mod_clock_mstop_enable(struct rzv2h_cpg_priv *priv,
> + u32 mstop_data)
> +{
> + unsigned long mstop_mask = FIELD_GET(BUS_MSTOP_BITS_MASK, mstop_data);
> + u16 mstop_index = FIELD_GET(BUS_MSTOP_IDX_MASK, mstop_data);
> + unsigned int index = (mstop_index - 1) * 16;
> + atomic_t *mstop = &priv->mstop_count[index];
> + unsigned long flags;
> + unsigned int i;
> + u32 val = 0;
> +
> + spin_lock_irqsave(&priv->rmw_lock, flags);
> + for_each_set_bit(i, &mstop_mask, 16) {
> + if (!atomic_read(&mstop[i]))
> + val |= BIT(i) << 16;
> + atomic_inc(&mstop[i]);
> + }
> + if (val)
> + writel(val, priv->base + CPG_BUS_MSTOP(mstop_index));
> + spin_unlock_irqrestore(&priv->rmw_lock, flags);
> +}
> +
> +static void rzv2h_mod_clock_mstop_disable(struct rzv2h_cpg_priv *priv,
> + u32 mstop_data)
> +{
> + unsigned long mstop_mask = FIELD_GET(BUS_MSTOP_BITS_MASK, mstop_data);
> + u16 mstop_index = FIELD_GET(BUS_MSTOP_IDX_MASK, mstop_data);
> + unsigned int index = (mstop_index - 1) * 16;
> + atomic_t *mstop = &priv->mstop_count[index];
> + unsigned long flags;
> + unsigned int i;
> + u32 val = 0;
> +
> + spin_lock_irqsave(&priv->rmw_lock, flags);
> + for_each_set_bit(i, &mstop_mask, 16) {
> + if (!atomic_read(&mstop[i]) ||
> + atomic_dec_and_test(&mstop[i]))
> + val |= BIT(i) << 16 | BIT(i);
> + }
> + if (val)
> + writel(val, priv->base + CPG_BUS_MSTOP(mstop_index));
> + spin_unlock_irqrestore(&priv->rmw_lock, flags);
> +}

> @@ -555,6 +619,41 @@ rzv2h_cpg_register_mod_clk(const struct rzv2h_mod_clk *mod,
>
> priv->clks[id] = clock->hw.clk;
>
> + /*
> + * Ensure the module clocks and MSTOP bits are synchronized when they are
> + * turned ON by the bootloader. Enable MSTOP bits for module clocks that were
> + * turned ON in an earlier boot stage.
> + */
> + if (clock->mstop_data != BUS_MSTOP_NONE &&
> + !mod->critical && rzv2h_mod_clock_is_enabled(&clock->hw)) {
> + rzv2h_mod_clock_mstop_enable(priv, clock->mstop_data);
> + } else if (clock->mstop_data != BUS_MSTOP_NONE && mod->critical) {
> + unsigned long mstop_mask = FIELD_GET(BUS_MSTOP_BITS_MASK, clock->mstop_data);
> + u16 mstop_index = FIELD_GET(BUS_MSTOP_IDX_MASK, clock->mstop_data);
> + unsigned int index = (mstop_index - 1) * 16;
> + atomic_t *mstop = &priv->mstop_count[index];
> + unsigned long flags;
> + unsigned int i;
> + u32 val = 0;
> +
> + /*
> + * Critical clocks are turned ON immediately upon registration, and the
> + * MSTOP counter is updated through the rzv2h_mod_clock_enable() path.
> + * However, if the critical clocks were already turned ON by the initial
> + * bootloader, synchronize the atomic counter here and clear the MSTOP bit.
> + */
> + spin_lock_irqsave(&priv->rmw_lock, flags);
> + for_each_set_bit(i, &mstop_mask, 16) {
> + if (atomic_read(&mstop[i]))
> + continue;
> + val |= BIT(i) << 16;
> + atomic_inc(&mstop[i]);
> + }
> + if (val)
> + writel(val, priv->base + CPG_BUS_MSTOP(mstop_index));
> + spin_unlock_irqrestore(&priv->rmw_lock, flags);

If these three could somehow be shared, it would be nice.

Best regards,
Pavel
--
DENX Software Engineering GmbH, Managing Director: Erika Unter
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]