All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Gabriel Fernandez" <gabriel.fernandez@foss.st.com>
Cc: linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
	robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH 7/7] clk: stm32mp25: add ck_ker_usb2phy1_stp clock
Date: Fri, 23 Oct 2026 13:51:57 +0000	[thread overview]
Message-ID: <sashiko-outbox-182855@kernel.org> (raw)
In-Reply-To: <20261023-ups_mp25_clk_update-v1-7-e906e7a38cb3@foss.st.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] clk: stm32mp25: missing .disable_unused in clk_stm32_usb2phy1_stp_ops
- [Medium] clk: stm32mp25: stale or zero cached rate for ck_ker_usb2phy1_stp
--

commit 34669aa594d0d50f9cff33a984e8708660cbe4e8
Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com>

clk: stm32mp25: add ck_ker_usb2phy1_stp clock

This commit adds the ck_ker_usb2phy1_stp gate clock for USB Host low power
support on STM32MP25, parenting it to HSE_KER_ON and deriving its rate from
ck_ker_usb2phy1.

> diff --git a/drivers/clk/stm32/clk-stm32mp25.c b/drivers/clk/stm32/clk-stm32mp25.c
> index a6a1293370eb5..649af99680f46 100644
> --- a/drivers/clk/stm32/clk-stm32mp25.c
> +++ b/drivers/clk/stm32/clk-stm32mp25.c

[ ... ]

> @@ -1635,6 +1637,42 @@ static struct clk_stm32_composite ck_ker_usb2phy1 = {
>  					    &clk_stm32_composite_ops, 0),
>  };
>  
> +static int clk_stm32_usb2phy1_stp_enable(struct clk_hw *hw)
> +{
> +	return clk_stm32_gate_ops.enable(hw);
> +}
> +
> +static void clk_stm32_usb2phy1_stp_disable(struct clk_hw *hw)
> +{
> +	clk_stm32_gate_ops.disable(hw);
> +}
> +
> +static int clk_stm32_usb2phy1_stp_is_enabled(struct clk_hw *hw)
> +{
> +	return clk_stm32_gate_ops.is_enabled(hw);
> +}
> +
> +static unsigned long clk_stm32_usb2phy1_stp_recalc_rate(struct clk_hw *hw,
> +							unsigned long parent_rate)
> +{
> +	/* The rate of ck_ker_usb2phy1_stp is the same as ck_ker_usb2phy1 */
> +	return clk_hw_get_rate(&ck_ker_usb2phy1.hw);
> +}
> +
> +static const struct clk_ops clk_stm32_usb2phy1_stp_ops = {
> +	.enable		= clk_stm32_usb2phy1_stp_enable,
> +	.disable	= clk_stm32_usb2phy1_stp_disable,
> +	.is_enabled	= clk_stm32_usb2phy1_stp_is_enabled,
> +	.recalc_rate	= clk_stm32_usb2phy1_stp_recalc_rate,
> +};

[Severity: Medium]
Should clk_stm32_usb2phy1_stp_ops also wire up .disable_unused to
clk_stm32_gate_ops.disable_unused?

In drivers/clk/stm32/clk-stm32-core.c, clk_stm32_gate_ops provides a dedicated
.disable_unused callback:

const struct clk_ops clk_stm32_gate_ops = {
	.enable		= clk_stm32_gate_enable,
	.disable	= clk_stm32_gate_disable,
	.is_enabled	= clk_stm32_gate_is_enabled,
	.disable_unused	= clk_stm32_gate_disable_unused,
};

Because clk_stm32_usb2phy1_stp_ops omits .disable_unused,
clk_disable_unused_subtree() in drivers/clk/clk.c falls back to calling
core->ops->disable(core->hw) when the clock is enabled in hardware at boot
(bit 4 of RCC_USB2PHY1CFGR set) but unused by any consumer:

	if (clk_core_is_enabled(core)) {
		trace_clk_disable(core);
		if (core->ops->disable_unused)
			core->ops->disable_unused(core->hw);
		else if (core->ops->disable)
			core->ops->disable(core->hw);
		trace_clk_disable_complete(core);
	}

That calls clk_stm32_usb2phy1_stp_disable() -> clk_stm32_gate_ops.disable() ->
stm32_gate_endisable() with data->gate_cpt[GATE_USB2PHY1STP] == 0:

	} else {
		if (--data->gate_cpt[gate_id] > 0)
			return;

		if (gate->set_clr != 0)
			writel(BIT(gate->bit_idx), addr + gate->set_clr);
		else
			writel(readl(addr) & ~BIT(gate->bit_idx), addr);
	}

Wouldn't this underflow the u16 reference counter
data->gate_cpt[GATE_USB2PHY1STP] from 0 to 0xffff, causing
stm32_gate_endisable() to return early without clearing bit 4 in
RCC_USB2PHY1CFGR and preventing later clk_enable() / clk_disable() cycles from
disabling the gate?

> +
> +/* Parent clock of ck_ker_usb2phy1_stp is HSE_KER_ON to ensure it remains active during low power */
> +static struct clk_stm32_gate ck_ker_usb2phy1_stp = {
> +	.gate_id = GATE_USB2PHY1STP,
> +	.hw.init = CLK_HW_INIT_INDEX("ck_ker_usb2phy1_stp", HSE_KER_ON,
> +				     &clk_stm32_usb2phy1_stp_ops, 0),
> +};

[Severity: Medium]
Can clk_get_rate() on ck_ker_usb2phy1_stp return a stale or zero cached rate
here?

In drivers/clk/clk.c, clk_core_get_rate_recalc() only invokes .recalc_rate on
clk_get_rate() when CLK_GET_RATE_NOCACHE is set:

static unsigned long clk_core_get_rate_recalc(struct clk_core *core)
{
	if (core && (core->flags & CLK_GET_RATE_NOCACHE))
		__clk_recalc_rates(core, false, 0);

	return clk_core_get_rate_nolock(core);
}

Because ck_ker_usb2phy1_stp is parented to HSE_KER_ON rather than
ck_ker_usb2phy1 and its flags are 0, any rate or parent change on
ck_ker_usb2phy1 (such as via assigned-clock-parents / assigned-clock-rates in
of_clk_set_defaults() or runtime clk_set_rate() / clk_set_parent()) only
recalculates ck_ker_usb2phy1's subtree and leaves ck_ker_usb2phy1_stp's cached
core->rate stale.

In addition, when stm32mp25_rcc_clocks_probe() runs before the SCMI clock
provider is registered, stm32_rcc_clock_init() registers ck_ker_usb2phy1 and
then ck_ker_usb2phy1_stp as orphans via hlist_add_head(&core->child_node,
&clk_orphan_list) in __clk_core_init(). Because hlist_add_head() places
ck_ker_usb2phy1_stp ahead of ck_ker_usb2phy1 on clk_orphan_list,
clk_core_reparent_orphans_nolock() reparents and recalculates
ck_ker_usb2phy1_stp while ck_ker_usb2phy1 is still an orphan with rate 0,
caching 0 for ck_ker_usb2phy1_stp.

Finally, on device trees such as arch/arm64/boot/dts/st/stm32mp251.dtsi and
stm32mp231.dtsi where the optional CK_SCMI_HSE_KER_ON clock is not listed in
the rcc node's clocks property, ck_ker_usb2phy1_stp remains an orphan
(core->parent == NULL), causing clk_core_get_rate_nolock() to always return 0.

Should ck_ker_usb2phy1_stp set CLK_GET_RATE_NOCACHE, and how should the case
where HSE_KER_ON is absent from the device tree be handled?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261023-ups_mp25_clk_update-v1-0-e906e7a38cb3@foss.st.com?part=7

      reply	other threads:[~2026-10-23 13:51 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-23 13:28 [PATCH 0/7] clk: stm32mp25: add Cortex-M0 D3 clocks, ETR/STM and USB2PHY1 STP Gabriel Fernandez
2026-10-23 13:28 ` [PATCH 1/7] clk: stm32mp25: define the number of clocks in the driver Gabriel Fernandez
2026-10-23 13:28 ` [PATCH 2/7] dt-bindings: stm32: add kernel clocks for ETR and STM Gabriel Fernandez
2026-10-23 13:28 ` [PATCH 3/7] clk: stm32mp25: update register with reference manual Gabriel Fernandez
2026-10-23 13:28 ` [PATCH 4/7] dt-bindings: stm32: add clock binding for Cortex-CM0 on stm32mp25 platform Gabriel Fernandez
2026-10-23 13:28 ` [PATCH 5/7] clk: stm32mp25: add clock for D3 peripherals allocation for Cortex-CM0 Gabriel Fernandez
2026-10-23 13:28 ` [PATCH 6/7] dt-bindings: stm32: add binding for usb2phy1stp clock on stm32mp25 Gabriel Fernandez
2026-10-23 13:28 ` [PATCH 7/7] clk: stm32mp25: add ck_ker_usb2phy1_stp clock Gabriel Fernandez
2026-10-23 13:51   ` sashiko-bot [this message]

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=sashiko-outbox-182855@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=gabriel.fernandez@foss.st.com \
    --cc=linux-clk@vger.kernel.org \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.