2005-04-17 02:20:36 +04:00
/*
* linux / arch / arm / common / time - acorn . c
*
* Copyright ( c ) 1996 - 2000 Russell King .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* Changelog :
* 24 - Sep - 1996 RMK Created
* 10 - Oct - 1996 RMK Brought up to date with arch - sa110eval
* 04 - Dec - 1997 RMK Updated for new arch / arm / time . c
* 13 = Jun - 2004 DS Moved to arch / arm / common b / c shared w / CLPS7500
*/
# include <linux/timex.h>
# include <linux/init.h>
# include <linux/interrupt.h>
2006-07-02 01:32:14 +04:00
# include <linux/irq.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2005-04-17 02:20:36 +04:00
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2005-04-17 02:20:36 +04:00
# include <asm/hardware/ioc.h>
# include <asm/mach/time.h>
2012-11-08 22:51:58 +04:00
static u32 ioc_timer_gettimeoffset ( void )
2005-04-17 02:20:36 +04:00
{
unsigned int count1 , count2 , status ;
long offset ;
ioc_writeb ( 0 , IOC_T0LATCH ) ;
barrier ( ) ;
count1 = ioc_readb ( IOC_T0CNTL ) | ( ioc_readb ( IOC_T0CNTH ) < < 8 ) ;
barrier ( ) ;
status = ioc_readb ( IOC_IRQREQA ) ;
barrier ( ) ;
ioc_writeb ( 0 , IOC_T0LATCH ) ;
barrier ( ) ;
count2 = ioc_readb ( IOC_T0CNTL ) | ( ioc_readb ( IOC_T0CNTH ) < < 8 ) ;
offset = count2 ;
if ( count2 < count1 ) {
/*
* We have not had an interrupt between reading count1
* and count2 .
*/
if ( status & ( 1 < < 5 ) )
offset - = LATCH ;
} else if ( count2 > count1 ) {
/*
* We have just had another interrupt between reading
* count1 and count2 .
*/
offset - = LATCH ;
}
offset = ( LATCH - offset ) * ( tick_nsec / 1000 ) ;
2012-11-08 22:51:58 +04:00
return ( ( offset + LATCH / 2 ) / LATCH ) * 1000 ;
2005-04-17 02:20:36 +04:00
}
void __init ioctime_init ( void )
{
ioc_writeb ( LATCH & 255 , IOC_T0LTCHL ) ;
ioc_writeb ( LATCH > > 8 , IOC_T0LTCHH ) ;
ioc_writeb ( 0 , IOC_T0GO ) ;
}
static irqreturn_t
2006-10-06 21:53:39 +04:00
ioc_timer_interrupt ( int irq , void * dev_id )
2005-04-17 02:20:36 +04:00
{
2006-10-06 21:53:39 +04:00
timer_tick ( ) ;
2005-04-17 02:20:36 +04:00
return IRQ_HANDLED ;
}
static struct irqaction ioc_timer_irq = {
. name = " timer " ,
2006-07-03 04:20:05 +04:00
. flags = IRQF_DISABLED ,
2005-04-17 02:20:36 +04:00
. handler = ioc_timer_interrupt
} ;
/*
* Set up timer interrupt .
*/
2012-11-08 23:40:59 +04:00
void __init ioc_timer_init ( void )
2005-04-17 02:20:36 +04:00
{
2012-11-08 22:51:58 +04:00
arch_gettimeoffset = ioc_timer_gettimeoffset ;
2005-04-17 02:20:36 +04:00
ioctime_init ( ) ;
2012-03-01 20:55:44 +04:00
setup_irq ( IRQ_TIMER0 , & ioc_timer_irq ) ;
2005-04-17 02:20:36 +04:00
}