aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clocksource/timer-atmel-st.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/drivers/clocksource/timer-atmel-st.c b/drivers/clocksource/timer-atmel-st.c
index 41b7b6dc1d0d..29d21d68df5a 100644
--- a/drivers/clocksource/timer-atmel-st.c
+++ b/drivers/clocksource/timer-atmel-st.c
@@ -22,6 +22,7 @@
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/irq.h> 24#include <linux/irq.h>
25#include <linux/clk.h>
25#include <linux/clockchips.h> 26#include <linux/clockchips.h>
26#include <linux/export.h> 27#include <linux/export.h>
27#include <linux/mfd/syscon.h> 28#include <linux/mfd/syscon.h>
@@ -33,9 +34,7 @@ static unsigned long last_crtr;
33static u32 irqmask; 34static u32 irqmask;
34static struct clock_event_device clkevt; 35static struct clock_event_device clkevt;
35static struct regmap *regmap_st; 36static struct regmap *regmap_st;
36 37static int timer_latch;
37#define AT91_SLOW_CLOCK 32768
38#define RM9200_TIMER_LATCH ((AT91_SLOW_CLOCK + HZ/2) / HZ)
39 38
40/* 39/*
41 * The ST_CRTR is updated asynchronously to the master clock ... but 40 * The ST_CRTR is updated asynchronously to the master clock ... but
@@ -82,8 +81,8 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
82 if (sr & AT91_ST_PITS) { 81 if (sr & AT91_ST_PITS) {
83 u32 crtr = read_CRTR(); 82 u32 crtr = read_CRTR();
84 83
85 while (((crtr - last_crtr) & AT91_ST_CRTV) >= RM9200_TIMER_LATCH) { 84 while (((crtr - last_crtr) & AT91_ST_CRTV) >= timer_latch) {
86 last_crtr += RM9200_TIMER_LATCH; 85 last_crtr += timer_latch;
87 clkevt.event_handler(&clkevt); 86 clkevt.event_handler(&clkevt);
88 } 87 }
89 return IRQ_HANDLED; 88 return IRQ_HANDLED;
@@ -144,7 +143,7 @@ static int clkevt32k_set_periodic(struct clock_event_device *dev)
144 143
145 /* PIT for periodic irqs; fixed rate of 1/HZ */ 144 /* PIT for periodic irqs; fixed rate of 1/HZ */
146 irqmask = AT91_ST_PITS; 145 irqmask = AT91_ST_PITS;
147 regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH); 146 regmap_write(regmap_st, AT91_ST_PIMR, timer_latch);
148 regmap_write(regmap_st, AT91_ST_IER, irqmask); 147 regmap_write(regmap_st, AT91_ST_IER, irqmask);
149 return 0; 148 return 0;
150} 149}
@@ -197,7 +196,8 @@ static struct clock_event_device clkevt = {
197 */ 196 */
198static void __init atmel_st_timer_init(struct device_node *node) 197static void __init atmel_st_timer_init(struct device_node *node)
199{ 198{
200 unsigned int val; 199 struct clk *sclk;
200 unsigned int sclk_rate, val;
201 int irq, ret; 201 int irq, ret;
202 202
203 regmap_st = syscon_node_to_regmap(node); 203 regmap_st = syscon_node_to_regmap(node);
@@ -221,6 +221,19 @@ static void __init atmel_st_timer_init(struct device_node *node)
221 if (ret) 221 if (ret)
222 panic(pr_fmt("Unable to setup IRQ\n")); 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 /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used 237 /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
225 * directly for the clocksource and all clockevents, after adjusting 238 * directly for the clocksource and all clockevents, after adjusting
226 * its prescaler from the 1 Hz default. 239 * its prescaler from the 1 Hz default.
@@ -229,11 +242,11 @@ static void __init atmel_st_timer_init(struct device_node *node)
229 242
230 /* Setup timer clockevent, with minimum of two ticks (important!!) */ 243 /* Setup timer clockevent, with minimum of two ticks (important!!) */
231 clkevt.cpumask = cpumask_of(0); 244 clkevt.cpumask = cpumask_of(0);
232 clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK, 245 clockevents_config_and_register(&clkevt, sclk_rate,
233 2, AT91_ST_ALMV); 246 2, AT91_ST_ALMV);
234 247
235 /* register clocksource */ 248 /* register clocksource */
236 clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK); 249 clocksource_register_hz(&clk32k, sclk_rate);
237} 250}
238CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st", 251CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",
239 atmel_st_timer_init); 252 atmel_st_timer_init);