2007-10-21 19:37:54 +04:00
/*
2008-02-25 10:06:07 +03:00
* gptimers . c - Blackfin General Purpose Timer core API
2007-10-21 19:37:54 +04:00
*
2008-02-25 10:06:07 +03:00
* Copyright ( c ) 2005 - 2008 Analog Devices Inc .
* Copyright ( C ) 2005 John DeHority
* Copyright ( C ) 2006 Hella Aglaia GmbH ( awe @ aglaia - gmbh . de )
2007-10-21 19:37:54 +04:00
*
* Licensed under the GPLv2 .
*/
# include <linux/kernel.h>
# include <linux/module.h>
2008-05-20 12:42:39 +04:00
# include <linux/io.h>
2007-10-21 19:37:54 +04:00
# include <asm/blackfin.h>
# include <asm/gptimers.h>
# ifdef DEBUG
# define tassert(expr)
# else
# define tassert(expr) \
if ( ! ( expr ) ) \
2007-10-29 13:02:09 +03:00
printk ( KERN_DEBUG " %s:%s:%i: Assertion failed: " # expr " \n " , __FILE__ , __func__ , __LINE__ ) ;
2007-10-21 19:37:54 +04:00
# endif
2012-05-16 14:11:10 +04:00
# ifndef CONFIG_BF60x
# define BFIN_TIMER_NUM_GROUP (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1)
# else
# define BFIN_TIMER_NUM_GROUP 1
# endif
2007-10-21 19:37:54 +04:00
2011-06-16 00:53:48 +04:00
static struct bfin_gptimer_regs * const timer_regs [ MAX_BLACKFIN_GPTIMERS ] =
2007-10-21 19:37:54 +04:00
{
2011-06-16 00:53:48 +04:00
( void * ) TIMER0_CONFIG ,
( void * ) TIMER1_CONFIG ,
( void * ) TIMER2_CONFIG ,
2007-10-21 19:37:54 +04:00
# if (MAX_BLACKFIN_GPTIMERS > 3)
2011-06-16 00:53:48 +04:00
( void * ) TIMER3_CONFIG ,
( void * ) TIMER4_CONFIG ,
( void * ) TIMER5_CONFIG ,
( void * ) TIMER6_CONFIG ,
( void * ) TIMER7_CONFIG ,
2008-04-23 04:53:15 +04:00
# if (MAX_BLACKFIN_GPTIMERS > 8)
2011-06-16 00:53:48 +04:00
( void * ) TIMER8_CONFIG ,
( void * ) TIMER9_CONFIG ,
( void * ) TIMER10_CONFIG ,
2008-04-23 04:53:15 +04:00
# if (MAX_BLACKFIN_GPTIMERS > 11)
2011-06-16 00:53:48 +04:00
( void * ) TIMER11_CONFIG ,
2008-04-23 04:53:15 +04:00
# endif
# endif
2007-10-21 19:37:54 +04:00
# endif
} ;
2011-06-16 00:53:48 +04:00
static struct bfin_gptimer_group_regs * const group_regs [ BFIN_TIMER_NUM_GROUP ] =
2007-10-21 19:37:54 +04:00
{
2011-06-16 00:53:48 +04:00
( void * ) TIMER0_GROUP_REG ,
2007-10-21 19:37:54 +04:00
# if (MAX_BLACKFIN_GPTIMERS > 8)
2011-06-16 00:53:48 +04:00
( void * ) TIMER8_GROUP_REG ,
2007-10-21 19:37:54 +04:00
# endif
} ;
2007-10-29 13:02:09 +03:00
static uint32_t const trun_mask [ MAX_BLACKFIN_GPTIMERS ] =
2007-10-21 19:37:54 +04:00
{
TIMER_STATUS_TRUN0 ,
TIMER_STATUS_TRUN1 ,
TIMER_STATUS_TRUN2 ,
# if (MAX_BLACKFIN_GPTIMERS > 3)
TIMER_STATUS_TRUN3 ,
TIMER_STATUS_TRUN4 ,
TIMER_STATUS_TRUN5 ,
TIMER_STATUS_TRUN6 ,
TIMER_STATUS_TRUN7 ,
2008-04-23 04:53:15 +04:00
# if (MAX_BLACKFIN_GPTIMERS > 8)
2007-10-21 19:37:54 +04:00
TIMER_STATUS_TRUN8 ,
TIMER_STATUS_TRUN9 ,
TIMER_STATUS_TRUN10 ,
2008-04-23 04:53:15 +04:00
# if (MAX_BLACKFIN_GPTIMERS > 11)
2007-10-21 19:37:54 +04:00
TIMER_STATUS_TRUN11 ,
2008-04-23 04:53:15 +04:00
# endif
# endif
2007-10-21 19:37:54 +04:00
# endif
} ;
2007-10-29 13:02:09 +03:00
static uint32_t const tovf_mask [ MAX_BLACKFIN_GPTIMERS ] =
{
TIMER_STATUS_TOVF0 ,
TIMER_STATUS_TOVF1 ,
TIMER_STATUS_TOVF2 ,
# if (MAX_BLACKFIN_GPTIMERS > 3)
TIMER_STATUS_TOVF3 ,
TIMER_STATUS_TOVF4 ,
TIMER_STATUS_TOVF5 ,
TIMER_STATUS_TOVF6 ,
TIMER_STATUS_TOVF7 ,
2008-04-23 04:53:15 +04:00
# if (MAX_BLACKFIN_GPTIMERS > 8)
2007-10-29 13:02:09 +03:00
TIMER_STATUS_TOVF8 ,
TIMER_STATUS_TOVF9 ,
TIMER_STATUS_TOVF10 ,
2008-04-23 04:53:15 +04:00
# if (MAX_BLACKFIN_GPTIMERS > 11)
2007-10-29 13:02:09 +03:00
TIMER_STATUS_TOVF11 ,
2008-04-23 04:53:15 +04:00
# endif
# endif
2007-10-29 13:02:09 +03:00
# endif
} ;
static uint32_t const timil_mask [ MAX_BLACKFIN_GPTIMERS ] =
2007-10-21 19:37:54 +04:00
{
TIMER_STATUS_TIMIL0 ,
TIMER_STATUS_TIMIL1 ,
TIMER_STATUS_TIMIL2 ,
# if (MAX_BLACKFIN_GPTIMERS > 3)
TIMER_STATUS_TIMIL3 ,
TIMER_STATUS_TIMIL4 ,
TIMER_STATUS_TIMIL5 ,
TIMER_STATUS_TIMIL6 ,
TIMER_STATUS_TIMIL7 ,
2008-04-23 04:53:15 +04:00
# if (MAX_BLACKFIN_GPTIMERS > 8)
2007-10-21 19:37:54 +04:00
TIMER_STATUS_TIMIL8 ,
TIMER_STATUS_TIMIL9 ,
TIMER_STATUS_TIMIL10 ,
2008-04-23 04:53:15 +04:00
# if (MAX_BLACKFIN_GPTIMERS > 11)
2007-10-21 19:37:54 +04:00
TIMER_STATUS_TIMIL11 ,
2008-04-23 04:53:15 +04:00
# endif
# endif
2007-10-21 19:37:54 +04:00
# endif
} ;
2009-11-15 10:35:22 +03:00
void set_gptimer_pwidth ( unsigned int timer_id , uint32_t value )
2007-10-21 19:37:54 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
bfin_write ( & timer_regs [ timer_id ] - > width , value ) ;
2007-10-21 19:37:54 +04:00
SSYNC ( ) ;
}
EXPORT_SYMBOL ( set_gptimer_pwidth ) ;
2009-11-15 10:35:22 +03:00
uint32_t get_gptimer_pwidth ( unsigned int timer_id )
2007-10-21 19:37:54 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
return bfin_read ( & timer_regs [ timer_id ] - > width ) ;
2007-10-21 19:37:54 +04:00
}
EXPORT_SYMBOL ( get_gptimer_pwidth ) ;
2009-11-15 10:35:22 +03:00
void set_gptimer_period ( unsigned int timer_id , uint32_t period )
2007-10-21 19:37:54 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
bfin_write ( & timer_regs [ timer_id ] - > period , period ) ;
2007-10-21 19:37:54 +04:00
SSYNC ( ) ;
}
EXPORT_SYMBOL ( set_gptimer_period ) ;
2009-11-15 10:35:22 +03:00
uint32_t get_gptimer_period ( unsigned int timer_id )
2007-10-21 19:37:54 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
return bfin_read ( & timer_regs [ timer_id ] - > period ) ;
2007-10-21 19:37:54 +04:00
}
EXPORT_SYMBOL ( get_gptimer_period ) ;
2009-11-15 10:35:22 +03:00
uint32_t get_gptimer_count ( unsigned int timer_id )
2007-10-21 19:37:54 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
return bfin_read ( & timer_regs [ timer_id ] - > counter ) ;
2007-10-21 19:37:54 +04:00
}
EXPORT_SYMBOL ( get_gptimer_count ) ;
2012-05-16 14:11:10 +04:00
# ifdef CONFIG_BF60x
void set_gptimer_delay ( unsigned int timer_id , uint32_t delay )
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
bfin_write ( & timer_regs [ timer_id ] - > delay , delay ) ;
SSYNC ( ) ;
}
EXPORT_SYMBOL ( set_gptimer_delay ) ;
uint32_t get_gptimer_delay ( unsigned int timer_id )
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
return bfin_read ( & timer_regs [ timer_id ] - > delay ) ;
}
EXPORT_SYMBOL ( get_gptimer_delay ) ;
# endif
# ifdef CONFIG_BF60x
int get_gptimer_intr ( unsigned int timer_id )
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
return ! ! ( bfin_read ( & group_regs [ BFIN_TIMER_OCTET ( timer_id ) ] - > data_ilat ) & timil_mask [ timer_id ] ) ;
}
EXPORT_SYMBOL ( get_gptimer_intr ) ;
void clear_gptimer_intr ( unsigned int timer_id )
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
bfin_write ( & group_regs [ BFIN_TIMER_OCTET ( timer_id ) ] - > data_ilat , timil_mask [ timer_id ] ) ;
}
EXPORT_SYMBOL ( clear_gptimer_intr ) ;
int get_gptimer_over ( unsigned int timer_id )
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
return ! ! ( bfin_read ( & group_regs [ BFIN_TIMER_OCTET ( timer_id ) ] - > stat_ilat ) & tovf_mask [ timer_id ] ) ;
}
EXPORT_SYMBOL ( get_gptimer_over ) ;
void clear_gptimer_over ( unsigned int timer_id )
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
bfin_write ( & group_regs [ BFIN_TIMER_OCTET ( timer_id ) ] - > stat_ilat , tovf_mask [ timer_id ] ) ;
}
EXPORT_SYMBOL ( clear_gptimer_over ) ;
int get_gptimer_run ( unsigned int timer_id )
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
return ! ! ( bfin_read ( & group_regs [ BFIN_TIMER_OCTET ( timer_id ) ] - > run ) & trun_mask [ timer_id ] ) ;
}
EXPORT_SYMBOL ( get_gptimer_run ) ;
uint32_t get_gptimer_status ( unsigned int group )
{
tassert ( group < BFIN_TIMER_NUM_GROUP ) ;
return bfin_read ( & group_regs [ group ] - > data_ilat ) ;
}
EXPORT_SYMBOL ( get_gptimer_status ) ;
void set_gptimer_status ( unsigned int group , uint32_t value )
{
tassert ( group < BFIN_TIMER_NUM_GROUP ) ;
bfin_write ( & group_regs [ group ] - > data_ilat , value ) ;
SSYNC ( ) ;
}
EXPORT_SYMBOL ( set_gptimer_status ) ;
# else
2009-11-15 10:35:22 +03:00
uint32_t get_gptimer_status ( unsigned int group )
2007-10-21 19:37:54 +04:00
{
tassert ( group < BFIN_TIMER_NUM_GROUP ) ;
2011-06-16 00:54:46 +04:00
return bfin_read ( & group_regs [ group ] - > status ) ;
2007-10-21 19:37:54 +04:00
}
EXPORT_SYMBOL ( get_gptimer_status ) ;
2009-11-15 10:35:22 +03:00
void set_gptimer_status ( unsigned int group , uint32_t value )
2007-10-21 19:37:54 +04:00
{
tassert ( group < BFIN_TIMER_NUM_GROUP ) ;
2011-06-16 00:54:46 +04:00
bfin_write ( & group_regs [ group ] - > status , value ) ;
2007-10-21 19:37:54 +04:00
SSYNC ( ) ;
}
EXPORT_SYMBOL ( set_gptimer_status ) ;
2011-06-16 00:54:46 +04:00
static uint32_t read_gptimer_status ( unsigned int timer_id )
{
return bfin_read ( & group_regs [ BFIN_TIMER_OCTET ( timer_id ) ] - > status ) ;
}
2009-11-15 10:35:22 +03:00
int get_gptimer_intr ( unsigned int timer_id )
2007-10-21 19:37:54 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
return ! ! ( read_gptimer_status ( timer_id ) & timil_mask [ timer_id ] ) ;
2007-10-21 19:37:54 +04:00
}
EXPORT_SYMBOL ( get_gptimer_intr ) ;
2009-11-15 10:35:22 +03:00
void clear_gptimer_intr ( unsigned int timer_id )
2007-10-21 19:37:54 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
bfin_write ( & group_regs [ BFIN_TIMER_OCTET ( timer_id ) ] - > status , timil_mask [ timer_id ] ) ;
2007-10-21 19:37:54 +04:00
}
EXPORT_SYMBOL ( clear_gptimer_intr ) ;
2009-11-15 10:35:22 +03:00
int get_gptimer_over ( unsigned int timer_id )
2007-10-29 13:02:09 +03:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
return ! ! ( read_gptimer_status ( timer_id ) & tovf_mask [ timer_id ] ) ;
2007-10-29 13:02:09 +03:00
}
EXPORT_SYMBOL ( get_gptimer_over ) ;
2009-11-15 10:35:22 +03:00
void clear_gptimer_over ( unsigned int timer_id )
2007-10-29 13:02:09 +03:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
bfin_write ( & group_regs [ BFIN_TIMER_OCTET ( timer_id ) ] - > status , tovf_mask [ timer_id ] ) ;
2007-10-29 13:02:09 +03:00
}
EXPORT_SYMBOL ( clear_gptimer_over ) ;
2009-11-15 10:35:22 +03:00
int get_gptimer_run ( unsigned int timer_id )
2009-05-04 13:11:37 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
return ! ! ( read_gptimer_status ( timer_id ) & trun_mask [ timer_id ] ) ;
2009-05-04 13:11:37 +04:00
}
EXPORT_SYMBOL ( get_gptimer_run ) ;
2012-05-16 14:11:10 +04:00
# endif
2009-05-04 13:11:37 +04:00
2009-11-15 10:35:22 +03:00
void set_gptimer_config ( unsigned int timer_id , uint16_t config )
2007-10-21 19:37:54 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
bfin_write ( & timer_regs [ timer_id ] - > config , config ) ;
2007-10-21 19:37:54 +04:00
SSYNC ( ) ;
}
EXPORT_SYMBOL ( set_gptimer_config ) ;
2009-11-15 10:35:22 +03:00
uint16_t get_gptimer_config ( unsigned int timer_id )
2007-10-21 19:37:54 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
return bfin_read ( & timer_regs [ timer_id ] - > config ) ;
2007-10-21 19:37:54 +04:00
}
EXPORT_SYMBOL ( get_gptimer_config ) ;
void enable_gptimers ( uint16_t mask )
{
int i ;
2012-05-16 14:11:10 +04:00
# ifdef CONFIG_BF60x
uint16_t imask ;
imask = bfin_read16 ( TIMER_DATA_IMSK ) ;
imask & = ~ mask ;
bfin_write16 ( TIMER_DATA_IMSK , imask ) ;
# endif
2007-10-21 19:37:54 +04:00
tassert ( ( mask & ~ BLACKFIN_GPTIMER_IDMASK ) = = 0 ) ;
for ( i = 0 ; i < BFIN_TIMER_NUM_GROUP ; + + i ) {
2011-06-16 00:54:46 +04:00
bfin_write ( & group_regs [ i ] - > enable , mask & 0xFF ) ;
2007-10-21 19:37:54 +04:00
mask > > = 8 ;
}
SSYNC ( ) ;
}
EXPORT_SYMBOL ( enable_gptimers ) ;
2009-05-04 13:11:37 +04:00
static void _disable_gptimers ( uint16_t mask )
2007-10-21 19:37:54 +04:00
{
int i ;
uint16_t m = mask ;
tassert ( ( mask & ~ BLACKFIN_GPTIMER_IDMASK ) = = 0 ) ;
for ( i = 0 ; i < BFIN_TIMER_NUM_GROUP ; + + i ) {
2011-06-16 00:54:46 +04:00
bfin_write ( & group_regs [ i ] - > disable , m & 0xFF ) ;
2007-10-21 19:37:54 +04:00
m > > = 8 ;
}
2009-05-04 13:11:37 +04:00
}
void disable_gptimers ( uint16_t mask )
{
2012-05-17 10:21:22 +04:00
# ifndef CONFIG_BF60x
2009-05-04 13:11:37 +04:00
int i ;
_disable_gptimers ( mask ) ;
2007-10-21 19:37:54 +04:00
for ( i = 0 ; i < MAX_BLACKFIN_GPTIMERS ; + + i )
if ( mask & ( 1 < < i ) )
2011-06-16 00:54:46 +04:00
bfin_write ( & group_regs [ BFIN_TIMER_OCTET ( i ) ] - > status , trun_mask [ i ] ) ;
2007-10-21 19:37:54 +04:00
SSYNC ( ) ;
2012-05-17 10:21:22 +04:00
# else
_disable_gptimers ( mask ) ;
2012-05-16 14:11:10 +04:00
# endif
2007-10-21 19:37:54 +04:00
}
EXPORT_SYMBOL ( disable_gptimers ) ;
2009-05-04 13:11:37 +04:00
void disable_gptimers_sync ( uint16_t mask )
{
_disable_gptimers ( mask ) ;
SSYNC ( ) ;
}
EXPORT_SYMBOL ( disable_gptimers_sync ) ;
2009-11-15 10:35:22 +03:00
void set_gptimer_pulse_hi ( unsigned int timer_id )
2007-10-21 19:37:54 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
bfin_write_or ( & timer_regs [ timer_id ] - > config , TIMER_PULSE_HI ) ;
2007-10-21 19:37:54 +04:00
SSYNC ( ) ;
}
EXPORT_SYMBOL ( set_gptimer_pulse_hi ) ;
2009-11-15 10:35:22 +03:00
void clear_gptimer_pulse_hi ( unsigned int timer_id )
2007-10-21 19:37:54 +04:00
{
tassert ( timer_id < MAX_BLACKFIN_GPTIMERS ) ;
2011-06-16 00:54:46 +04:00
bfin_write_and ( & timer_regs [ timer_id ] - > config , ~ TIMER_PULSE_HI ) ;
2007-10-21 19:37:54 +04:00
SSYNC ( ) ;
}
EXPORT_SYMBOL ( clear_gptimer_pulse_hi ) ;
uint16_t get_enabled_gptimers ( void )
{
int i ;
uint16_t result = 0 ;
for ( i = 0 ; i < BFIN_TIMER_NUM_GROUP ; + + i )
2011-06-16 00:54:46 +04:00
result | = ( bfin_read ( & group_regs [ i ] - > enable ) < < ( i < < 3 ) ) ;
2007-10-21 19:37:54 +04:00
return result ;
}
EXPORT_SYMBOL ( get_enabled_gptimers ) ;
MODULE_AUTHOR ( " Axel Weiss (awe@aglaia-gmbh.de) " ) ;
MODULE_DESCRIPTION ( " Blackfin General Purpose Timers API " ) ;
MODULE_LICENSE ( " GPL " ) ;