blob: cc6166f938b4e04adb01a587c36bafc49bf73f7a [file] [log] [blame]
Stefano Babic1c2b3ac2011-01-20 07:49:52 +00001/*
2 * (C) Copyright 2007
3 * Sascha Hauer, Pengutronix
4 *
5 * (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
6 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02007 * SPDX-License-Identifier: GPL-2.0+
Stefano Babic1c2b3ac2011-01-20 07:49:52 +00008 */
9
10#include <common.h>
11#include <asm/io.h>
Stefano Babicb36049c2012-02-04 12:56:50 +010012#include <div64.h>
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000013#include <asm/arch/imx-regs.h>
Benoît Thébaudeau6ce2db02012-08-21 11:07:54 +000014#include <asm/arch/crm_regs.h>
Stefano Babicb36049c2012-02-04 12:56:50 +010015#include <asm/arch/clock.h>
16
17DECLARE_GLOBAL_DATA_PTR;
18
Simon Glass2655ee12012-12-13 20:48:34 +000019#define timestamp (gd->arch.tbl)
Simon Glassa848da52012-12-13 20:48:35 +000020#define lastinc (gd->arch.lastinc)
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000021
22/* General purpose timers bitfields */
23#define GPTCR_SWR (1<<15) /* Software reset */
24#define GPTCR_FRR (1<<9) /* Freerun / restart */
Benoît Thébaudeau6ce2db02012-08-21 11:07:54 +000025#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000026#define GPTCR_TEN (1) /* Timer enable */
Stefano Babicb36049c2012-02-04 12:56:50 +010027
Benoît Thébaudeau6ce2db02012-08-21 11:07:54 +000028/*
29 * "time" is measured in 1 / CONFIG_SYS_HZ seconds,
30 * "tick" is internal timer period
31 */
32/* ~0.4% error - measured with stop-watch on 100s boot-delay */
Stefano Babicb36049c2012-02-04 12:56:50 +010033static inline unsigned long long tick_to_time(unsigned long long tick)
34{
35 tick *= CONFIG_SYS_HZ;
Benoît Thébaudeau6ce2db02012-08-21 11:07:54 +000036 do_div(tick, MXC_CLK32);
Stefano Babicb36049c2012-02-04 12:56:50 +010037
38 return tick;
39}
40
Benoît Thébaudeau6ce2db02012-08-21 11:07:54 +000041static inline unsigned long long us_to_tick(unsigned long long us)
Stefano Babicb36049c2012-02-04 12:56:50 +010042{
Benoît Thébaudeau6ce2db02012-08-21 11:07:54 +000043 us = us * MXC_CLK32 + 999999;
44 do_div(us, 1000000);
Stefano Babicb36049c2012-02-04 12:56:50 +010045
Benoît Thébaudeau6ce2db02012-08-21 11:07:54 +000046 return us;
Stefano Babicb36049c2012-02-04 12:56:50 +010047}
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000048
Benoît Thébaudeau6ce2db02012-08-21 11:07:54 +000049/*
50 * nothing really to do with interrupts, just starts up a counter.
51 * The 32KHz 32-bit timer overruns in 134217 seconds
52 */
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000053int timer_init(void)
54{
55 int i;
56 struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR;
Benoît Thébaudeau6ce2db02012-08-21 11:07:54 +000057 struct ccm_regs *ccm = (struct ccm_regs *)CCM_BASE_ADDR;
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000058
59 /* setup GP Timer 1 */
60 writel(GPTCR_SWR, &gpt->ctrl);
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000061
Benoît Thébaudeau6ce2db02012-08-21 11:07:54 +000062 writel(readl(&ccm->cgr1) | 3 << MXC_CCM_CGR1_GPT_OFFSET, &ccm->cgr1);
63
64 for (i = 0; i < 100; i++)
65 writel(0, &gpt->ctrl); /* We have no udelay by now */
66 writel(0, &gpt->pre); /* prescaler = 1 */
67 /* Freerun Mode, 32KHz input */
68 writel(readl(&gpt->ctrl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR,
69 &gpt->ctrl);
70 writel(readl(&gpt->ctrl) | GPTCR_TEN, &gpt->ctrl);
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000071
72 return 0;
73}
74
Stefano Babicb36049c2012-02-04 12:56:50 +010075unsigned long long get_ticks(void)
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000076{
77 struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR;
Stefano Babicb36049c2012-02-04 12:56:50 +010078 ulong now = readl(&gpt->counter); /* current tick value */
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000079
Stefano Babicb36049c2012-02-04 12:56:50 +010080 if (now >= lastinc) {
81 /*
82 * normal mode (non roll)
83 * move stamp forward with absolut diff ticks
84 */
85 timestamp += (now - lastinc);
86 } else {
87 /* we have rollover of incrementer */
88 timestamp += (0xFFFFFFFF - lastinc) + now;
89 }
90 lastinc = now;
91 return timestamp;
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000092}
93
Stefano Babicb36049c2012-02-04 12:56:50 +010094ulong get_timer_masked(void)
Stefano Babic1c2b3ac2011-01-20 07:49:52 +000095{
Stefano Babicb36049c2012-02-04 12:56:50 +010096 /*
97 * get_ticks() returns a long long (64 bit), it wraps in
Benoît Thébaudeaue4528342012-08-21 11:07:20 +000098 * 2^64 / MXC_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~
Stefano Babicb36049c2012-02-04 12:56:50 +010099 * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in
100 * 5 * 10^6 days - long enough.
101 */
102 return tick_to_time(get_ticks());
Stefano Babic1c2b3ac2011-01-20 07:49:52 +0000103}
104
Stefano Babic1c2b3ac2011-01-20 07:49:52 +0000105ulong get_timer(ulong base)
106{
Stefano Babicb36049c2012-02-04 12:56:50 +0100107 return get_timer_masked() - base;
108}
Stefano Babic1c2b3ac2011-01-20 07:49:52 +0000109
Stefano Babicb36049c2012-02-04 12:56:50 +0100110/* delay x useconds AND preserve advance timstamp value */
111void __udelay(unsigned long usec)
112{
113 unsigned long long tmp;
114 ulong tmo;
Stefano Babic1c2b3ac2011-01-20 07:49:52 +0000115
Stefano Babicb36049c2012-02-04 12:56:50 +0100116 tmo = us_to_tick(usec);
117 tmp = get_ticks() + tmo; /* get current timestamp */
Stefano Babic1c2b3ac2011-01-20 07:49:52 +0000118
Stefano Babicb36049c2012-02-04 12:56:50 +0100119 while (get_ticks() < tmp) /* loop till event */
120 /*NOP*/;
Stefano Babic1c2b3ac2011-01-20 07:49:52 +0000121}
122
Stefano Babic1c2b3ac2011-01-20 07:49:52 +0000123/*
Stefano Babicb36049c2012-02-04 12:56:50 +0100124 * This function is derived from PowerPC code (timebase clock frequency).
125 * On ARM it returns the number of timer ticks per second.
Stefano Babic1c2b3ac2011-01-20 07:49:52 +0000126 */
Stefano Babicb36049c2012-02-04 12:56:50 +0100127ulong get_tbclk(void)
Stefano Babic1c2b3ac2011-01-20 07:49:52 +0000128{
Benoît Thébaudeau6ce2db02012-08-21 11:07:54 +0000129 return MXC_CLK32;
Stefano Babic1c2b3ac2011-01-20 07:49:52 +0000130}