2005-04-16 15:20:36 -07:00
/*
* linux / arch / arm / mach - footbridge / dc21285 - timer . c
*
* Copyright ( C ) 1998 Russell King .
* Copyright ( C ) 1998 Phil Blundell
*/
2011-01-28 21:00:39 +00:00
# include <linux/clockchips.h>
# include <linux/clocksource.h>
2005-04-16 15:20:36 -07:00
# include <linux/init.h>
# include <linux/interrupt.h>
2006-07-01 22:32:17 +01:00
# include <linux/irq.h>
2013-11-29 01:03:35 +00:00
# include <linux/sched_clock.h>
2005-04-16 15:20:36 -07:00
# include <asm/irq.h>
# include <asm/hardware/dec21285.h>
# include <asm/mach/time.h>
2012-03-28 18:30:01 +01:00
# include <asm/system_info.h>
2005-04-16 15:20:36 -07:00
# include "common.h"
2011-01-28 21:00:39 +00:00
static cycle_t cksrc_dc21285_read ( struct clocksource * cs )
{
return cs - > mask - * CSR_TIMER2_VALUE ;
}
2005-04-16 15:20:36 -07:00
2011-01-28 21:00:39 +00:00
static int cksrc_dc21285_enable ( struct clocksource * cs )
2005-04-16 15:20:36 -07:00
{
2011-01-28 21:00:39 +00:00
* CSR_TIMER2_LOAD = cs - > mask ;
* CSR_TIMER2_CLR = 0 ;
* CSR_TIMER2_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16 ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
2011-03-28 11:25:40 +02:00
static void cksrc_dc21285_disable ( struct clocksource * cs )
2011-01-28 21:00:39 +00:00
{
* CSR_TIMER2_CNTL = 0 ;
2005-04-16 15:20:36 -07:00
}
2011-01-28 21:00:39 +00:00
static struct clocksource cksrc_dc21285 = {
. name = " dc21285_timer2 " ,
. rating = 200 ,
. read = cksrc_dc21285_read ,
. enable = cksrc_dc21285_enable ,
. disable = cksrc_dc21285_disable ,
. mask = CLOCKSOURCE_MASK ( 24 ) ,
. flags = CLOCK_SOURCE_IS_CONTINUOUS ,
} ;
2013-11-30 12:21:21 +00:00
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 ;
}
2011-01-28 21:00:39 +00:00
static void ckevt_dc21285_set_mode ( enum clock_event_mode mode ,
struct clock_event_device * c )
2005-04-16 15:20:36 -07:00
{
2011-01-28 21:00:39 +00:00
switch ( mode ) {
case CLOCK_EVT_MODE_RESUME :
case CLOCK_EVT_MODE_PERIODIC :
* CSR_TIMER1_CLR = 0 ;
* CSR_TIMER1_LOAD = ( mem_fclk_21285 + 8 * HZ ) / ( 16 * HZ ) ;
* CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD |
TIMER_CNTL_DIV16 ;
break ;
2013-11-30 12:21:21 +00:00
case CLOCK_EVT_MODE_ONESHOT :
case CLOCK_EVT_MODE_UNUSED :
case CLOCK_EVT_MODE_SHUTDOWN :
2011-01-28 21:00:39 +00:00
* CSR_TIMER1_CNTL = 0 ;
break ;
}
}
static struct clock_event_device ckevt_dc21285 = {
. name = " dc21285_timer1 " ,
2013-11-30 12:21:21 +00:00
. features = CLOCK_EVT_FEAT_PERIODIC |
CLOCK_EVT_FEAT_ONESHOT ,
2011-01-28 21:00:39 +00:00
. rating = 200 ,
. irq = IRQ_TIMER1 ,
2013-11-30 12:21:21 +00:00
. set_next_event = ckevt_dc21285_set_next_event ,
2011-01-28 21:00:39 +00:00
. set_mode = ckevt_dc21285_set_mode ,
} ;
static irqreturn_t timer1_interrupt ( int irq , void * dev_id )
{
struct clock_event_device * ce = dev_id ;
2005-04-16 15:20:36 -07:00
* CSR_TIMER1_CLR = 0 ;
2013-11-30 12:21:21 +00:00
/* Stop the timer if in one-shot mode */
if ( ce - > mode = = CLOCK_EVT_MODE_ONESHOT )
* CSR_TIMER1_CNTL = 0 ;
2011-01-28 21:00:39 +00:00
ce - > event_handler ( ce ) ;
2005-04-16 15:20:36 -07:00
return IRQ_HANDLED ;
}
static struct irqaction footbridge_timer_irq = {
2011-01-28 21:00:39 +00:00
. name = " dc21285_timer1 " ,
2005-04-16 15:20:36 -07:00
. handler = timer1_interrupt ,
2014-03-04 21:45:48 +01:00
. flags = IRQF_TIMER | IRQF_IRQPOLL ,
2011-01-28 21:00:39 +00:00
. dev_id = & ckevt_dc21285 ,
2005-04-16 15:20:36 -07:00
} ;
/*
* Set up timer interrupt .
*/
2012-11-08 12:40:59 -07:00
void __init footbridge_timer_init ( void )
2005-04-16 15:20:36 -07:00
{
2011-01-28 21:00:39 +00:00
struct clock_event_device * ce = & ckevt_dc21285 ;
2013-12-29 12:39:50 +00:00
unsigned rate = DIV_ROUND_CLOSEST ( mem_fclk_21285 , 16 ) ;
2011-01-28 21:00:39 +00:00
2013-12-29 12:39:50 +00:00
clocksource_register_hz ( & cksrc_dc21285 , rate ) ;
2011-01-28 21:00:39 +00:00
setup_irq ( ce - > irq , & footbridge_timer_irq ) ;
2005-04-16 15:20:36 -07:00
2011-06-11 00:46:17 +01:00
ce - > cpumask = cpumask_of ( smp_processor_id ( ) ) ;
2013-12-29 12:39:50 +00:00
clockevents_config_and_register ( ce , rate , 0x4 , 0xffffff ) ;
2005-04-16 15:20:36 -07:00
}
2013-11-29 01:03:35 +00:00
2014-01-17 20:42:48 +01:00
static u64 notrace footbridge_read_sched_clock ( void )
2013-11-29 01:03:35 +00:00
{
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 ;
2014-01-17 20:42:48 +01:00
sched_clock_register ( footbridge_read_sched_clock , 24 , rate ) ;
2005-04-16 15:20:36 -07:00
}