~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/arch/arm/cpu/arm926ejs/mx27/timer.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (C) Copyright 2002
 
3
 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
 
4
 * Marius Groeger <mgroeger@sysgo.de>
 
5
 *
 
6
 * (C) Copyright 2002
 
7
 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
 
8
 * Alex Zuepke <azu@sysgo.de>
 
9
 *
 
10
 * (C) Copyright 2002
 
11
 * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
 
12
 *
 
13
 * (C) Copyright 2009
 
14
 * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
 
15
 *
 
16
 * SPDX-License-Identifier:     GPL-2.0+
 
17
 */
 
18
 
 
19
#include <common.h>
 
20
#include <div64.h>
 
21
#include <asm/io.h>
 
22
#include <asm/arch/imx-regs.h>
 
23
 
 
24
/* General purpose timers bitfields */
 
25
#define GPTCR_SWR               (1 << 15)       /* Software reset       */
 
26
#define GPTCR_FRR               (1 << 8)        /* Freerun / restart    */
 
27
#define GPTCR_CLKSOURCE_32      (4 << 1)        /* Clock source         */
 
28
#define GPTCR_TEN               1               /* Timer enable         */
 
29
 
 
30
DECLARE_GLOBAL_DATA_PTR;
 
31
 
 
32
#define timestamp       (gd->arch.tbl)
 
33
#define lastinc         (gd->arch.lastinc)
 
34
 
 
35
/*
 
36
 * "time" is measured in 1 / CONFIG_SYS_HZ seconds,
 
37
 * "tick" is internal timer period
 
38
 */
 
39
#ifdef CONFIG_MX27_TIMER_HIGH_PRECISION
 
40
/* ~0.4% error - measured with stop-watch on 100s boot-delay */
 
41
static inline unsigned long long tick_to_time(unsigned long long tick)
 
42
{
 
43
        tick *= CONFIG_SYS_HZ;
 
44
        do_div(tick, CONFIG_MX27_CLK32);
 
45
        return tick;
 
46
}
 
47
 
 
48
static inline unsigned long long time_to_tick(unsigned long long time)
 
49
{
 
50
        time *= CONFIG_MX27_CLK32;
 
51
        do_div(time, CONFIG_SYS_HZ);
 
52
        return time;
 
53
}
 
54
 
 
55
static inline unsigned long long us_to_tick(unsigned long long us)
 
56
{
 
57
        us = us * CONFIG_MX27_CLK32 + 999999;
 
58
        do_div(us, 1000000);
 
59
        return us;
 
60
}
 
61
#else
 
62
/* ~2% error */
 
63
#define TICK_PER_TIME   ((CONFIG_MX27_CLK32 + CONFIG_SYS_HZ / 2) / \
 
64
                CONFIG_SYS_HZ)
 
65
#define US_PER_TICK     (1000000 / CONFIG_MX27_CLK32)
 
66
 
 
67
static inline unsigned long long tick_to_time(unsigned long long tick)
 
68
{
 
69
        do_div(tick, TICK_PER_TIME);
 
70
        return tick;
 
71
}
 
72
 
 
73
static inline unsigned long long time_to_tick(unsigned long long time)
 
74
{
 
75
        return time * TICK_PER_TIME;
 
76
}
 
77
 
 
78
static inline unsigned long long us_to_tick(unsigned long long us)
 
79
{
 
80
        us += US_PER_TICK - 1;
 
81
        do_div(us, US_PER_TICK);
 
82
        return us;
 
83
}
 
84
#endif
 
85
 
 
86
/* nothing really to do with interrupts, just starts up a counter. */
 
87
/* The 32768Hz 32-bit timer overruns in 131072 seconds */
 
88
int timer_init(void)
 
89
{
 
90
        int i;
 
91
        struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE;
 
92
        struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
 
93
 
 
94
        /* setup GP Timer 1 */
 
95
        writel(GPTCR_SWR, &regs->gpt_tctl);
 
96
 
 
97
        writel(readl(&pll->pccr0) | PCCR0_GPT1_EN, &pll->pccr0);
 
98
        writel(readl(&pll->pccr1) | PCCR1_PERCLK1_EN, &pll->pccr1);
 
99
 
 
100
        for (i = 0; i < 100; i++)
 
101
                writel(0, &regs->gpt_tctl); /* We have no udelay by now */
 
102
        writel(0, &regs->gpt_tprer); /* 32Khz */
 
103
        /* Freerun Mode, PERCLK1 input */
 
104
        writel(readl(&regs->gpt_tctl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR,
 
105
                        &regs->gpt_tctl);
 
106
        writel(readl(&regs->gpt_tctl) | GPTCR_TEN, &regs->gpt_tctl);
 
107
 
 
108
        return 0;
 
109
}
 
110
 
 
111
unsigned long long get_ticks(void)
 
112
{
 
113
        struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE;
 
114
        ulong now = readl(&regs->gpt_tcn); /* current tick value */
 
115
 
 
116
        if (now >= lastinc) {
 
117
                /*
 
118
                 * normal mode (non roll)
 
119
                 * move stamp forward with absolut diff ticks
 
120
                 */
 
121
                timestamp += (now - lastinc);
 
122
        } else {
 
123
                /* we have rollover of incrementer */
 
124
                timestamp += (0xFFFFFFFF - lastinc) + now;
 
125
        }
 
126
        lastinc = now;
 
127
        return timestamp;
 
128
}
 
129
 
 
130
ulong get_timer_masked(void)
 
131
{
 
132
        /*
 
133
         * get_ticks() returns a long long (64 bit), it wraps in
 
134
         * 2^64 / CONFIG_MX27_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~
 
135
         * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in
 
136
         * 5 * 10^6 days - long enough.
 
137
         */
 
138
        return tick_to_time(get_ticks());
 
139
}
 
140
 
 
141
ulong get_timer(ulong base)
 
142
{
 
143
        return get_timer_masked() - base;
 
144
}
 
145
 
 
146
/* delay x useconds AND preserve advance timstamp value */
 
147
void __udelay(unsigned long usec)
 
148
{
 
149
        unsigned long long tmp;
 
150
        ulong tmo;
 
151
 
 
152
        tmo = us_to_tick(usec);
 
153
        tmp = get_ticks() + tmo;        /* get current timestamp */
 
154
 
 
155
        while (get_ticks() < tmp)       /* loop till event */
 
156
                 /*NOP*/;
 
157
}
 
158
 
 
159
ulong get_tbclk(void)
 
160
{
 
161
        return CONFIG_MX27_CLK32;
 
162
}