124e8bee5SAlison Wang /* 224e8bee5SAlison Wang * Copyright 2013 Freescale Semiconductor, Inc. 324e8bee5SAlison Wang * 4*1a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 524e8bee5SAlison Wang */ 624e8bee5SAlison Wang 724e8bee5SAlison Wang #include <common.h> 824e8bee5SAlison Wang #include <asm/io.h> 924e8bee5SAlison Wang #include <div64.h> 1024e8bee5SAlison Wang #include <asm/arch/imx-regs.h> 1124e8bee5SAlison Wang #include <asm/arch/clock.h> 1224e8bee5SAlison Wang 1324e8bee5SAlison Wang static struct pit_reg *cur_pit = (struct pit_reg *)PIT_BASE_ADDR; 1424e8bee5SAlison Wang 1524e8bee5SAlison Wang DECLARE_GLOBAL_DATA_PTR; 1624e8bee5SAlison Wang 1724e8bee5SAlison Wang #define TIMER_LOAD_VAL 0xffffffff 1824e8bee5SAlison Wang tick_to_time(unsigned long long tick)1924e8bee5SAlison Wangstatic inline unsigned long long tick_to_time(unsigned long long tick) 2024e8bee5SAlison Wang { 2124e8bee5SAlison Wang tick *= CONFIG_SYS_HZ; 2224e8bee5SAlison Wang do_div(tick, mxc_get_clock(MXC_IPG_CLK)); 2324e8bee5SAlison Wang 2424e8bee5SAlison Wang return tick; 2524e8bee5SAlison Wang } 2624e8bee5SAlison Wang us_to_tick(unsigned long long usec)2724e8bee5SAlison Wangstatic inline unsigned long long us_to_tick(unsigned long long usec) 2824e8bee5SAlison Wang { 2924e8bee5SAlison Wang usec = usec * mxc_get_clock(MXC_IPG_CLK) + 999999; 3024e8bee5SAlison Wang do_div(usec, 1000000); 3124e8bee5SAlison Wang 3224e8bee5SAlison Wang return usec; 3324e8bee5SAlison Wang } 3424e8bee5SAlison Wang timer_init(void)3524e8bee5SAlison Wangint timer_init(void) 3624e8bee5SAlison Wang { 3724e8bee5SAlison Wang __raw_writel(0, &cur_pit->mcr); 3824e8bee5SAlison Wang 3924e8bee5SAlison Wang __raw_writel(TIMER_LOAD_VAL, &cur_pit->ldval1); 4024e8bee5SAlison Wang __raw_writel(0, &cur_pit->tctrl1); 4124e8bee5SAlison Wang __raw_writel(1, &cur_pit->tctrl1); 4224e8bee5SAlison Wang 4324e8bee5SAlison Wang gd->arch.tbl = 0; 4424e8bee5SAlison Wang gd->arch.tbu = 0; 4524e8bee5SAlison Wang 4624e8bee5SAlison Wang return 0; 4724e8bee5SAlison Wang } 4824e8bee5SAlison Wang get_ticks(void)4924e8bee5SAlison Wangunsigned long long get_ticks(void) 5024e8bee5SAlison Wang { 5124e8bee5SAlison Wang ulong now = TIMER_LOAD_VAL - __raw_readl(&cur_pit->cval1); 5224e8bee5SAlison Wang 5324e8bee5SAlison Wang /* increment tbu if tbl has rolled over */ 5424e8bee5SAlison Wang if (now < gd->arch.tbl) 5524e8bee5SAlison Wang gd->arch.tbu++; 5624e8bee5SAlison Wang gd->arch.tbl = now; 5724e8bee5SAlison Wang 5824e8bee5SAlison Wang return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl; 5924e8bee5SAlison Wang } 6024e8bee5SAlison Wang get_timer_masked(void)6124e8bee5SAlison Wangulong get_timer_masked(void) 6224e8bee5SAlison Wang { 6324e8bee5SAlison Wang return tick_to_time(get_ticks()); 6424e8bee5SAlison Wang } 6524e8bee5SAlison Wang get_timer(ulong base)6624e8bee5SAlison Wangulong get_timer(ulong base) 6724e8bee5SAlison Wang { 6824e8bee5SAlison Wang return get_timer_masked() - base; 6924e8bee5SAlison Wang } 7024e8bee5SAlison Wang 7124e8bee5SAlison Wang /* delay x useconds AND preserve advance timstamp value */ __udelay(unsigned long usec)7224e8bee5SAlison Wangvoid __udelay(unsigned long usec) 7324e8bee5SAlison Wang { 7424e8bee5SAlison Wang unsigned long long start; 7524e8bee5SAlison Wang ulong tmo; 7624e8bee5SAlison Wang 7724e8bee5SAlison Wang start = get_ticks(); /* get current timestamp */ 7824e8bee5SAlison Wang tmo = us_to_tick(usec); /* convert usecs to ticks */ 7924e8bee5SAlison Wang while ((get_ticks() - start) < tmo) 8024e8bee5SAlison Wang ; /* loop till time has passed */ 8124e8bee5SAlison Wang } 8224e8bee5SAlison Wang 8324e8bee5SAlison Wang /* 8424e8bee5SAlison Wang * This function is derived from PowerPC code (timebase clock frequency). 8524e8bee5SAlison Wang * On ARM it returns the number of timer ticks per second. 8624e8bee5SAlison Wang */ get_tbclk(void)8724e8bee5SAlison Wangulong get_tbclk(void) 8824e8bee5SAlison Wang { 8924e8bee5SAlison Wang return mxc_get_clock(MXC_IPG_CLK); 9024e8bee5SAlison Wang } 91