From b34b9547cee41575a4fddf390f615570759dc999 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 18 Feb 2024 18:41:37 +0100 Subject: clocksource/drivers/arm_global_timer: Fix maximum prescaler value The prescaler in the "Global Timer Control Register bit assignments" is documented to use bits [15:8], which means that the maximum prescaler register value is 0xff. Fixes: 171b45a4a70e ("clocksource/drivers/arm_global_timer: Implement rate compensation whenever source clock changes") Signed-off-by: Martin Blumenstingl Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240218174138.1942418-2-martin.blumenstingl@googlemail.com --- drivers/clocksource/arm_global_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clocksource/arm_global_timer.c') diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index 44a61dc6f932..e1c773bb5535 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -32,7 +32,7 @@ #define GT_CONTROL_IRQ_ENABLE BIT(2) /* banked */ #define GT_CONTROL_AUTO_INC BIT(3) /* banked */ #define GT_CONTROL_PRESCALER_SHIFT 8 -#define GT_CONTROL_PRESCALER_MAX 0xF +#define GT_CONTROL_PRESCALER_MAX 0xFF #define GT_CONTROL_PRESCALER_MASK (GT_CONTROL_PRESCALER_MAX << \ GT_CONTROL_PRESCALER_SHIFT) -- cgit v1.2.3 From 9256cec7b4f3293c11585326401325b1f81670e1 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 18 Feb 2024 18:41:38 +0100 Subject: clocksource/drivers/arm_global_timer: Remove stray tab Remove a stray tab in global_timer_of_register() which is different from the coding style in the rest of the driver. Signed-off-by: Martin Blumenstingl Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240218174138.1942418-3-martin.blumenstingl@googlemail.com --- drivers/clocksource/arm_global_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clocksource/arm_global_timer.c') diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index e1c773bb5535..8dd1e46b7176 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -411,7 +411,7 @@ static int __init global_timer_of_register(struct device_node *np) err = gt_clocksource_init(); if (err) goto out_irq; - + err = cpuhp_setup_state(CPUHP_AP_ARM_GLOBAL_TIMER_STARTING, "clockevents/arm/global_timer:starting", gt_starting_cpu, gt_dying_cpu); -- cgit v1.2.3 From 97454a65d56b240013ed8d396427b85e34384238 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 14 Jan 2024 21:36:41 -0800 Subject: clocksource: arm_global_timer: fix non-kernel-doc comment Use a common C comment "/*" instead of a kernel-doc marker "/**" to prevent kernel-doc warnings: arm_global_timer.c:92: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst * To ensure that updates to comparator value register do not set the arm_global_timer.c:92: warning: missing initial short description on line: * To ensure that updates to comparator value register do not set the Signed-off-by: Randy Dunlap Cc: Patrice Chotard Cc: linux-arm-kernel@lists.infradead.org Cc: Daniel Lezcano Cc: Thomas Gleixner Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240115053641.29129-1-rdunlap@infradead.org --- drivers/clocksource/arm_global_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clocksource/arm_global_timer.c') diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index 8dd1e46b7176..d749dee1d41d 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -88,7 +88,7 @@ static u64 gt_counter_read(void) return _gt_counter_read(); } -/** +/* * To ensure that updates to comparator value register do not set the * Interrupt Status Register proceed as follows: * 1. Clear the Comp Enable bit in the Timer Control Register. -- cgit v1.2.3 From f31c204850f9d93906b5ac8c203b2066524ff245 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 25 Feb 2024 16:13:34 +0100 Subject: clocksource/drivers/arm_global_timer: Make gt_target_rate unsigned long Change the data type of gt_target_rate to unsigned long as this is what we get back from clk_get_rate(). Signed-off-by: Martin Blumenstingl Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240225151336.2728533-2-martin.blumenstingl@googlemail.com --- drivers/clocksource/arm_global_timer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/clocksource/arm_global_timer.c') diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index d749dee1d41d..fd39cfabe526 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -52,7 +52,8 @@ */ static void __iomem *gt_base; static struct notifier_block gt_clk_rate_change_nb; -static u32 gt_psv_new, gt_psv_bck, gt_target_rate; +static u32 gt_psv_new, gt_psv_bck; +static unsigned long gt_target_rate; static int gt_ppi; static struct clock_event_device __percpu *gt_evt; -- cgit v1.2.3 From e651f2fae33634175fae956d896277cf916f5d09 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 25 Feb 2024 16:13:35 +0100 Subject: clocksource/drivers/arm_global_timer: Guard against division by zero The result of the division of new_rate by gt_target_rate can be zero (if new_rate is smaller than gt_target_rate). Using that result as divisor without checking can result in a division by zero error. Guard against this by checking for a zero value earlier. While here, also change the psv variable to an unsigned long to make sure we don't overflow the datatype as all other types involved are also unsiged long. Signed-off-by: Martin Blumenstingl Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240225151336.2728533-3-martin.blumenstingl@googlemail.com --- drivers/clocksource/arm_global_timer.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/clocksource/arm_global_timer.c') diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index fd39cfabe526..4726a15b0afc 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -291,18 +291,17 @@ static int gt_clk_rate_change_cb(struct notifier_block *nb, switch (event) { case PRE_RATE_CHANGE: { - int psv; + unsigned long psv; - psv = DIV_ROUND_CLOSEST(ndata->new_rate, - gt_target_rate); - - if (abs(gt_target_rate - (ndata->new_rate / psv)) > MAX_F_ERR) + psv = DIV_ROUND_CLOSEST(ndata->new_rate, gt_target_rate); + if (!psv || + abs(gt_target_rate - (ndata->new_rate / psv)) > MAX_F_ERR) return NOTIFY_BAD; psv--; /* prescaler within legal range? */ - if (psv < 0 || psv > GT_CONTROL_PRESCALER_MAX) + if (psv > GT_CONTROL_PRESCALER_MAX) return NOTIFY_BAD; /* -- cgit v1.2.3 From 755350bcfb4ac8cbbb62bd7ee6be8271d4b2a88a Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 25 Feb 2024 16:13:36 +0100 Subject: clocksource/drivers/arm_global_timer: Simplify prescaler register access Use GENMASK() to define the prescaler mask and make the whole driver use the mask (together with helpers such as FIELD_{GET,PREP,FIT}) instead of needing an additional shift and max value constant. Signed-off-by: Martin Blumenstingl Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20240225151336.2728533-4-martin.blumenstingl@googlemail.com --- drivers/clocksource/arm_global_timer.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers/clocksource/arm_global_timer.c') diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index 4726a15b0afc..ab1c8c2b66b8 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -31,10 +32,7 @@ #define GT_CONTROL_COMP_ENABLE BIT(1) /* banked */ #define GT_CONTROL_IRQ_ENABLE BIT(2) /* banked */ #define GT_CONTROL_AUTO_INC BIT(3) /* banked */ -#define GT_CONTROL_PRESCALER_SHIFT 8 -#define GT_CONTROL_PRESCALER_MAX 0xFF -#define GT_CONTROL_PRESCALER_MASK (GT_CONTROL_PRESCALER_MAX << \ - GT_CONTROL_PRESCALER_SHIFT) +#define GT_CONTROL_PRESCALER_MASK GENMASK(15, 8) #define GT_INT_STATUS 0x0c #define GT_INT_STATUS_EVENT_FLAG BIT(0) @@ -248,7 +246,7 @@ static void gt_write_presc(u32 psv) reg = readl(gt_base + GT_CONTROL); reg &= ~GT_CONTROL_PRESCALER_MASK; - reg |= psv << GT_CONTROL_PRESCALER_SHIFT; + reg |= FIELD_PREP(GT_CONTROL_PRESCALER_MASK, psv); writel(reg, gt_base + GT_CONTROL); } @@ -257,8 +255,7 @@ static u32 gt_read_presc(void) u32 reg; reg = readl(gt_base + GT_CONTROL); - reg &= GT_CONTROL_PRESCALER_MASK; - return reg >> GT_CONTROL_PRESCALER_SHIFT; + return FIELD_GET(GT_CONTROL_PRESCALER_MASK, reg); } static void __init gt_delay_timer_init(void) @@ -273,9 +270,9 @@ static int __init gt_clocksource_init(void) writel(0, gt_base + GT_COUNTER0); writel(0, gt_base + GT_COUNTER1); /* set prescaler and enable timer on all the cores */ - writel(((CONFIG_ARM_GT_INITIAL_PRESCALER_VAL - 1) << - GT_CONTROL_PRESCALER_SHIFT) - | GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL); + writel(FIELD_PREP(GT_CONTROL_PRESCALER_MASK, + CONFIG_ARM_GT_INITIAL_PRESCALER_VAL - 1) | + GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL); #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK sched_clock_register(gt_sched_clock_read, 64, gt_target_rate); @@ -301,7 +298,7 @@ static int gt_clk_rate_change_cb(struct notifier_block *nb, psv--; /* prescaler within legal range? */ - if (psv > GT_CONTROL_PRESCALER_MAX) + if (!FIELD_FIT(GT_CONTROL_PRESCALER_MASK, psv)) return NOTIFY_BAD; /* -- cgit v1.2.3