diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2011-08-09 14:36:59 -0400 |
---|---|---|
committer | Eric Miao <eric.y.miao@gmail.com> | 2011-08-10 22:10:44 -0400 |
commit | 7ce5ae39c46f159aee3b3427844f1491e1ccac74 (patch) | |
tree | da07dbd620cb9cccb72a29559c09c17717c58137 /arch/arm | |
parent | 4c22ea8f449ce837dd84965badca8e10f1f4094f (diff) |
ARM: mmp: Also start timer 1 on boot.
Currently, arch-mmp/time.c uses timer 0 both as a clocksource timer
and as a clockevent timer, the latter by setting up a comparator
interrupt to match on 'current_time + delta'. This is problematic
if delta is small enough, as that can lead to 'current_time + delta'
already being in the past when comparator setup has finished, leading
to the requested event not triggering.
As there is also a silicon issue that requires stopping a timer's
counter while writing to one of its match registers, we'll switch to
using two separate timers -- timer 0 as clockevent timer, which we'll
start and stop on every invocation of ->set_next_event(), and timer 1
as clocksource timer, which will be free-running.
This first patch enables timer 1 on boot, so that we can use it as
clocksource timer.
Signed-off-by: Lennert Buytenhek <buytenh@laptop.org>
Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>
Signed-off-by: Eric Miao <eric.y.miao@gmail.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-mmp/time.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 99833b9485cf..09e88c25fe8e 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c | |||
@@ -145,23 +145,26 @@ static struct clocksource cksrc = { | |||
145 | static void __init timer_config(void) | 145 | static void __init timer_config(void) |
146 | { | 146 | { |
147 | uint32_t ccr = __raw_readl(TIMERS_VIRT_BASE + TMR_CCR); | 147 | uint32_t ccr = __raw_readl(TIMERS_VIRT_BASE + TMR_CCR); |
148 | uint32_t cer = __raw_readl(TIMERS_VIRT_BASE + TMR_CER); | ||
149 | uint32_t cmr = __raw_readl(TIMERS_VIRT_BASE + TMR_CMR); | ||
150 | 148 | ||
151 | __raw_writel(cer & ~0x1, TIMERS_VIRT_BASE + TMR_CER); /* disable */ | 149 | __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_CER); /* disable */ |
152 | 150 | ||
153 | ccr &= (cpu_is_mmp2()) ? TMR_CCR_CS_0(0) : TMR_CCR_CS_0(3); | 151 | ccr &= (cpu_is_mmp2()) ? (TMR_CCR_CS_0(0) | TMR_CCR_CS_1(0)) : |
152 | (TMR_CCR_CS_0(3) | TMR_CCR_CS_1(3)); | ||
154 | __raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR); | 153 | __raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR); |
155 | 154 | ||
156 | /* free-running mode */ | 155 | /* free-running mode */ |
157 | __raw_writel(cmr | 0x01, TIMERS_VIRT_BASE + TMR_CMR); | 156 | __raw_writel(0x3, TIMERS_VIRT_BASE + TMR_CMR); |
158 | 157 | ||
159 | __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* free-running */ | 158 | __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* free-running */ |
160 | __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(0)); /* clear status */ | 159 | __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(0)); /* clear status */ |
161 | __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0)); | 160 | __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0)); |
162 | 161 | ||
162 | __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(1)); /* free-running */ | ||
163 | __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(1)); /* clear status */ | ||
164 | __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(1)); | ||
165 | |||
163 | /* enable timer counter */ | 166 | /* enable timer counter */ |
164 | __raw_writel(cer | 0x01, TIMERS_VIRT_BASE + TMR_CER); | 167 | __raw_writel(0x3, TIMERS_VIRT_BASE + TMR_CER); |
165 | } | 168 | } |
166 | 169 | ||
167 | static struct irqaction timer_irq = { | 170 | static struct irqaction timer_irq = { |