[PATCH v2] loongarch: time: Derive max_delta from prcfg1 tmrbits

Jiaxun Yang posted 1 patch 1 year, 1 month ago
arch/loongarch/include/asm/cpu-info.h  | 1 +
arch/loongarch/include/asm/loongarch.h | 1 -
arch/loongarch/kernel/cpu-probe.c      | 2 ++
arch/loongarch/kernel/time.c           | 2 +-
4 files changed, 4 insertions(+), 2 deletions(-)
[PATCH v2] loongarch: time: Derive max_delta from prcfg1 tmrbits
Posted by Jiaxun Yang 1 year, 1 month ago
As per arch spec, maximum timer bits is configurable and
should not be hardcoded in any way.

Probe timer bits from prcfg1 and use that to determine
clockevent's max_delta to be conformance.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
Changes in v2:
- Move probing to cpu-probe
- Link to v1: https://lore.kernel.org/r/20250102-la-misc-v1-1-8dc7db525e54@flygoat.com
---
 arch/loongarch/include/asm/cpu-info.h  | 1 +
 arch/loongarch/include/asm/loongarch.h | 1 -
 arch/loongarch/kernel/cpu-probe.c      | 2 ++
 arch/loongarch/kernel/time.c           | 2 +-
 4 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/loongarch/include/asm/cpu-info.h b/arch/loongarch/include/asm/cpu-info.h
index 900589cb159de4e5997358443c5b5e3e50f92239..fb28ba9e3011c9256da4a9748de97236ae7f001f 100644
--- a/arch/loongarch/include/asm/cpu-info.h
+++ b/arch/loongarch/include/asm/cpu-info.h
@@ -57,6 +57,7 @@ struct cpuinfo_loongarch {
 	int			global_id; /* physical global thread number */
 	int			vabits; /* Virtual Address size in bits */
 	int			pabits; /* Physical Address size in bits */
+	int			timerbits; /* Width of timer in bits */
 	unsigned int		ksave_mask; /* Usable KSave mask. */
 	unsigned int		watch_dreg_count;   /* Number data breakpoints */
 	unsigned int		watch_ireg_count;   /* Number instruction breakpoints */
diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h
index 64ad277e096edd7d77af6f37e234d68e571764a4..a3cc4f8d4c4a0b0521ef2b76c87fa57eca417d75 100644
--- a/arch/loongarch/include/asm/loongarch.h
+++ b/arch/loongarch/include/asm/loongarch.h
@@ -466,7 +466,6 @@
 
 #define LOONGARCH_CSR_TCFG		0x41	/* Timer config */
 #define  CSR_TCFG_VAL_SHIFT		2
-#define	 CSR_TCFG_VAL_WIDTH		48
 #define  CSR_TCFG_VAL			(_ULCAST_(0x3fffffffffff) << CSR_TCFG_VAL_SHIFT)
 #define  CSR_TCFG_PERIOD_SHIFT		1
 #define  CSR_TCFG_PERIOD		(_ULCAST_(0x1) << CSR_TCFG_PERIOD_SHIFT)
diff --git a/arch/loongarch/kernel/cpu-probe.c b/arch/loongarch/kernel/cpu-probe.c
index cbce099037b2728b82ecb9c5aa58e05b07695c5a..06c98ddf29490571e8b927b4ca721c27ff7f0ea8 100644
--- a/arch/loongarch/kernel/cpu-probe.c
+++ b/arch/loongarch/kernel/cpu-probe.c
@@ -192,6 +192,8 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
 	config = read_csr_prcfg1();
 	c->ksave_mask = GENMASK((config & CSR_CONF1_KSNUM) - 1, 0);
 	c->ksave_mask &= ~(EXC_KSAVE_MASK | PERCPU_KSAVE_MASK | KVM_KSAVE_MASK);
+	c->timerbits = (config & CSR_CONF1_TMRBITS) >> CSR_CONF1_TMRBITS_SHIFT;
+	c->timerbits += 1;
 
 	config = read_csr_prcfg3();
 	switch (config & CSR_CONF3_TLBTYPE) {
diff --git a/arch/loongarch/kernel/time.c b/arch/loongarch/kernel/time.c
index a07d7eff4dc5fb0f41f5fad02698ff7a84c7bc8a..ebfdab6b155585dbab08b7cc49cba627a59854ec 100644
--- a/arch/loongarch/kernel/time.c
+++ b/arch/loongarch/kernel/time.c
@@ -132,7 +132,7 @@ int constant_clockevent_init(void)
 #else
 	unsigned long min_delta = 1000;
 #endif
-	unsigned long max_delta = (1UL << 48) - 1;
+	unsigned long max_delta = CLOCKSOURCE_MASK(current_cpu_data.timerbits);
 	struct clock_event_device *cd;
 	static int irq = 0, timer_irq_installed = 0;
 

---
base-commit: 8155b4ef3466f0e289e8fcc9e6e62f3f4dceeac2
change-id: 20241223-la-misc-d610d14f947e

Best regards,
-- 
Jiaxun Yang <jiaxun.yang@flygoat.com>
Re: [PATCH v2] loongarch: time: Derive max_delta from prcfg1 tmrbits
Posted by Huacai Chen 1 year, 1 month ago
Applied, thanks.

Huacai

On Fri, Jan 3, 2025 at 8:10 PM Jiaxun Yang <jiaxun.yang@flygoat.com> wrote:
>
> As per arch spec, maximum timer bits is configurable and
> should not be hardcoded in any way.
>
> Probe timer bits from prcfg1 and use that to determine
> clockevent's max_delta to be conformance.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
> Changes in v2:
> - Move probing to cpu-probe
> - Link to v1: https://lore.kernel.org/r/20250102-la-misc-v1-1-8dc7db525e54@flygoat.com
> ---
>  arch/loongarch/include/asm/cpu-info.h  | 1 +
>  arch/loongarch/include/asm/loongarch.h | 1 -
>  arch/loongarch/kernel/cpu-probe.c      | 2 ++
>  arch/loongarch/kernel/time.c           | 2 +-
>  4 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/arch/loongarch/include/asm/cpu-info.h b/arch/loongarch/include/asm/cpu-info.h
> index 900589cb159de4e5997358443c5b5e3e50f92239..fb28ba9e3011c9256da4a9748de97236ae7f001f 100644
> --- a/arch/loongarch/include/asm/cpu-info.h
> +++ b/arch/loongarch/include/asm/cpu-info.h
> @@ -57,6 +57,7 @@ struct cpuinfo_loongarch {
>         int                     global_id; /* physical global thread number */
>         int                     vabits; /* Virtual Address size in bits */
>         int                     pabits; /* Physical Address size in bits */
> +       int                     timerbits; /* Width of timer in bits */
>         unsigned int            ksave_mask; /* Usable KSave mask. */
>         unsigned int            watch_dreg_count;   /* Number data breakpoints */
>         unsigned int            watch_ireg_count;   /* Number instruction breakpoints */
> diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h
> index 64ad277e096edd7d77af6f37e234d68e571764a4..a3cc4f8d4c4a0b0521ef2b76c87fa57eca417d75 100644
> --- a/arch/loongarch/include/asm/loongarch.h
> +++ b/arch/loongarch/include/asm/loongarch.h
> @@ -466,7 +466,6 @@
>
>  #define LOONGARCH_CSR_TCFG             0x41    /* Timer config */
>  #define  CSR_TCFG_VAL_SHIFT            2
> -#define         CSR_TCFG_VAL_WIDTH             48
>  #define  CSR_TCFG_VAL                  (_ULCAST_(0x3fffffffffff) << CSR_TCFG_VAL_SHIFT)
>  #define  CSR_TCFG_PERIOD_SHIFT         1
>  #define  CSR_TCFG_PERIOD               (_ULCAST_(0x1) << CSR_TCFG_PERIOD_SHIFT)
> diff --git a/arch/loongarch/kernel/cpu-probe.c b/arch/loongarch/kernel/cpu-probe.c
> index cbce099037b2728b82ecb9c5aa58e05b07695c5a..06c98ddf29490571e8b927b4ca721c27ff7f0ea8 100644
> --- a/arch/loongarch/kernel/cpu-probe.c
> +++ b/arch/loongarch/kernel/cpu-probe.c
> @@ -192,6 +192,8 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
>         config = read_csr_prcfg1();
>         c->ksave_mask = GENMASK((config & CSR_CONF1_KSNUM) - 1, 0);
>         c->ksave_mask &= ~(EXC_KSAVE_MASK | PERCPU_KSAVE_MASK | KVM_KSAVE_MASK);
> +       c->timerbits = (config & CSR_CONF1_TMRBITS) >> CSR_CONF1_TMRBITS_SHIFT;
> +       c->timerbits += 1;
>
>         config = read_csr_prcfg3();
>         switch (config & CSR_CONF3_TLBTYPE) {
> diff --git a/arch/loongarch/kernel/time.c b/arch/loongarch/kernel/time.c
> index a07d7eff4dc5fb0f41f5fad02698ff7a84c7bc8a..ebfdab6b155585dbab08b7cc49cba627a59854ec 100644
> --- a/arch/loongarch/kernel/time.c
> +++ b/arch/loongarch/kernel/time.c
> @@ -132,7 +132,7 @@ int constant_clockevent_init(void)
>  #else
>         unsigned long min_delta = 1000;
>  #endif
> -       unsigned long max_delta = (1UL << 48) - 1;
> +       unsigned long max_delta = CLOCKSOURCE_MASK(current_cpu_data.timerbits);
>         struct clock_event_device *cd;
>         static int irq = 0, timer_irq_installed = 0;
>
>
> ---
> base-commit: 8155b4ef3466f0e289e8fcc9e6e62f3f4dceeac2
> change-id: 20241223-la-misc-d610d14f947e
>
> Best regards,
> --
> Jiaxun Yang <jiaxun.yang@flygoat.com>
>