]>
Commit | Line | Data |
---|---|---|
be72e0c8 JR |
1 | /* |
2 | * Copyright (C) 2010 Linaro Limited | |
3 | * John Rigby <john.rigby@linaro.org> | |
4 | * | |
5 | * Based on original from Linux kernel source and | |
6 | * internal ST-Ericsson U-Boot source. | |
7 | * (C) Copyright 2009 Alessandro Rubini | |
8 | * (C) Copyright 2010 ST-Ericsson | |
9 | * | |
1a459660 | 10 | * SPDX-License-Identifier: GPL-2.0+ |
be72e0c8 JR |
11 | */ |
12 | ||
13 | #include <common.h> | |
14 | #include <asm/io.h> | |
15 | #include <asm/arch/hardware.h> | |
16 | ||
17 | DECLARE_GLOBAL_DATA_PTR; | |
18 | ||
19 | /* | |
20 | * The MTU device has some interrupt control registers | |
21 | * followed by 4 timers. | |
22 | */ | |
23 | ||
24 | /* The timers */ | |
25 | struct u8500_mtu_timer { | |
26 | u32 lr; /* Load value */ | |
27 | u32 cv; /* Current value */ | |
28 | u32 cr; /* Control reg */ | |
29 | u32 bglr; /* ??? */ | |
30 | }; | |
31 | ||
32 | /* The MTU that contains the timers */ | |
33 | struct u8500_mtu { | |
34 | u32 imsc; /* Interrupt mask set/clear */ | |
35 | u32 ris; /* Raw interrupt status */ | |
36 | u32 mis; /* Masked interrupt status */ | |
37 | u32 icr; /* Interrupt clear register */ | |
38 | struct u8500_mtu_timer pt[4]; | |
39 | }; | |
40 | ||
41 | /* bits for the control register */ | |
42 | #define MTU_CR_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR */ | |
43 | #define MTU_CR_32BITS 0x02 | |
44 | ||
45 | #define MTU_CR_PRESCALE_1 0x00 | |
46 | #define MTU_CR_PRESCALE_16 0x04 | |
47 | #define MTU_CR_PRESCALE_256 0x08 | |
48 | #define MTU_CR_PRESCALE_MASK 0x0c | |
49 | ||
50 | #define MTU_CR_PERIODIC 0x40 /* if 0 = free-running */ | |
51 | #define MTU_CR_ENA 0x80 | |
52 | ||
53 | /* | |
54 | * The MTU is clocked at 133 MHz by default. (V1 and later) | |
55 | */ | |
56 | #define TIMER_CLOCK (133 * 1000 * 1000 / 16) | |
57 | #define COUNT_TO_USEC(x) ((x) * 16 / 133) | |
58 | #define USEC_TO_COUNT(x) ((x) * 133 / 16) | |
59 | #define TICKS_PER_HZ (TIMER_CLOCK / CONFIG_SYS_HZ) | |
60 | #define TICKS_TO_HZ(x) ((x) / TICKS_PER_HZ) | |
61 | #define TIMER_LOAD_VAL 0xffffffff | |
62 | ||
63 | /* | |
64 | * MTU timer to use (from 0 to 3). | |
65 | */ | |
66 | #define MTU_TIMER 2 | |
67 | ||
68 | static struct u8500_mtu_timer *timer_base = | |
69 | &((struct u8500_mtu *)U8500_MTU0_BASE_V1)->pt[MTU_TIMER]; | |
70 | ||
71 | /* macro to read the 32 bit timer: since it decrements, we invert read value */ | |
72 | #define READ_TIMER() (~readl(&timer_base->cv)) | |
73 | ||
74 | /* Configure a free-running, auto-wrap counter with /16 prescaler */ | |
75 | int timer_init(void) | |
76 | { | |
77 | writel(MTU_CR_ENA | MTU_CR_PRESCALE_16 | MTU_CR_32BITS, | |
78 | &timer_base->cr); | |
79 | return 0; | |
80 | } | |
81 | ||
82 | ulong get_timer_masked(void) | |
83 | { | |
84 | /* current tick value */ | |
85 | ulong now = TICKS_TO_HZ(READ_TIMER()); | |
86 | ||
582601da SG |
87 | if (now >= gd->arch.lastinc) { /* normal (non rollover) */ |
88 | gd->arch.tbl += (now - gd->arch.lastinc); | |
66ee6923 | 89 | } else { /* rollover */ |
582601da SG |
90 | gd->arch.tbl += (TICKS_TO_HZ(TIMER_LOAD_VAL) - |
91 | gd->arch.lastinc) + now; | |
66ee6923 | 92 | } |
582601da | 93 | gd->arch.lastinc = now; |
66ee6923 | 94 | return gd->arch.tbl; |
be72e0c8 JR |
95 | } |
96 | ||
97 | /* Delay x useconds */ | |
98 | void __udelay(ulong usec) | |
99 | { | |
100 | long tmo = usec * (TIMER_CLOCK / 1000) / 1000; | |
101 | ulong now, last = READ_TIMER(); | |
102 | ||
103 | while (tmo > 0) { | |
104 | now = READ_TIMER(); | |
105 | if (now > last) /* normal (non rollover) */ | |
106 | tmo -= now - last; | |
107 | else /* rollover */ | |
108 | tmo -= TIMER_LOAD_VAL - last + now; | |
109 | last = now; | |
110 | } | |
111 | } | |
112 | ||
113 | ulong get_timer(ulong base) | |
114 | { | |
115 | return get_timer_masked() - base; | |
116 | } | |
117 | ||
be72e0c8 JR |
118 | /* |
119 | * Emulation of Power architecture long long timebase. | |
120 | * | |
8ff43b03 | 121 | * TODO: Support gd->arch.tbu for real long long timebase. |
be72e0c8 JR |
122 | */ |
123 | unsigned long long get_ticks(void) | |
124 | { | |
125 | return get_timer(0); | |
126 | } | |
127 | ||
128 | /* | |
129 | * Emulation of Power architecture timebase. | |
130 | * NB: Low resolution compared to Power tbclk. | |
131 | */ | |
132 | ulong get_tbclk(void) | |
133 | { | |
134 | return CONFIG_SYS_HZ; | |
135 | } |