@ -12,6 +12,7 @@
# include <div64.h>
# include <asm/arch/imx-regs.h>
# include <asm/arch/clock.h>
# include <asm/arch/sys_proto.h>
/* General purpose timers registers */
struct mxc_gpt {
@ -26,23 +27,59 @@ static struct mxc_gpt *cur_gpt = (struct mxc_gpt *)GPT1_BASE_ADDR;
/* General purpose timers bitfields */
# define GPTCR_SWR (1 << 15) /* Software reset */
# define GPTCR_24MEN (1 << 10) /* Enable 24MHz clock input */
# define GPTCR_FRR (1 << 9) /* Freerun / restart */
# define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source */
# define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source 32khz */
# define GPTCR_CLKSOURCE_OSC (5 << 6) /* Clock source OSC */
# define GPTCR_CLKSOURCE_PRE (1 << 6) /* Clock source PRECLK */
# define GPTCR_CLKSOURCE_MASK (0x7 << 6)
# define GPTCR_TEN 1 /* Timer enable */
# define GPTPR_PRESCALER24M_SHIFT 12
# define GPTPR_PRESCALER24M_MASK (0xF << GPTPR_PRESCALER24M_SHIFT)
DECLARE_GLOBAL_DATA_PTR ;
static inline int gpt_has_clk_source_osc ( void )
{
# if defined(CONFIG_MX6)
if ( ( ( is_cpu_type ( MXC_CPU_MX6Q ) | | is_cpu_type ( MXC_CPU_MX6D ) ) & &
( is_soc_rev ( CHIP_REV_1_0 ) > 0 ) ) | | is_cpu_type ( MXC_CPU_MX6DL ) | |
is_cpu_type ( MXC_CPU_MX6SOLO ) | | is_cpu_type ( MXC_CPU_MX6SX ) )
return 1 ;
return 0 ;
# else
return 0 ;
# endif
}
static inline ulong gpt_get_clk ( void )
{
# ifdef CONFIG_MXC_GPT_HCLK
if ( gpt_has_clk_source_osc ( ) )
return MXC_HCLK > > 3 ;
else
return mxc_get_clock ( MXC_IPG_PERCLK ) ;
# else
return MXC_CLK32 ;
# endif
}
static inline unsigned long long tick_to_time ( unsigned long long tick )
{
ulong gpt_clk = gpt_get_clk ( ) ;
tick * = CONFIG_SYS_HZ ;
do_div ( tick , MXC_CLK32 ) ;
do_div ( tick , gpt_clk ) ;
return tick ;
}
static inline unsigned long long us_to_tick ( unsigned long long usec )
{
usec = usec * MXC_CLK32 + 999999 ;
ulong gpt_clk = gpt_get_clk ( ) ;
usec = usec * gpt_clk + 999999 ;
do_div ( usec , 1000000 ) ;
return usec ;
@ -59,11 +96,31 @@ int timer_init(void)
for ( i = 0 ; i < 100 ; i + + )
__raw_writel ( 0 , & cur_gpt - > control ) ;
__raw_writel ( 0 , & cur_gpt - > prescaler ) ; /* 32Khz */
/* Freerun Mode, PERCLK1 input */
i = __raw_readl ( & cur_gpt - > control ) ;
__raw_writel ( i | GPTCR_CLKSOURCE_32 | GPTCR_TEN , & cur_gpt - > control ) ;
i & = ~ GPTCR_CLKSOURCE_MASK ;
# ifdef CONFIG_MXC_GPT_HCLK
if ( gpt_has_clk_source_osc ( ) ) {
i | = GPTCR_CLKSOURCE_OSC | GPTCR_TEN ;
/* For DL/S, SX, set 24Mhz OSC Enable bit and prescaler */
if ( is_cpu_type ( MXC_CPU_MX6DL ) | |
is_cpu_type ( MXC_CPU_MX6SOLO ) | |
is_cpu_type ( MXC_CPU_MX6SX ) ) {
i | = GPTCR_24MEN ;
/* Produce 3Mhz clock */
__raw_writel ( ( 7 < < GPTPR_PRESCALER24M_SHIFT ) ,
& cur_gpt - > prescaler ) ;
}
} else {
i | = GPTCR_CLKSOURCE_PRE | GPTCR_TEN ;
}
# else
__raw_writel ( 0 , & cur_gpt - > prescaler ) ; /* 32Khz */
i | = GPTCR_CLKSOURCE_32 | GPTCR_TEN ;
# endif
__raw_writel ( i , & cur_gpt - > control ) ;
gd - > arch . tbl = __raw_readl ( & cur_gpt - > counter ) ;
gd - > arch . tbu = 0 ;
@ -86,7 +143,7 @@ ulong get_timer_masked(void)
{
/*
* get_ticks ( ) returns a long long ( 64 bit ) , it wraps in
* 2 ^ 64 / MXC_CLK32 = 2 ^ 64 / 2 ^ 15 = 2 ^ 49 ~ 5 * 10 ^ 14 ( s ) ~
* 2 ^ 64 / GPT_CLK = 2 ^ 64 / 2 ^ 15 = 2 ^ 49 ~ 5 * 10 ^ 14 ( s ) ~
* 5 * 10 ^ 9 days . . . and get_ticks ( ) * CONFIG_SYS_HZ wraps in
* 5 * 10 ^ 6 days - long enough .
*/
@ -117,5 +174,5 @@ void __udelay(unsigned long usec)
*/
ulong get_tbclk ( void )
{
return MXC_CLK32 ;
return gpt_get_clk ( ) ;
}