diff options
Diffstat (limited to 'drivers/clocksource/timer-atmel-st.c')
| -rw-r--r-- | drivers/clocksource/timer-atmel-st.c | 31 | 
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 @@  #include <linux/kernel.h>  #include <linux/interrupt.h>  #include <linux/irq.h> +#include <linux/clk.h>  #include <linux/clockchips.h>  #include <linux/export.h>  #include <linux/mfd/syscon.h> @@ -33,9 +34,7 @@ static unsigned long last_crtr;  static u32 irqmask;  static struct clock_event_device clkevt;  static struct regmap *regmap_st; - -#define AT91_SLOW_CLOCK		32768 -#define RM9200_TIMER_LATCH	((AT91_SLOW_CLOCK + HZ/2) / HZ) +static int timer_latch;  /*   * 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)  	if (sr & AT91_ST_PITS) {  		u32	crtr = read_CRTR(); -		while (((crtr - last_crtr) & AT91_ST_CRTV) >= RM9200_TIMER_LATCH) { -			last_crtr += RM9200_TIMER_LATCH; +		while (((crtr - last_crtr) & AT91_ST_CRTV) >= timer_latch) { +			last_crtr += timer_latch;  			clkevt.event_handler(&clkevt);  		}  		return IRQ_HANDLED; @@ -144,7 +143,7 @@ static int clkevt32k_set_periodic(struct clock_event_device *dev)  	/* PIT for periodic irqs; fixed rate of 1/HZ */  	irqmask = AT91_ST_PITS; -	regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH); +	regmap_write(regmap_st, AT91_ST_PIMR, timer_latch);  	regmap_write(regmap_st, AT91_ST_IER, irqmask);  	return 0;  } @@ -197,7 +196,8 @@ static struct clock_event_device clkevt = {   */  static void __init atmel_st_timer_init(struct device_node *node)  { -	unsigned int val; +	struct clk *sclk; +	unsigned int sclk_rate, val;  	int irq, ret;  	regmap_st = syscon_node_to_regmap(node); @@ -221,6 +221,19 @@ static void __init atmel_st_timer_init(struct device_node *node)  	if (ret)  		panic(pr_fmt("Unable to setup IRQ\n")); +	sclk = of_clk_get(node, 0); +	if (IS_ERR(sclk)) +		panic(pr_fmt("Unable to get slow clock\n")); + +	clk_prepare_enable(sclk); +	if (ret) +		panic(pr_fmt("Could not enable slow clock\n")); + +	sclk_rate = clk_get_rate(sclk); +	if (!sclk_rate) +		panic(pr_fmt("Invalid slow clock rate\n")); +	timer_latch = (sclk_rate + HZ / 2) / HZ; +  	/* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used  	 * directly for the clocksource and all clockevents, after adjusting  	 * its prescaler from the 1 Hz default. @@ -229,11 +242,11 @@ static void __init atmel_st_timer_init(struct device_node *node)  	/* Setup timer clockevent, with minimum of two ticks (important!!) */  	clkevt.cpumask = cpumask_of(0); -	clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK, +	clockevents_config_and_register(&clkevt, sclk_rate,  					2, AT91_ST_ALMV);  	/* register clocksource */ -	clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK); +	clocksource_register_hz(&clk32k, sclk_rate);  }  CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",  		       atmel_st_timer_init); | 
