*
* (C) Copyright 2009 Freescale Semiconductor, Inc.
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
DECLARE_GLOBAL_DATA_PTR;
-#define timestamp (gd->arch.tbl)
-#define lastinc (gd->lastinc)
-
static inline unsigned long long tick_to_time(unsigned long long tick)
{
tick *= CONFIG_SYS_HZ;
do_div(tick, MXC_CLK32);
-
return tick;
}
+static inline unsigned long time_to_tick(unsigned long time)
+{
+ unsigned long long ticks = (unsigned long long)time;
+
+ ticks *= MXC_CLK32;
+ do_div(ticks, CONFIG_SYS_HZ);
+ return ticks;
+}
+
static inline unsigned long long us_to_tick(unsigned long long usec)
{
usec = usec * MXC_CLK32 + 999999;
int timer_init(void)
{
int i;
- ulong val;
/* setup GP Timer 1 */
__raw_writel(GPTCR_SWR, &cur_gpt->control);
i = __raw_readl(&cur_gpt->control);
__raw_writel(i | GPTCR_CLKSOURCE_32 | GPTCR_TEN, &cur_gpt->control);
- val = __raw_readl(&cur_gpt->counter);
- lastinc = val / (MXC_CLK32 / CONFIG_SYS_HZ);
- timestamp = 0;
+ gd->arch.tbl = __raw_readl(&cur_gpt->counter);
+ gd->arch.tbu = 0;
+ gd->arch.timer_rate_hz = MXC_CLK32;
return 0;
}
{
ulong now = __raw_readl(&cur_gpt->counter); /* current tick value */
- if (now >= lastinc) {
- /*
- * normal mode (non roll)
- * move stamp forward with absolut diff ticks
- */
- timestamp += (now - lastinc);
- } else {
- /* we have rollover of incrementer */
- timestamp += (0xFFFFFFFF - lastinc) + now;
- }
- lastinc = now;
- return timestamp;
+ /* increment tbu if tbl has rolled over */
+ if (now < gd->arch.tbl)
+ gd->arch.tbu++;
+ gd->arch.tbl = now;
+ return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl;
}
ulong get_timer_masked(void)
* 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in
* 5 * 10^6 days - long enough.
*/
+ /*
+ * LW: get_ticks() returns a long long with the top 32 bits always ZERO!
+ * Thus the calculation above is not true.
+ * A 64bit timer value would only make sense if it was
+ * consistently used throughout the code. Thus also the parameter
+ * to get_timer() and its return value would need to be 64bit wide!
+ */
return tick_to_time(get_ticks());
}
ulong get_timer(ulong base)
{
- return get_timer_masked() - base;
+ return tick_to_time(get_ticks() - time_to_tick(base));
}
/* delay x useconds AND preserve advance timstamp value */
void __udelay(unsigned long usec)
{
- unsigned long long tmp;
- ulong tmo;
+ unsigned long start = __raw_readl(&cur_gpt->counter);
+ unsigned long ticks;
+
+ if (usec == 0)
+ return;
- tmo = us_to_tick(usec);
- tmp = get_ticks() + tmo; /* get current timestamp */
+ ticks = us_to_tick(usec);
+ if (ticks == 0)
+ ticks++;
- while (get_ticks() < tmp) /* loop till event */
- /*NOP*/;
+ while (__raw_readl(&cur_gpt->counter) - start < ticks)
+ /* loop till event */;
}
/*
*/
ulong get_tbclk(void)
{
- return MXC_CLK32;
+ return gd->arch.timer_rate_hz;
}