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

Merge tag 'timer' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

timer changes for msm

A very simple series. We used to have more churn in the timer
area, so this is kept separate. Will probably put this into the
drivers series next time.

* tag 'timer' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc:
msm: timer: Use clockevents_config_and_register()
msm: timer: Setup interrupt after registering clockevent
msm: timer: Remove SoC specific #ifdefs
msm: timer: Remove msm_clocks[] and simplify code
msm: timer: Fix ONESHOT mode interrupts
msm: timer: Use GPT for clockevents and DGT for clocksource
msm: timer: Cleanup #includes and #defines
msm: timer: Tighten #ifdef for local timer support

+123 -222
+123 -222
arch/arm/mach-msm/timer.c
··· 1 - /* linux/arch/arm/mach-msm/timer.c 1 + /* 2 2 * 3 3 * Copyright (C) 2007 Google, Inc. 4 + * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. 4 5 * 5 6 * This software is licensed under the terms of the GNU General Public 6 7 * License version 2, as published by the Free Software Foundation, and ··· 14 13 * 15 14 */ 16 15 16 + #include <linux/clocksource.h> 17 + #include <linux/clockchips.h> 17 18 #include <linux/init.h> 18 - #include <linux/time.h> 19 19 #include <linux/interrupt.h> 20 20 #include <linux/irq.h> 21 - #include <linux/clk.h> 22 - #include <linux/clockchips.h> 23 - #include <linux/delay.h> 24 21 #include <linux/io.h> 25 22 26 23 #include <asm/mach/time.h> 27 24 #include <asm/hardware/gic.h> 25 + #include <asm/localtimer.h> 28 26 29 27 #include <mach/msm_iomap.h> 30 28 #include <mach/cpu.h> 29 + #include <mach/board.h> 31 30 32 31 #define TIMER_MATCH_VAL 0x0000 33 32 #define TIMER_COUNT_VAL 0x0004 34 33 #define TIMER_ENABLE 0x0008 35 - #define TIMER_ENABLE_CLR_ON_MATCH_EN 2 36 - #define TIMER_ENABLE_EN 1 34 + #define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) 35 + #define TIMER_ENABLE_EN BIT(0) 37 36 #define TIMER_CLEAR 0x000C 38 37 #define DGT_CLK_CTL 0x0034 39 - enum { 40 - DGT_CLK_CTL_DIV_1 = 0, 41 - DGT_CLK_CTL_DIV_2 = 1, 42 - DGT_CLK_CTL_DIV_3 = 2, 43 - DGT_CLK_CTL_DIV_4 = 3, 44 - }; 45 - #define CSR_PROTECTION 0x0020 46 - #define CSR_PROTECTION_EN 1 38 + #define DGT_CLK_CTL_DIV_4 0x3 47 39 48 40 #define GPT_HZ 32768 49 41 50 - enum timer_location { 51 - LOCAL_TIMER = 0, 52 - GLOBAL_TIMER = 1, 53 - }; 42 + #define MSM_DGT_SHIFT 5 54 43 55 - #define MSM_GLOBAL_TIMER MSM_CLOCK_DGT 56 - 57 - /* TODO: Remove these ifdefs */ 58 - #if defined(CONFIG_ARCH_QSD8X50) 59 - #define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */ 60 - #define MSM_DGT_SHIFT (0) 61 - #elif defined(CONFIG_ARCH_MSM7X30) 62 - #define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */ 63 - #define MSM_DGT_SHIFT (0) 64 - #elif defined(CONFIG_ARCH_MSM8X60) || defined(CONFIG_ARCH_MSM8960) 65 - #define DGT_HZ (27000000 / 4) /* 27 MHz (PXO) / 4 by default */ 66 - #define MSM_DGT_SHIFT (0) 67 - #else 68 - #define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */ 69 - #define MSM_DGT_SHIFT (5) 70 - #endif 71 - 72 - struct msm_clock { 73 - struct clock_event_device clockevent; 74 - struct clocksource clocksource; 75 - unsigned int irq; 76 - void __iomem *regbase; 77 - uint32_t freq; 78 - uint32_t shift; 79 - void __iomem *global_counter; 80 - void __iomem *local_counter; 81 - union { 82 - struct clock_event_device *evt; 83 - struct clock_event_device __percpu **percpu_evt; 84 - }; 85 - }; 86 - 87 - enum { 88 - MSM_CLOCK_GPT, 89 - MSM_CLOCK_DGT, 90 - NR_TIMERS, 91 - }; 92 - 93 - 94 - static struct msm_clock msm_clocks[]; 44 + static void __iomem *event_base; 95 45 96 46 static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) 97 47 { 98 48 struct clock_event_device *evt = *(struct clock_event_device **)dev_id; 99 - if (evt->event_handler == NULL) 100 - return IRQ_HANDLED; 49 + /* Stop the timer tick */ 50 + if (evt->mode == CLOCK_EVT_MODE_ONESHOT) { 51 + u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); 52 + ctrl &= ~TIMER_ENABLE_EN; 53 + writel_relaxed(ctrl, event_base + TIMER_ENABLE); 54 + } 101 55 evt->event_handler(evt); 102 56 return IRQ_HANDLED; 103 - } 104 - 105 - static cycle_t msm_read_timer_count(struct clocksource *cs) 106 - { 107 - struct msm_clock *clk = container_of(cs, struct msm_clock, clocksource); 108 - 109 - /* 110 - * Shift timer count down by a constant due to unreliable lower bits 111 - * on some targets. 112 - */ 113 - return readl(clk->global_counter) >> clk->shift; 114 - } 115 - 116 - static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt) 117 - { 118 - #ifdef CONFIG_SMP 119 - int i; 120 - for (i = 0; i < NR_TIMERS; i++) 121 - if (evt == &(msm_clocks[i].clockevent)) 122 - return &msm_clocks[i]; 123 - return &msm_clocks[MSM_GLOBAL_TIMER]; 124 - #else 125 - return container_of(evt, struct msm_clock, clockevent); 126 - #endif 127 57 } 128 58 129 59 static int msm_timer_set_next_event(unsigned long cycles, 130 60 struct clock_event_device *evt) 131 61 { 132 - struct msm_clock *clock = clockevent_to_clock(evt); 133 - uint32_t now = readl(clock->local_counter); 134 - uint32_t alarm = now + (cycles << clock->shift); 62 + u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); 135 63 136 - writel(alarm, clock->regbase + TIMER_MATCH_VAL); 64 + writel_relaxed(0, event_base + TIMER_CLEAR); 65 + writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); 66 + writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); 137 67 return 0; 138 68 } 139 69 140 70 static void msm_timer_set_mode(enum clock_event_mode mode, 141 71 struct clock_event_device *evt) 142 72 { 143 - struct msm_clock *clock = clockevent_to_clock(evt); 73 + u32 ctrl; 74 + 75 + ctrl = readl_relaxed(event_base + TIMER_ENABLE); 76 + ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); 144 77 145 78 switch (mode) { 146 79 case CLOCK_EVT_MODE_RESUME: 147 80 case CLOCK_EVT_MODE_PERIODIC: 148 81 break; 149 82 case CLOCK_EVT_MODE_ONESHOT: 150 - writel(TIMER_ENABLE_EN, clock->regbase + TIMER_ENABLE); 83 + /* Timer is enabled in set_next_event */ 151 84 break; 152 85 case CLOCK_EVT_MODE_UNUSED: 153 86 case CLOCK_EVT_MODE_SHUTDOWN: 154 - writel(0, clock->regbase + TIMER_ENABLE); 155 87 break; 156 88 } 89 + writel_relaxed(ctrl, event_base + TIMER_ENABLE); 157 90 } 158 91 159 - static struct msm_clock msm_clocks[] = { 160 - [MSM_CLOCK_GPT] = { 161 - .clockevent = { 162 - .name = "gp_timer", 163 - .features = CLOCK_EVT_FEAT_ONESHOT, 164 - .shift = 32, 165 - .rating = 200, 166 - .set_next_event = msm_timer_set_next_event, 167 - .set_mode = msm_timer_set_mode, 168 - }, 169 - .clocksource = { 170 - .name = "gp_timer", 171 - .rating = 200, 172 - .read = msm_read_timer_count, 173 - .mask = CLOCKSOURCE_MASK(32), 174 - .flags = CLOCK_SOURCE_IS_CONTINUOUS, 175 - }, 176 - .irq = INT_GP_TIMER_EXP, 177 - .freq = GPT_HZ, 178 - }, 179 - [MSM_CLOCK_DGT] = { 180 - .clockevent = { 181 - .name = "dg_timer", 182 - .features = CLOCK_EVT_FEAT_ONESHOT, 183 - .shift = 32 + MSM_DGT_SHIFT, 184 - .rating = 300, 185 - .set_next_event = msm_timer_set_next_event, 186 - .set_mode = msm_timer_set_mode, 187 - }, 188 - .clocksource = { 189 - .name = "dg_timer", 190 - .rating = 300, 191 - .read = msm_read_timer_count, 192 - .mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)), 193 - .flags = CLOCK_SOURCE_IS_CONTINUOUS, 194 - }, 195 - .irq = INT_DEBUG_TIMER_EXP, 196 - .freq = DGT_HZ >> MSM_DGT_SHIFT, 197 - .shift = MSM_DGT_SHIFT, 198 - } 92 + static struct clock_event_device msm_clockevent = { 93 + .name = "gp_timer", 94 + .features = CLOCK_EVT_FEAT_ONESHOT, 95 + .rating = 200, 96 + .set_next_event = msm_timer_set_next_event, 97 + .set_mode = msm_timer_set_mode, 98 + }; 99 + 100 + static union { 101 + struct clock_event_device *evt; 102 + struct clock_event_device __percpu **percpu_evt; 103 + } msm_evt; 104 + 105 + static void __iomem *source_base; 106 + 107 + static cycle_t msm_read_timer_count(struct clocksource *cs) 108 + { 109 + return readl_relaxed(source_base + TIMER_COUNT_VAL); 110 + } 111 + 112 + static cycle_t msm_read_timer_count_shift(struct clocksource *cs) 113 + { 114 + /* 115 + * Shift timer count down by a constant due to unreliable lower bits 116 + * on some targets. 117 + */ 118 + return msm_read_timer_count(cs) >> MSM_DGT_SHIFT; 119 + } 120 + 121 + static struct clocksource msm_clocksource = { 122 + .name = "dg_timer", 123 + .rating = 300, 124 + .read = msm_read_timer_count, 125 + .mask = CLOCKSOURCE_MASK(32), 126 + .flags = CLOCK_SOURCE_IS_CONTINUOUS, 199 127 }; 200 128 201 129 static void __init msm_timer_init(void) 202 130 { 203 - int i; 131 + struct clock_event_device *ce = &msm_clockevent; 132 + struct clocksource *cs = &msm_clocksource; 204 133 int res; 205 - int global_offset = 0; 134 + u32 dgt_hz; 206 135 207 136 if (cpu_is_msm7x01()) { 208 - msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE; 209 - msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10; 137 + event_base = MSM_CSR_BASE; 138 + source_base = MSM_CSR_BASE + 0x10; 139 + dgt_hz = 19200000 >> MSM_DGT_SHIFT; /* 600 KHz */ 140 + cs->read = msm_read_timer_count_shift; 141 + cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); 210 142 } else if (cpu_is_msm7x30()) { 211 - msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE + 0x04; 212 - msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x24; 143 + event_base = MSM_CSR_BASE + 0x04; 144 + source_base = MSM_CSR_BASE + 0x24; 145 + dgt_hz = 24576000 / 4; 213 146 } else if (cpu_is_qsd8x50()) { 214 - msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE; 215 - msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10; 147 + event_base = MSM_CSR_BASE; 148 + source_base = MSM_CSR_BASE + 0x10; 149 + dgt_hz = 19200000 / 4; 216 150 } else if (cpu_is_msm8x60() || cpu_is_msm8960()) { 217 - msm_clocks[MSM_CLOCK_GPT].regbase = MSM_TMR_BASE + 0x04; 218 - msm_clocks[MSM_CLOCK_DGT].regbase = MSM_TMR_BASE + 0x24; 219 - 220 - /* Use CPU0's timer as the global timer. */ 221 - global_offset = MSM_TMR0_BASE - MSM_TMR_BASE; 151 + event_base = MSM_TMR_BASE + 0x04; 152 + /* Use CPU0's timer as the global clock source. */ 153 + source_base = MSM_TMR0_BASE + 0x24; 154 + dgt_hz = 27000000 / 4; 155 + writel_relaxed(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL); 222 156 } else 223 157 BUG(); 224 158 225 - #ifdef CONFIG_ARCH_MSM_SCORPIONMP 226 - writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL); 227 - #endif 159 + writel_relaxed(0, event_base + TIMER_ENABLE); 160 + writel_relaxed(0, event_base + TIMER_CLEAR); 161 + writel_relaxed(~0, event_base + TIMER_MATCH_VAL); 162 + ce->cpumask = cpumask_of(0); 228 163 229 - for (i = 0; i < ARRAY_SIZE(msm_clocks); i++) { 230 - struct msm_clock *clock = &msm_clocks[i]; 231 - struct clock_event_device *ce = &clock->clockevent; 232 - struct clocksource *cs = &clock->clocksource; 233 - 234 - clock->local_counter = clock->regbase + TIMER_COUNT_VAL; 235 - clock->global_counter = clock->local_counter + global_offset; 236 - 237 - writel(0, clock->regbase + TIMER_ENABLE); 238 - writel(0, clock->regbase + TIMER_CLEAR); 239 - writel(~0, clock->regbase + TIMER_MATCH_VAL); 240 - 241 - ce->mult = div_sc(clock->freq, NSEC_PER_SEC, ce->shift); 242 - /* allow at least 10 seconds to notice that the timer wrapped */ 243 - ce->max_delta_ns = 244 - clockevent_delta2ns(0xf0000000 >> clock->shift, ce); 245 - /* 4 gets rounded down to 3 */ 246 - ce->min_delta_ns = clockevent_delta2ns(4, ce); 247 - ce->cpumask = cpumask_of(0); 248 - 249 - res = clocksource_register_hz(cs, clock->freq); 250 - if (res) 251 - printk(KERN_ERR "msm_timer_init: clocksource_register " 252 - "failed for %s\n", cs->name); 253 - 254 - ce->irq = clock->irq; 255 - if (cpu_is_msm8x60() || cpu_is_msm8960()) { 256 - clock->percpu_evt = alloc_percpu(struct clock_event_device *); 257 - if (!clock->percpu_evt) { 258 - pr_err("msm_timer_init: memory allocation " 259 - "failed for %s\n", ce->name); 260 - continue; 261 - } 262 - 263 - *__this_cpu_ptr(clock->percpu_evt) = ce; 264 - res = request_percpu_irq(ce->irq, msm_timer_interrupt, 265 - ce->name, clock->percpu_evt); 266 - if (!res) 267 - enable_percpu_irq(ce->irq, 0); 268 - } else { 269 - clock->evt = ce; 270 - res = request_irq(ce->irq, msm_timer_interrupt, 271 - IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING, 272 - ce->name, &clock->evt); 164 + ce->irq = INT_GP_TIMER_EXP; 165 + clockevents_config_and_register(ce, GPT_HZ, 4, 0xffffffff); 166 + if (cpu_is_msm8x60() || cpu_is_msm8960()) { 167 + msm_evt.percpu_evt = alloc_percpu(struct clock_event_device *); 168 + if (!msm_evt.percpu_evt) { 169 + pr_err("memory allocation failed for %s\n", ce->name); 170 + goto err; 273 171 } 274 - 275 - if (res) 276 - pr_err("msm_timer_init: request_irq failed for %s\n", 277 - ce->name); 278 - 279 - clockevents_register_device(ce); 172 + *__this_cpu_ptr(msm_evt.percpu_evt) = ce; 173 + res = request_percpu_irq(ce->irq, msm_timer_interrupt, 174 + ce->name, msm_evt.percpu_evt); 175 + if (!res) 176 + enable_percpu_irq(ce->irq, 0); 177 + } else { 178 + msm_evt.evt = ce; 179 + res = request_irq(ce->irq, msm_timer_interrupt, 180 + IRQF_TIMER | IRQF_NOBALANCING | 181 + IRQF_TRIGGER_RISING, ce->name, &msm_evt.evt); 280 182 } 183 + 184 + if (res) 185 + pr_err("request_irq failed for %s\n", ce->name); 186 + err: 187 + writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE); 188 + res = clocksource_register_hz(cs, dgt_hz); 189 + if (res) 190 + pr_err("clocksource_register failed\n"); 281 191 } 282 192 283 - #ifdef CONFIG_SMP 193 + #ifdef CONFIG_LOCAL_TIMERS 284 194 int __cpuinit local_timer_setup(struct clock_event_device *evt) 285 195 { 286 - static bool local_timer_inited; 287 - struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER]; 288 - 289 196 /* Use existing clock_event for cpu 0 */ 290 197 if (!smp_processor_id()) 291 198 return 0; 292 199 293 - writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL); 294 - 295 - if (!local_timer_inited) { 296 - writel(0, clock->regbase + TIMER_ENABLE); 297 - writel(0, clock->regbase + TIMER_CLEAR); 298 - writel(~0, clock->regbase + TIMER_MATCH_VAL); 299 - local_timer_inited = true; 300 - } 301 - evt->irq = clock->irq; 200 + writel_relaxed(0, event_base + TIMER_ENABLE); 201 + writel_relaxed(0, event_base + TIMER_CLEAR); 202 + writel_relaxed(~0, event_base + TIMER_MATCH_VAL); 203 + evt->irq = msm_clockevent.irq; 302 204 evt->name = "local_timer"; 303 - evt->features = CLOCK_EVT_FEAT_ONESHOT; 304 - evt->rating = clock->clockevent.rating; 205 + evt->features = msm_clockevent.features; 206 + evt->rating = msm_clockevent.rating; 305 207 evt->set_mode = msm_timer_set_mode; 306 208 evt->set_next_event = msm_timer_set_next_event; 307 - evt->shift = clock->clockevent.shift; 308 - evt->mult = div_sc(clock->freq, NSEC_PER_SEC, evt->shift); 309 - evt->max_delta_ns = 310 - clockevent_delta2ns(0xf0000000 >> clock->shift, evt); 209 + evt->shift = msm_clockevent.shift; 210 + evt->mult = div_sc(GPT_HZ, NSEC_PER_SEC, evt->shift); 211 + evt->max_delta_ns = clockevent_delta2ns(0xf0000000, evt); 311 212 evt->min_delta_ns = clockevent_delta2ns(4, evt); 312 213 313 - *__this_cpu_ptr(clock->percpu_evt) = evt; 314 - enable_percpu_irq(evt->irq, 0); 315 - 214 + *__this_cpu_ptr(msm_evt.percpu_evt) = evt; 316 215 clockevents_register_device(evt); 216 + enable_percpu_irq(evt->irq, 0); 317 217 return 0; 318 218 } 319 219 ··· 223 321 evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); 224 322 disable_percpu_irq(evt->irq); 225 323 } 226 - 227 - #endif 324 + #endif /* CONFIG_LOCAL_TIMERS */ 228 325 229 326 struct sys_timer msm_timer = { 230 327 .init = msm_timer_init