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

From: Jiaxun Yang
Date: Fri Jan 03 2025 - 07:10:26 EST


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@xxxxxxxxxxx>
---
Changes in v2:
- Move probing to cpu-probe
- Link to v1: https://lore.kernel.org/r/20250102-la-misc-v1-1-8dc7db525e54@xxxxxxxxxxx
---
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@xxxxxxxxxxx>