2005-11-10 17:26:51 +03:00
/*
* linux / arch / arm / mach - omap2 / timer - gp . c
*
* OMAP2 GP timer support .
*
* Copyright ( C ) 2005 Nokia Corporation
* Author : Paul Mundt < paul . mundt @ nokia . com >
* Juha Yrj <EFBFBD> l <EFBFBD> < juha . yrjola @ nokia . com >
2006-06-27 03:16:12 +04:00
* OMAP Dual - mode timer framework support by Timo Teras
2005-11-10 17:26:51 +03:00
*
* Some parts based off of TI ' s 24 xx code :
*
* Copyright ( C ) 2004 Texas Instruments , Inc .
*
* Roughly modelled after the OMAP1 MPU timer code .
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*/
# include <linux/init.h>
# include <linux/time.h>
# include <linux/interrupt.h>
# include <linux/err.h>
2006-01-07 19:15:52 +03:00
# include <linux/clk.h>
2006-06-27 03:16:12 +04:00
# include <linux/delay.h>
2006-12-07 04:14:00 +03:00
# include <linux/irq.h>
2006-01-07 19:15:52 +03:00
2005-11-10 17:26:51 +03:00
# include <asm/mach/time.h>
2006-06-27 03:16:12 +04:00
# include <asm/arch/dmtimer.h>
2005-11-10 17:26:51 +03:00
2006-06-27 03:16:12 +04:00
static struct omap_dm_timer * gptimer ;
2005-11-10 17:26:51 +03:00
2006-06-27 03:16:12 +04:00
static inline void omap2_gp_timer_start ( unsigned long load_val )
2005-11-10 17:26:51 +03:00
{
2006-06-27 03:16:12 +04:00
omap_dm_timer_set_load ( gptimer , 1 , 0xffffffff - load_val ) ;
omap_dm_timer_set_int_enable ( gptimer , OMAP_TIMER_INT_OVERFLOW ) ;
omap_dm_timer_start ( gptimer ) ;
2005-11-10 17:26:51 +03:00
}
2006-10-06 21:53:39 +04:00
static irqreturn_t omap2_gp_timer_interrupt ( int irq , void * dev_id )
2005-11-10 17:26:51 +03:00
{
write_seqlock ( & xtime_lock ) ;
2006-06-27 03:16:12 +04:00
omap_dm_timer_write_status ( gptimer , OMAP_TIMER_INT_OVERFLOW ) ;
2006-10-06 21:53:39 +04:00
timer_tick ( ) ;
2005-11-10 17:26:51 +03:00
write_sequnlock ( & xtime_lock ) ;
return IRQ_HANDLED ;
}
static struct irqaction omap2_gp_timer_irq = {
. name = " gp timer " ,
2007-05-08 11:35:39 +04:00
. flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL ,
2005-11-10 17:26:51 +03:00
. handler = omap2_gp_timer_interrupt ,
} ;
static void __init omap2_gp_timer_init ( void )
{
2006-06-27 03:16:12 +04:00
u32 tick_period ;
2005-11-10 17:26:51 +03:00
2006-06-27 03:16:12 +04:00
omap_dm_timer_init ( ) ;
2006-06-27 03:16:13 +04:00
gptimer = omap_dm_timer_request_specific ( 1 ) ;
2006-06-27 03:16:12 +04:00
BUG_ON ( gptimer = = NULL ) ;
2005-11-10 17:26:51 +03:00
2006-06-27 03:16:12 +04:00
omap_dm_timer_set_source ( gptimer , OMAP_TIMER_SRC_SYS_CLK ) ;
2006-12-07 04:14:04 +03:00
tick_period = clk_get_rate ( omap_dm_timer_get_fclk ( gptimer ) ) / HZ ;
2005-11-10 17:26:51 +03:00
tick_period - = 1 ;
2006-06-27 03:16:12 +04:00
setup_irq ( omap_dm_timer_get_irq ( gptimer ) , & omap2_gp_timer_irq ) ;
omap2_gp_timer_start ( tick_period ) ;
2005-11-10 17:26:51 +03:00
}
struct sys_timer omap_timer = {
. init = omap2_gp_timer_init ,
} ;