Re: [PATCH] clocksource/drivers/exynos_mct: Support using only local timer

From: Krzysztof Kozlowski
Date: Mon Mar 07 2022 - 04:06:38 EST


On 07/03/2022 09:32, Vincent Whitchurch wrote:
> The ARTPEC-8 SoC has a quad-core Cortex-A53 and a single-core Cortex-A5
> which share one MCT with one global and eight local timers.
>
> The Cortex-A53 boots first and starts the global FRC and also registers
> a clock events device using the global timer. (This global timer clock
> events is usually replaced by arch timer clock events for each of the
> cores.)
>
> When the A5 boots, we should not use the global timer interrupts or
> write to the global timer registers. This is because even if there are
> four global comparators, the control bits for all four are in the same
> registers, and we would need to synchronize between the cpus. Instead,
> the global timer FRC (already started by the A53) should be used as the
> clock source, and one of the local timers which are not used by the A53
> can be used for clock events on the A5.
>
> To support this, add a module param to set the local timer starting
> index. If this parameter is non-zero, the global timer clock events
> device is not registered and we don't write to the global FRC if it is
> already started.
>
> Signed-off-by: Vincent Whitchurch <vincent.whitchurch@xxxxxxxx>
> ---
> drivers/clocksource/exynos_mct.c | 29 ++++++++++++++++++++++++-----
> 1 file changed, 24 insertions(+), 5 deletions(-)

This should not be send separately from the previous patch.

>
> diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
> index f29c812b70c9..7ea2919b1808 100644
> --- a/drivers/clocksource/exynos_mct.c
> +++ b/drivers/clocksource/exynos_mct.c
> @@ -33,7 +33,7 @@
> #define EXYNOS4_MCT_G_INT_ENB EXYNOS4_MCTREG(0x248)
> #define EXYNOS4_MCT_G_WSTAT EXYNOS4_MCTREG(0x24C)
> #define _EXYNOS4_MCT_L_BASE EXYNOS4_MCTREG(0x300)
> -#define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * x))
> +#define EXYNOS4_MCT_L_BASE(x) (_EXYNOS4_MCT_L_BASE + (0x100 * (x)))
> #define EXYNOS4_MCT_L_MASK (0xffffff00)
>
> #define MCT_L_TCNTB_OFFSET (0x00)
> @@ -77,6 +77,13 @@ static unsigned long clk_rate;
> static unsigned int mct_int_type;
> static int mct_irqs[MCT_NR_IRQS];
>
> +/*
> + * First local timer index to use. If non-zero, global
> + * timer is not written to.
> + */
> +static unsigned int mct_local_idx;
> +module_param_named(local_idx, mct_local_idx, int, 0);

No, it's a no go. Please use dedicated compatible if you need specific
quirks.

> +
> struct mct_clock_event_device {
> struct clock_event_device evt;
> unsigned long base;
> @@ -157,6 +164,17 @@ static void exynos4_mct_frc_start(void)
> u32 reg;
>
> reg = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
> +
> + /*
> + * If the FRC is already running, we don't need to start it again. We
> + * could probably just do this on all systems, but, to avoid any risk
> + * for regressions, we only do it on systems where it's absolutely
> + * necessary (i.e., on systems where writes to the global registers
> + * need to be avoided).
> + */
> + if (mct_local_idx && (reg & MCT_G_TCON_START))
> + return;

I don't get it. exynos4_mct_frc_start() is called exactly only once in
the system - during init. Not once per every CPU or cluster (I
understood you have two clusters, right?).

Best regards,
Krzysztof