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

« back to all changes in this revision

Viewing changes to roms/u-boot/arch/arm/cpu/arm920t/s3c24x0/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, <garyj@denx.de>
 
12
 *
 
13
 * SPDX-License-Identifier:     GPL-2.0+
 
14
 */
 
15
 
 
16
#include <common.h>
 
17
#ifdef CONFIG_S3C24X0
 
18
 
 
19
#include <asm/io.h>
 
20
#include <asm/arch/s3c24x0_cpu.h>
 
21
 
 
22
DECLARE_GLOBAL_DATA_PTR;
 
23
 
 
24
int timer_init(void)
 
25
{
 
26
        struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
 
27
        ulong tmr;
 
28
 
 
29
        /* use PWM Timer 4 because it has no output */
 
30
        /* prescaler for Timer 4 is 16 */
 
31
        writel(0x0f00, &timers->tcfg0);
 
32
        if (gd->arch.tbu == 0) {
 
33
                /*
 
34
                 * for 10 ms clock period @ PCLK with 4 bit divider = 1/2
 
35
                 * (default) and prescaler = 16. Should be 10390
 
36
                 * @33.25MHz and 15625 @ 50 MHz
 
37
                 */
 
38
                gd->arch.tbu = get_PCLK() / (2 * 16 * 100);
 
39
                gd->arch.timer_rate_hz = get_PCLK() / (2 * 16);
 
40
        }
 
41
        /* load value for 10 ms timeout */
 
42
        writel(gd->arch.tbu, &timers->tcntb4);
 
43
        /* auto load, manual update of timer 4 */
 
44
        tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000;
 
45
        writel(tmr, &timers->tcon);
 
46
        /* auto load, start timer 4 */
 
47
        tmr = (tmr & ~0x0700000) | 0x0500000;
 
48
        writel(tmr, &timers->tcon);
 
49
        gd->arch.lastinc = 0;
 
50
        gd->arch.tbl = 0;
 
51
 
 
52
        return 0;
 
53
}
 
54
 
 
55
/*
 
56
 * timer without interrupts
 
57
 */
 
58
ulong get_timer(ulong base)
 
59
{
 
60
        return get_timer_masked() - base;
 
61
}
 
62
 
 
63
void __udelay (unsigned long usec)
 
64
{
 
65
        ulong tmo;
 
66
        ulong start = get_ticks();
 
67
 
 
68
        tmo = usec / 1000;
 
69
        tmo *= (gd->arch.tbu * 100);
 
70
        tmo /= 1000;
 
71
 
 
72
        while ((ulong) (get_ticks() - start) < tmo)
 
73
                /*NOP*/;
 
74
}
 
75
 
 
76
ulong get_timer_masked(void)
 
77
{
 
78
        ulong tmr = get_ticks();
 
79
 
 
80
        return tmr / (gd->arch.timer_rate_hz / CONFIG_SYS_HZ);
 
81
}
 
82
 
 
83
void udelay_masked(unsigned long usec)
 
84
{
 
85
        ulong tmo;
 
86
        ulong endtime;
 
87
        signed long diff;
 
88
 
 
89
        if (usec >= 1000) {
 
90
                tmo = usec / 1000;
 
91
                tmo *= (gd->arch.tbu * 100);
 
92
                tmo /= 1000;
 
93
        } else {
 
94
                tmo = usec * (gd->arch.tbu * 100);
 
95
                tmo /= (1000 * 1000);
 
96
        }
 
97
 
 
98
        endtime = get_ticks() + tmo;
 
99
 
 
100
        do {
 
101
                ulong now = get_ticks();
 
102
                diff = endtime - now;
 
103
        } while (diff >= 0);
 
104
}
 
105
 
 
106
/*
 
107
 * This function is derived from PowerPC code (read timebase as long long).
 
108
 * On ARM it just returns the timer value.
 
109
 */
 
110
unsigned long long get_ticks(void)
 
111
{
 
112
        struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
 
113
        ulong now = readl(&timers->tcnto4) & 0xffff;
 
114
 
 
115
        if (gd->arch.lastinc >= now) {
 
116
                /* normal mode */
 
117
                gd->arch.tbl += gd->arch.lastinc - now;
 
118
        } else {
 
119
                /* we have an overflow ... */
 
120
                gd->arch.tbl += gd->arch.lastinc + gd->arch.tbu - now;
 
121
        }
 
122
        gd->arch.lastinc = now;
 
123
 
 
124
        return gd->arch.tbl;
 
125
}
 
126
 
 
127
/*
 
128
 * This function is derived from PowerPC code (timebase clock frequency).
 
129
 * On ARM it returns the number of timer ticks per second.
 
130
 */
 
131
ulong get_tbclk(void)
 
132
{
 
133
        return CONFIG_SYS_HZ;
 
134
}
 
135
 
 
136
/*
 
137
 * reset the cpu by setting up the watchdog timer and let him time out
 
138
 */
 
139
void reset_cpu(ulong ignored)
 
140
{
 
141
        struct s3c24x0_watchdog *watchdog;
 
142
 
 
143
        watchdog = s3c24x0_get_base_watchdog();
 
144
 
 
145
        /* Disable watchdog */
 
146
        writel(0x0000, &watchdog->wtcon);
 
147
 
 
148
        /* Initialize watchdog timer count register */
 
149
        writel(0x0001, &watchdog->wtcnt);
 
150
 
 
151
        /* Enable watchdog timer; assert reset at timer timeout */
 
152
        writel(0x0021, &watchdog->wtcon);
 
153
 
 
154
        while (1)
 
155
                /* loop forever and wait for reset to happen */;
 
156
 
 
157
        /*NOTREACHED*/
 
158
}
 
159
 
 
160
#endif /* CONFIG_S3C24X0 */