From 742c4cc1853e2529d7b0d020c0387038f979bf07 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Thu, 13 Oct 2022 20:45:37 +0200 Subject: [PATCH v2 3/5] Revert "clocksource/drivers/arm_global_timer: Implement rate compensation whenever source clock changes" This reverts commit 171b45a4a70eef2fd36bb794ce4f5a48c440361e. --- drivers/clocksource/Kconfig | 14 --- drivers/clocksource/arm_global_timer.c | 122 ++----------------------- 2 files changed, 10 insertions(+), 126 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 4469e7f555e9..7b00efa59ffb 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -375,20 +375,6 @@ config ARM_GLOBAL_TIMER help This option enables support for the ARM global timer unit. -config ARM_GT_INITIAL_PRESCALER_VAL - int "ARM global timer initial prescaler value" - default 2 if ARCH_ZYNQ - default 1 - depends on ARM_GLOBAL_TIMER - help - When the ARM global timer initializes, its current rate is declared - to the kernel and maintained forever. Should its parent clock - change, the driver tries to fix the timer's internal prescaler. - On some machs (i.e. Zynq) the initial prescaler value thus poses - bounds about how much the parent clock is allowed to decrease or - increase wrt the initial clock value. - This affects CPU_FREQ max delta from the initial frequency. - config ARM_TIMER_SP804 bool "Support for Dual Timer SP804 module" if COMPILE_TEST depends on GENERIC_SCHED_CLOCK && HAVE_CLK diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index 60a8047fd32e..88b2d38a7a61 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -31,10 +31,6 @@ #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 0xF -#define GT_CONTROL_PRESCALER_MASK (GT_CONTROL_PRESCALER_MAX << \ - GT_CONTROL_PRESCALER_SHIFT) #define GT_INT_STATUS 0x0c #define GT_INT_STATUS_EVENT_FLAG BIT(0) @@ -43,7 +39,6 @@ #define GT_COMP1 0x14 #define GT_AUTO_INC 0x18 -#define MAX_F_ERR 50 /* * We are expecting to be clocked by the ARM peripheral clock. * @@ -51,8 +46,7 @@ * the units for all operations. */ static void __iomem *gt_base; -struct notifier_block gt_clk_rate_change_nb; -static u32 gt_psv_new, gt_psv_bck, gt_target_rate; +static unsigned long gt_clk_rate; static int gt_ppi; static struct clock_event_device __percpu *gt_evt; @@ -102,10 +96,7 @@ static void gt_compare_set(unsigned long delta, int periodic) unsigned long ctrl; counter += delta; - ctrl = readl(gt_base + GT_CONTROL); - ctrl &= ~(GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE | - GT_CONTROL_AUTO_INC | GT_CONTROL_AUTO_INC); - ctrl |= GT_CONTROL_TIMER_ENABLE; + ctrl = GT_CONTROL_TIMER_ENABLE; writel_relaxed(ctrl, gt_base + GT_CONTROL); writel_relaxed(lower_32_bits(counter), gt_base + GT_COMP0); writel_relaxed(upper_32_bits(counter), gt_base + GT_COMP1); @@ -132,7 +123,7 @@ static int gt_clockevent_shutdown(struct clock_event_device *evt) static int gt_clockevent_set_periodic(struct clock_event_device *evt) { - gt_compare_set(DIV_ROUND_CLOSEST(gt_target_rate, HZ), 1); + gt_compare_set(DIV_ROUND_CLOSEST(gt_clk_rate, HZ), 1); return 0; } @@ -186,7 +177,7 @@ static int gt_starting_cpu(unsigned int cpu) clk->cpumask = cpumask_of(cpu); clk->rating = 300; clk->irq = gt_ppi; - clockevents_config_and_register(clk, gt_target_rate, + clockevents_config_and_register(clk, gt_clk_rate, 1, 0xffffffff); enable_percpu_irq(clk->irq, IRQ_TYPE_NONE); return 0; @@ -241,28 +232,9 @@ static struct delay_timer gt_delay_timer = { .read_current_timer = gt_read_long, }; -static void gt_write_presc(u32 psv) -{ - u32 reg; - - reg = readl(gt_base + GT_CONTROL); - reg &= ~GT_CONTROL_PRESCALER_MASK; - reg |= psv << GT_CONTROL_PRESCALER_SHIFT; - writel(reg, gt_base + GT_CONTROL); -} - -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; -} - static void __init gt_delay_timer_init(void) { - gt_delay_timer.freq = gt_target_rate; + gt_delay_timer.freq = gt_clk_rate; register_current_timer_delay(>_delay_timer); } @@ -271,81 +243,18 @@ static int __init gt_clocksource_init(void) writel(0, gt_base + GT_CONTROL); 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); + /* enables timer on all the cores */ + writel(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); + sched_clock_register(gt_sched_clock_read, 64, gt_clk_rate); #endif - return clocksource_register_hz(>_clocksource, gt_target_rate); -} - -static int gt_clk_rate_change_cb(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct clk_notifier_data *ndata = data; - - switch (event) { - case PRE_RATE_CHANGE: - { - int psv; - - psv = DIV_ROUND_CLOSEST(ndata->new_rate, - gt_target_rate); - - if (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) - return NOTIFY_BAD; - - /* - * store timer clock ctrl register so we can restore it in case - * of an abort. - */ - gt_psv_bck = gt_read_presc(); - gt_psv_new = psv; - /* scale down: adjust divider in post-change notification */ - if (ndata->new_rate < ndata->old_rate) - return NOTIFY_DONE; - - /* scale up: adjust divider now - before frequency change */ - gt_write_presc(psv); - break; - } - case POST_RATE_CHANGE: - /* scale up: pre-change notification did the adjustment */ - if (ndata->new_rate > ndata->old_rate) - return NOTIFY_OK; - - /* scale down: adjust divider now - after frequency change */ - gt_write_presc(gt_psv_new); - break; - - case ABORT_RATE_CHANGE: - /* we have to undo the adjustment in case we scale up */ - if (ndata->new_rate < ndata->old_rate) - return NOTIFY_OK; - - /* restore original register value */ - gt_write_presc(gt_psv_bck); - break; - default: - return NOTIFY_DONE; - } - - return NOTIFY_DONE; + return clocksource_register_hz(>_clocksource, gt_clk_rate); } static int __init global_timer_of_register(struct device_node *np) { struct clk *gt_clk; - static unsigned long gt_clk_rate; int err = 0; /* @@ -383,20 +292,11 @@ static int __init global_timer_of_register(struct device_node *np) } gt_clk_rate = clk_get_rate(gt_clk); - gt_target_rate = gt_clk_rate / CONFIG_ARM_GT_INITIAL_PRESCALER_VAL; - gt_clk_rate_change_nb.notifier_call = - gt_clk_rate_change_cb; - err = clk_notifier_register(gt_clk, >_clk_rate_change_nb); - if (err) { - pr_warn("Unable to register clock notifier\n"); - goto out_clk; - } - gt_evt = alloc_percpu(struct clock_event_device); if (!gt_evt) { pr_warn("global-timer: can't allocate memory\n"); err = -ENOMEM; - goto out_clk_nb; + goto out_clk; } err = request_percpu_irq(gt_ppi, gt_clockevent_interrupt, @@ -426,8 +326,6 @@ static int __init global_timer_of_register(struct device_node *np) free_percpu_irq(gt_ppi, gt_evt); out_free: free_percpu(gt_evt); -out_clk_nb: - clk_notifier_unregister(gt_clk, >_clk_rate_change_nb); out_clk: clk_disable_unprepare(gt_clk); out_unmap: -- 2.20.1