Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: mmp: Change the way we use timer 0 as clockevent timer.

Instead of setting up a match interrupt for 'current_time + delta'
on ->set_next_event(), program timer 0 to count down from 'delta - 1'
and trigger an interrupt when it reaches zero.

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>

authored by

Lennert Buytenhek and committed by
Eric Miao
af9dafb1 71c0c341

+35 -12
+35 -12
arch/arm/mach-mmp/time.c
··· 75 75 { 76 76 struct clock_event_device *c = dev_id; 77 77 78 - /* disable and clear pending interrupt status */ 79 - __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0)); 80 - __raw_writel(0x1, TIMERS_VIRT_BASE + TMR_ICR(0)); 78 + /* 79 + * Clear pending interrupt status. 80 + */ 81 + __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0)); 82 + 83 + /* 84 + * Disable timer 0. 85 + */ 86 + __raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER); 87 + 81 88 c->event_handler(c); 89 + 82 90 return IRQ_HANDLED; 83 91 } 84 92 85 93 static int timer_set_next_event(unsigned long delta, 86 94 struct clock_event_device *dev) 87 95 { 88 - unsigned long flags, next; 96 + unsigned long flags; 89 97 90 98 local_irq_save(flags); 91 99 92 - /* clear pending interrupt status and enable */ 100 + /* 101 + * Disable timer 0. 102 + */ 103 + __raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER); 104 + 105 + /* 106 + * Clear and enable timer match 0 interrupt. 107 + */ 93 108 __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0)); 94 109 __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_IER(0)); 95 110 96 - next = timer_read() + delta; 97 - __raw_writel(next, TIMERS_VIRT_BASE + TMR_TN_MM(0, 0)); 111 + /* 112 + * Setup new clockevent timer value. 113 + */ 114 + __raw_writel(delta - 1, TIMERS_VIRT_BASE + TMR_TN_MM(0, 0)); 115 + 116 + /* 117 + * Enable timer 0. 118 + */ 119 + __raw_writel(0x03, TIMERS_VIRT_BASE + TMR_CER); 98 120 99 121 local_irq_restore(flags); 122 + 100 123 return 0; 101 124 } 102 125 ··· 175 152 (TMR_CCR_CS_0(3) | TMR_CCR_CS_1(3)); 176 153 __raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR); 177 154 178 - /* free-running mode */ 179 - __raw_writel(0x3, TIMERS_VIRT_BASE + TMR_CMR); 155 + /* set timer 0 to periodic mode, and timer 1 to free-running mode */ 156 + __raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CMR); 180 157 181 - __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* free-running */ 158 + __raw_writel(0x1, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* periodic */ 182 159 __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(0)); /* clear status */ 183 160 __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0)); 184 161 ··· 186 163 __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(1)); /* clear status */ 187 164 __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(1)); 188 165 189 - /* enable timer counter */ 190 - __raw_writel(0x3, TIMERS_VIRT_BASE + TMR_CER); 166 + /* enable timer 1 counter */ 167 + __raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CER); 191 168 } 192 169 193 170 static struct irqaction timer_irq = {