aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-msm/timer.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 405e8a925202..9f3671a43314 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -81,11 +81,20 @@ enum {
81 81
82static struct msm_clock msm_clocks[]; 82static struct msm_clock msm_clocks[];
83 83
84static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt);
85
84static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) 86static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
85{ 87{
86 struct clock_event_device *evt = *(struct clock_event_device **)dev_id; 88 struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
87 if (evt->event_handler == NULL) 89 if (evt->event_handler == NULL)
88 return IRQ_HANDLED; 90 return IRQ_HANDLED;
91 /* Stop the timer tick */
92 if (evt->mode == CLOCK_EVT_MODE_ONESHOT) {
93 struct msm_clock *clock = clockevent_to_clock(evt);
94 u32 ctrl = readl_relaxed(clock->regbase + TIMER_ENABLE);
95 ctrl &= ~TIMER_ENABLE_EN;
96 writel_relaxed(ctrl, clock->regbase + TIMER_ENABLE);
97 }
89 evt->event_handler(evt); 98 evt->event_handler(evt);
90 return IRQ_HANDLED; 99 return IRQ_HANDLED;
91} 100}
@@ -118,10 +127,12 @@ static int msm_timer_set_next_event(unsigned long cycles,
118 struct clock_event_device *evt) 127 struct clock_event_device *evt)
119{ 128{
120 struct msm_clock *clock = clockevent_to_clock(evt); 129 struct msm_clock *clock = clockevent_to_clock(evt);
121 uint32_t now = readl(clock->local_counter); 130 u32 match = cycles << clock->shift;
122 uint32_t alarm = now + (cycles << clock->shift); 131 u32 ctrl = readl_relaxed(clock->regbase + TIMER_ENABLE);
123 132
124 writel(alarm, clock->regbase + TIMER_MATCH_VAL); 133 writel_relaxed(0, clock->regbase + TIMER_CLEAR);
134 writel_relaxed(match, clock->regbase + TIMER_MATCH_VAL);
135 writel_relaxed(ctrl | TIMER_ENABLE_EN, clock->regbase + TIMER_ENABLE);
125 return 0; 136 return 0;
126} 137}
127 138
@@ -129,19 +140,23 @@ static void msm_timer_set_mode(enum clock_event_mode mode,
129 struct clock_event_device *evt) 140 struct clock_event_device *evt)
130{ 141{
131 struct msm_clock *clock = clockevent_to_clock(evt); 142 struct msm_clock *clock = clockevent_to_clock(evt);
143 u32 ctrl;
144
145 ctrl = readl_relaxed(clock->regbase + TIMER_ENABLE);
146 ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN);
132 147
133 switch (mode) { 148 switch (mode) {
134 case CLOCK_EVT_MODE_RESUME: 149 case CLOCK_EVT_MODE_RESUME:
135 case CLOCK_EVT_MODE_PERIODIC: 150 case CLOCK_EVT_MODE_PERIODIC:
136 break; 151 break;
137 case CLOCK_EVT_MODE_ONESHOT: 152 case CLOCK_EVT_MODE_ONESHOT:
138 writel(TIMER_ENABLE_EN, clock->regbase + TIMER_ENABLE); 153 /* Timer is enabled in set_next_event */
139 break; 154 break;
140 case CLOCK_EVT_MODE_UNUSED: 155 case CLOCK_EVT_MODE_UNUSED:
141 case CLOCK_EVT_MODE_SHUTDOWN: 156 case CLOCK_EVT_MODE_SHUTDOWN:
142 writel(0, clock->regbase + TIMER_ENABLE);
143 break; 157 break;
144 } 158 }
159 writel_relaxed(ctrl, clock->regbase + TIMER_ENABLE);
145} 160}
146 161
147static struct msm_clock msm_clocks[] = { 162static struct msm_clock msm_clocks[] = {