From: sashiko-bot@kernel.org
To: "Troy Mitchell" <troy.mitchell@linux.spacemit.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH 2/5] clocksource/drivers/spacemit: Add K1 timer support
Date: Tue, 03 Nov 2026 09:02:07 +0000 [thread overview]
Message-ID: <sashiko-outbox-194914@kernel.org> (raw)
In-Reply-To: <20261103-spacemit-soc-timer-v1-2-36722421db6e@linux.spacemit.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] clocksource/drivers/spacemit: wrong MMIO register offsets for K1 timer
- [High] clocksource/drivers/spacemit: free-running mode in spacemit_timer_resume()
- [High] clocksource/drivers/spacemit: direct TMR_COUNT read in spacemit_timer_stop()
--
commit 4dc32afe42f41419e8802088abd5d90ef4a2a234
Author: Troy Mitchell <troy.mitchell@linux.spacemit.com>
clocksource/drivers/spacemit: Add K1 timer support
This commit adds a platform clockevent driver for the SpacemiT K1 and K3 APB
timers, using counter 0 and its first match comparator as a shared oneshot
broadcast timer device.
> diff --git a/drivers/clocksource/timer-spacemit.c b/drivers/clocksource/timer-spacemit.c
> new file mode 100644
> index 0000000000000..70076c17b5037
> --- /dev/null
> +++ b/drivers/clocksource/timer-spacemit.c
> @@ -0,0 +1,312 @@
[ ... ]
> +/* Use counter 0 and its first match comparator. */
> +#define TMR_CER 0x00
> +#define TMR_CMR 0x04
> +#define TMR_CCR 0x0c
> +#define TMR_MATCH 0x10
> +#define TMR_PRELOAD 0x40
> +#define TMR_PRELOAD_CTRL 0x50
> +#define TMR_IER 0x60
> +#define TMR_ICR 0x70
> +#define TMR_SR 0x80
> +#define TMR_COUNT 0x90
[Severity: High]
Are these register offsets matching the SpacemiT K1/K3 3-counter,
3-comparator APB timer hardware layout?
The K1/K3 timer block uses the MMP timer register map (as in
arch/arm/mach-mmp/regs-timers.h), where the counter 0 and shared control
registers are at:
TMR_CCR 0x0000
TMR_TN_MM(0, 0) 0x0004
TMR_CR(0) 0x0028
TMR_SR(0) 0x0034
TMR_IER(0) 0x0040
TMR_PLVR(0) 0x004c
TMR_PLCR(0) 0x0058
TMR_ICR(0) 0x0074
TMR_CER 0x0084
TMR_CMR 0x0088
TMR_CVWR(0) 0x00a4
With the offsets defined here, TMR_CER (0x00) points to TMR_CCR, TMR_CMR
(0x04) points to counter 0 match 0, TMR_CCR (0x0c) points to counter 0 match
2, TMR_MATCH (0x10) points to counter 1 match 0, TMR_PRELOAD (0x40) points to
TMR_IER(0), TMR_PRELOAD_CTRL (0x50) points to TMR_PLVR(1), TMR_IER (0x60)
points to TMR_PLCR(2), TMR_ICR (0x70) points to TMR_WSR, TMR_SR (0x80) points
to TMR_WICR, and TMR_COUNT (0x90) points to TMR_ILR(1).
Won't this cause spacemit_timer_probe(), spacemit_timer_resume(),
spacemit_timer_next_event(), and spacemit_timer_interrupt() to read and write
the wrong hardware registers?
[ ... ]
> +static int spacemit_timer_stop(struct spacemit_timer *timer)
> +{
> + u32 val, prev;
> + int ret, i;
> +
> + val = readl(timer->base + TMR_CER) & ~TMR_COUNTER_EN;
> + ret = spacemit_timer_write(timer, TMR_CER, val, TMR_COUNTER_EN);
> + if (ret)
> + return ret;
> +
> + /*
> + * CER crosses into the counter clock domain. Its readback alone does
> + * not show that counting has stopped. COUNT is synchronized back to
> + * APB, with up to three counter clocks of latency. Wait for a stable
> + * count before changing the match or preload registers.
> + */
> + prev = readl(timer->base + TMR_COUNT);
> + for (i = 0; i < 10; i++) {
> + udelay(timer->sync_us);
> + val = readl(timer->base + TMR_COUNT);
> + if (val == prev)
> + return 0;
> + prev = val;
> + }
> +
> + return -ETIMEDOUT;
> +}
[Severity: High]
Can the counter value register be read directly in spacemit_timer_stop()
without cross-domain metastability?
In this timer block, the counter register TMR_CR(n) runs in the functional
clock domain and is not synchronized to the APB bus on direct reads. As noted
in arch/arm/mach-mmp/time.c:timer_read():
__raw_writel(1, mmp_timer_base + TMR_CVWR(1));
while (delay--)
val = __raw_readl(mmp_timer_base + TMR_CVWR(1));
Should spacemit_timer_stop() latch and read the synchronized counter snapshot
through TMR_CVWR(0) (offset 0xa4) instead of reading the counter register
directly?
[ ... ]
> +static int spacemit_timer_next_event(unsigned long delta,
> + struct clock_event_device *evt)
> +{
> + struct spacemit_timer *timer = to_spacemit_timer(evt);
> + unsigned long flags;
> + u32 val;
> + int ret;
> +
> + raw_spin_lock_irqsave(&timer->lock, flags);
> +
> + ret = spacemit_timer_quiesce(timer);
> + if (ret)
> + goto out;
> +
> + ret = spacemit_timer_write(timer, TMR_MATCH, delta - 1, U32_MAX);
> + if (ret)
> + goto out;
> +
> + ret = spacemit_timer_write(timer, TMR_IER, TMR_MATCH0, TMR_MATCH_MASK);
> + if (ret)
> + goto out;
> +
> + /* Enabling the counter reloads the zero preload value. */
> + val = readl(timer->base + TMR_CER) | TMR_COUNTER_EN;
> + ret = spacemit_timer_write(timer, TMR_CER, val, TMR_COUNTER_EN);
[ ... ]
> +static int spacemit_timer_resume(struct clock_event_device *evt)
> +{
> + struct spacemit_timer *timer = to_spacemit_timer(evt);
> + unsigned long flags;
> + u32 val;
> + int ret;
> +
> + raw_spin_lock_irqsave(&timer->lock, flags);
> + ret = spacemit_timer_quiesce(timer);
> + if (ret)
> + goto out;
> +
> + /* Select the functional clock and disable automatic match reload. */
> + val = readl(timer->base + TMR_CCR) & ~TMR_CLOCK_MASK;
> + ret = spacemit_timer_write(timer, TMR_CCR, val, TMR_CLOCK_MASK);
> + if (ret)
> + goto out;
> +
> + val = readl(timer->base + TMR_CMR) | TMR_FREE_RUNNING;
> + ret = spacemit_timer_write(timer, TMR_CMR, val, TMR_FREE_RUNNING);
> + if (ret)
> + goto out;
> +
> + ret = spacemit_timer_write(timer, TMR_PRELOAD_CTRL, 0, GENMASK(2, 0));
> + if (ret)
> + goto out;
> +
> + ret = spacemit_timer_write(timer, TMR_PRELOAD, 0, U32_MAX);
[Severity: High]
When TMR_FREE_RUNNING (BIT(0)) is set in TMR_CMR during
spacemit_timer_resume(), does enabling the counter in
spacemit_timer_next_event() reload TMR_PRELOAD?
In this timer block, setting bit 0 of TMR_CMR selects free-running mode where
the counter wraps across 32 bits and ignores the preload register, whereas
clearing bit 0 of TMR_CMR selects preload mode (as in
arch/arm/mach-mmp/time.c:timer_config(), which clears bit 0 in TMR_CMR for
counter 0).
Because spacemit_timer_next_event() programs TMR_MATCH with delta - 1
relative to zero rather than relative to the current counter value, won't
setting TMR_FREE_RUNNING in TMR_CMR leave the counter at its previous non-zero
value when re-enabled, causing oneshot events to fire at the wrong time or
wait for a full 32-bit wraparound?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261103-spacemit-soc-timer-v1-0-36722421db6e@linux.spacemit.com?part=2
next prev parent reply other threads:[~2026-11-03 9:02 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 8:36 [PATCH 0/5] Add SpacemiT K1/K3 SoC timer support Troy Mitchell
2026-11-03 8:36 ` Troy Mitchell
2026-11-03 8:36 ` [PATCH 1/5] dt-bindings: timer: Add SpacemiT K1 timer Troy Mitchell
2026-11-03 8:36 ` Troy Mitchell
2026-11-03 8:36 ` [PATCH 2/5] clocksource/drivers/spacemit: Add K1 timer support Troy Mitchell
2026-11-03 8:36 ` Troy Mitchell
2026-11-03 9:02 ` sashiko-bot [this message]
2026-11-03 9:59 ` Troy Mitchell
2026-11-04 18:28 ` Iker Pedrosa
2026-11-04 18:28 ` Iker Pedrosa
2026-11-03 8:36 ` [PATCH 3/5] riscv: dts: spacemit: Add the K1 APB timer Troy Mitchell
2026-11-03 8:36 ` Troy Mitchell
2026-11-04 18:34 ` Iker Pedrosa
2026-11-04 18:34 ` Iker Pedrosa
2026-11-03 8:36 ` [PATCH 4/5] riscv: dts: spacemit: Add the K3 " Troy Mitchell
2026-11-03 8:36 ` Troy Mitchell
2026-11-03 8:36 ` [PATCH 5/5] MAINTAINERS: Add entry for SpacemiT timer Troy Mitchell
2026-11-03 8:36 ` Troy Mitchell
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-194914@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=troy.mitchell@linux.spacemit.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 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.