Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clocksource: atmel-st: get and use slow clock

The current slow clock rate is hardcoded. Properly get the slow clock
and use its rate.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>

+22 -9
+22 -9
drivers/clocksource/timer-atmel-st.c
··· 22 22 #include <linux/kernel.h> 23 23 #include <linux/interrupt.h> 24 24 #include <linux/irq.h> 25 + #include <linux/clk.h> 25 26 #include <linux/clockchips.h> 26 27 #include <linux/export.h> 27 28 #include <linux/mfd/syscon.h> ··· 34 33 static u32 irqmask; 35 34 static struct clock_event_device clkevt; 36 35 static struct regmap *regmap_st; 37 - 38 - #define AT91_SLOW_CLOCK 32768 39 - #define RM9200_TIMER_LATCH ((AT91_SLOW_CLOCK + HZ/2) / HZ) 36 + static int timer_latch; 40 37 41 38 /* 42 39 * The ST_CRTR is updated asynchronously to the master clock ... but ··· 81 82 if (sr & AT91_ST_PITS) { 82 83 u32 crtr = read_CRTR(); 83 84 84 - while (((crtr - last_crtr) & AT91_ST_CRTV) >= RM9200_TIMER_LATCH) { 85 - last_crtr += RM9200_TIMER_LATCH; 85 + while (((crtr - last_crtr) & AT91_ST_CRTV) >= timer_latch) { 86 + last_crtr += timer_latch; 86 87 clkevt.event_handler(&clkevt); 87 88 } 88 89 return IRQ_HANDLED; ··· 143 144 144 145 /* PIT for periodic irqs; fixed rate of 1/HZ */ 145 146 irqmask = AT91_ST_PITS; 146 - regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH); 147 + regmap_write(regmap_st, AT91_ST_PIMR, timer_latch); 147 148 regmap_write(regmap_st, AT91_ST_IER, irqmask); 148 149 return 0; 149 150 } ··· 196 197 */ 197 198 static void __init atmel_st_timer_init(struct device_node *node) 198 199 { 199 - unsigned int val; 200 + struct clk *sclk; 201 + unsigned int sclk_rate, val; 200 202 int irq, ret; 201 203 202 204 regmap_st = syscon_node_to_regmap(node); ··· 221 221 if (ret) 222 222 panic(pr_fmt("Unable to setup IRQ\n")); 223 223 224 + sclk = of_clk_get(node, 0); 225 + if (IS_ERR(sclk)) 226 + panic(pr_fmt("Unable to get slow clock\n")); 227 + 228 + clk_prepare_enable(sclk); 229 + if (ret) 230 + panic(pr_fmt("Could not enable slow clock\n")); 231 + 232 + sclk_rate = clk_get_rate(sclk); 233 + if (!sclk_rate) 234 + panic(pr_fmt("Invalid slow clock rate\n")); 235 + timer_latch = (sclk_rate + HZ / 2) / HZ; 236 + 224 237 /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used 225 238 * directly for the clocksource and all clockevents, after adjusting 226 239 * its prescaler from the 1 Hz default. ··· 242 229 243 230 /* Setup timer clockevent, with minimum of two ticks (important!!) */ 244 231 clkevt.cpumask = cpumask_of(0); 245 - clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK, 232 + clockevents_config_and_register(&clkevt, sclk_rate, 246 233 2, AT91_ST_ALMV); 247 234 248 235 /* register clocksource */ 249 - clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK); 236 + clocksource_register_hz(&clk32k, sclk_rate); 250 237 } 251 238 CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st", 252 239 atmel_st_timer_init);