aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2011-08-09 14:36:59 -0400
committerEric Miao <eric.y.miao@gmail.com>2011-08-10 22:10:44 -0400
commit7ce5ae39c46f159aee3b3427844f1491e1ccac74 (patch)
treeda07dbd620cb9cccb72a29559c09c17717c58137 /arch/arm
parent4c22ea8f449ce837dd84965badca8e10f1f4094f (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.c15
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 = {
145static void __init timer_config(void) 145static 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
167static struct irqaction timer_irq = { 170static struct irqaction timer_irq = {