diff options
Diffstat (limited to 'arch/arm/mach-footbridge/dc21285-timer.c')
| -rw-r--r-- | arch/arm/mach-footbridge/dc21285-timer.c | 46 | 
1 files changed, 41 insertions, 5 deletions
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index 9ee78f7b499..bf7aa7d298e 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -9,6 +9,7 @@  #include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/irq.h> +#include <linux/sched_clock.h>  #include <asm/irq.h> @@ -46,6 +47,16 @@ static struct clocksource cksrc_dc21285 = {  	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,  }; +static int ckevt_dc21285_set_next_event(unsigned long delta, +	struct clock_event_device *c) +{ +	*CSR_TIMER1_CLR = 0; +	*CSR_TIMER1_LOAD = delta; +	*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16; + +	return 0; +} +  static void ckevt_dc21285_set_mode(enum clock_event_mode mode,  	struct clock_event_device *c)  { @@ -58,7 +69,9 @@ static void ckevt_dc21285_set_mode(enum clock_event_mode mode,  				   TIMER_CNTL_DIV16;  		break; -	default: +	case CLOCK_EVT_MODE_ONESHOT: +	case CLOCK_EVT_MODE_UNUSED: +	case CLOCK_EVT_MODE_SHUTDOWN:  		*CSR_TIMER1_CNTL = 0;  		break;  	} @@ -66,9 +79,11 @@ static void ckevt_dc21285_set_mode(enum clock_event_mode mode,  static struct clock_event_device ckevt_dc21285 = {  	.name		= "dc21285_timer1", -	.features	= CLOCK_EVT_FEAT_PERIODIC, +	.features	= CLOCK_EVT_FEAT_PERIODIC | +			  CLOCK_EVT_FEAT_ONESHOT,  	.rating		= 200,  	.irq		= IRQ_TIMER1, +	.set_next_event	= ckevt_dc21285_set_next_event,  	.set_mode	= ckevt_dc21285_set_mode,  }; @@ -78,6 +93,10 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)  	*CSR_TIMER1_CLR = 0; +	/* Stop the timer if in one-shot mode */ +	if (ce->mode == CLOCK_EVT_MODE_ONESHOT) +		*CSR_TIMER1_CNTL = 0; +  	ce->event_handler(ce);  	return IRQ_HANDLED; @@ -86,7 +105,7 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)  static struct irqaction footbridge_timer_irq = {  	.name		= "dc21285_timer1",  	.handler	= timer1_interrupt, -	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, +	.flags		= IRQF_TIMER | IRQF_IRQPOLL,  	.dev_id		= &ckevt_dc21285,  }; @@ -96,11 +115,28 @@ static struct irqaction footbridge_timer_irq = {  void __init footbridge_timer_init(void)  {  	struct clock_event_device *ce = &ckevt_dc21285; +	unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16); -	clocksource_register_hz(&cksrc_dc21285, (mem_fclk_21285 + 8) / 16); +	clocksource_register_hz(&cksrc_dc21285, rate);  	setup_irq(ce->irq, &footbridge_timer_irq);  	ce->cpumask = cpumask_of(smp_processor_id()); -	clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff); +	clockevents_config_and_register(ce, rate, 0x4, 0xffffff); +} + +static u64 notrace footbridge_read_sched_clock(void) +{ +	return ~*CSR_TIMER3_VALUE; +} + +void __init footbridge_sched_clock(void) +{ +	unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16); + +	*CSR_TIMER3_LOAD = 0; +	*CSR_TIMER3_CLR = 0; +	*CSR_TIMER3_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16; + +	sched_clock_register(footbridge_read_sched_clock, 24, rate);  }  | 
