1 /* 2 * linux/arch/arm/kernel/smp_twd.c 3 * 4 * Copyright (C) 2002 ARM Ltd. 5 * All Rights Reserved 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 #include <linux/init.h> 12 #include <linux/kernel.h> 13 #include <linux/clk.h> 14 #include <linux/delay.h> 15 #include <linux/device.h> 16 #include <linux/err.h> 17 #include <linux/smp.h> 18 #include <linux/jiffies.h> 19 #include <linux/clockchips.h> 20 #include <linux/interrupt.h> 21 #include <linux/io.h> 22 #include <linux/of_irq.h> 23 #include <linux/of_address.h> 24 25 #include <asm/smp_twd.h> 26 #include <asm/localtimer.h> 27 28 /* set up by the platform code */ 29 static void __iomem *twd_base; 30 31 static struct clk *twd_clk; 32 static unsigned long twd_timer_rate; 33 static DEFINE_PER_CPU(bool, percpu_setup_called); 34 35 static struct clock_event_device __percpu **twd_evt; 36 static int twd_ppi; 37 38 static void twd_set_mode(enum clock_event_mode mode, 39 struct clock_event_device *clk) 40 { 41 unsigned long ctrl; 42 43 switch (mode) { 44 case CLOCK_EVT_MODE_PERIODIC: 45 ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE 46 | TWD_TIMER_CONTROL_PERIODIC; 47 __raw_writel(DIV_ROUND_CLOSEST(twd_timer_rate, HZ), 48 twd_base + TWD_TIMER_LOAD); 49 break; 50 case CLOCK_EVT_MODE_ONESHOT: 51 /* period set, and timer enabled in 'next_event' hook */ 52 ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT; 53 break; 54 case CLOCK_EVT_MODE_UNUSED: 55 case CLOCK_EVT_MODE_SHUTDOWN: 56 default: 57 ctrl = 0; 58 } 59 60 __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL); 61 } 62 63 static int twd_set_next_event(unsigned long evt, 64 struct clock_event_device *unused) 65 { 66 unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL); 67 68 ctrl |= TWD_TIMER_CONTROL_ENABLE; 69 70 __raw_writel(evt, twd_base + TWD_TIMER_COUNTER); 71 __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL); 72 73 return 0; 74 } 75 76 /* 77 * local_timer_ack: checks for a local timer interrupt. 78 * 79 * If a local timer interrupt has occurred, acknowledge and return 1. 80 * Otherwise, return 0. 81 */ 82 static int twd_timer_ack(void) 83 { 84 if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) { 85 __raw_writel(1, twd_base + TWD_TIMER_INTSTAT); 86 return 1; 87 } 88 89 return 0; 90 } 91 92 static void twd_timer_stop(struct clock_event_device *clk) 93 { 94 twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk); 95 disable_percpu_irq(clk->irq); 96 } 97 98 #ifdef CONFIG_COMMON_CLK 99 100 /* 101 * Updates clockevent frequency when the cpu frequency changes. 102 * Called on the cpu that is changing frequency with interrupts disabled. 103 */ 104 static void twd_update_frequency(void *new_rate) 105 { 106 twd_timer_rate = *((unsigned long *) new_rate); 107 108 clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); 109 } 110 111 static int twd_rate_change(struct notifier_block *nb, 112 unsigned long flags, void *data) 113 { 114 struct clk_notifier_data *cnd = data; 115 116 /* 117 * The twd clock events must be reprogrammed to account for the new 118 * frequency. The timer is local to a cpu, so cross-call to the 119 * changing cpu. 120 */ 121 if (flags == POST_RATE_CHANGE) 122 smp_call_function(twd_update_frequency, 123 (void *)&cnd->new_rate, 1); 124 125 return NOTIFY_OK; 126 } 127 128 static struct notifier_block twd_clk_nb = { 129 .notifier_call = twd_rate_change, 130 }; 131 132 static int twd_clk_init(void) 133 { 134 if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) 135 return clk_notifier_register(twd_clk, &twd_clk_nb); 136 137 return 0; 138 } 139 core_initcall(twd_clk_init); 140 141 #elif defined (CONFIG_CPU_FREQ) 142 143 #include <linux/cpufreq.h> 144 145 /* 146 * Updates clockevent frequency when the cpu frequency changes. 147 * Called on the cpu that is changing frequency with interrupts disabled. 148 */ 149 static void twd_update_frequency(void *data) 150 { 151 twd_timer_rate = clk_get_rate(twd_clk); 152 153 clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); 154 } 155 156 static int twd_cpufreq_transition(struct notifier_block *nb, 157 unsigned long state, void *data) 158 { 159 struct cpufreq_freqs *freqs = data; 160 161 /* 162 * The twd clock events must be reprogrammed to account for the new 163 * frequency. The timer is local to a cpu, so cross-call to the 164 * changing cpu. 165 */ 166 if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE) 167 smp_call_function_single(freqs->cpu, twd_update_frequency, 168 NULL, 1); 169 170 return NOTIFY_OK; 171 } 172 173 static struct notifier_block twd_cpufreq_nb = { 174 .notifier_call = twd_cpufreq_transition, 175 }; 176 177 static int twd_cpufreq_init(void) 178 { 179 if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) 180 return cpufreq_register_notifier(&twd_cpufreq_nb, 181 CPUFREQ_TRANSITION_NOTIFIER); 182 183 return 0; 184 } 185 core_initcall(twd_cpufreq_init); 186 187 #endif 188 189 static void __cpuinit twd_calibrate_rate(void) 190 { 191 unsigned long count; 192 u64 waitjiffies; 193 194 /* 195 * If this is the first time round, we need to work out how fast 196 * the timer ticks 197 */ 198 if (twd_timer_rate == 0) { 199 printk(KERN_INFO "Calibrating local timer... "); 200 201 /* Wait for a tick to start */ 202 waitjiffies = get_jiffies_64() + 1; 203 204 while (get_jiffies_64() < waitjiffies) 205 udelay(10); 206 207 /* OK, now the tick has started, let's get the timer going */ 208 waitjiffies += 5; 209 210 /* enable, no interrupt or reload */ 211 __raw_writel(0x1, twd_base + TWD_TIMER_CONTROL); 212 213 /* maximum value */ 214 __raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER); 215 216 while (get_jiffies_64() < waitjiffies) 217 udelay(10); 218 219 count = __raw_readl(twd_base + TWD_TIMER_COUNTER); 220 221 twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); 222 223 printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000, 224 (twd_timer_rate / 10000) % 100); 225 } 226 } 227 228 static irqreturn_t twd_handler(int irq, void *dev_id) 229 { 230 struct clock_event_device *evt = *(struct clock_event_device **)dev_id; 231 232 if (twd_timer_ack()) { 233 evt->event_handler(evt); 234 return IRQ_HANDLED; 235 } 236 237 return IRQ_NONE; 238 } 239 240 static void twd_get_clock(struct device_node *np) 241 { 242 int err; 243 244 if (np) 245 twd_clk = of_clk_get(np, 0); 246 else 247 twd_clk = clk_get_sys("smp_twd", NULL); 248 249 if (IS_ERR(twd_clk)) { 250 pr_err("smp_twd: clock not found %d\n", (int) PTR_ERR(twd_clk)); 251 return; 252 } 253 254 err = clk_prepare_enable(twd_clk); 255 if (err) { 256 pr_err("smp_twd: clock failed to prepare+enable: %d\n", err); 257 clk_put(twd_clk); 258 return; 259 } 260 261 twd_timer_rate = clk_get_rate(twd_clk); 262 } 263 264 /* 265 * Setup the local clock events for a CPU. 266 */ 267 static int __cpuinit twd_timer_setup(struct clock_event_device *clk) 268 { 269 struct clock_event_device **this_cpu_clk; 270 int cpu = smp_processor_id(); 271 272 /* 273 * If the basic setup for this CPU has been done before don't 274 * bother with the below. 275 */ 276 if (per_cpu(percpu_setup_called, cpu)) { 277 __raw_writel(0, twd_base + TWD_TIMER_CONTROL); 278 clockevents_register_device(*__this_cpu_ptr(twd_evt)); 279 enable_percpu_irq(clk->irq, 0); 280 return 0; 281 } 282 per_cpu(percpu_setup_called, cpu) = true; 283 284 twd_calibrate_rate(); 285 286 /* 287 * The following is done once per CPU the first time .setup() is 288 * called. 289 */ 290 __raw_writel(0, twd_base + TWD_TIMER_CONTROL); 291 292 clk->name = "local_timer"; 293 clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | 294 CLOCK_EVT_FEAT_C3STOP; 295 clk->rating = 350; 296 clk->set_mode = twd_set_mode; 297 clk->set_next_event = twd_set_next_event; 298 clk->irq = twd_ppi; 299 300 this_cpu_clk = __this_cpu_ptr(twd_evt); 301 *this_cpu_clk = clk; 302 303 clockevents_config_and_register(clk, twd_timer_rate, 304 0xf, 0xffffffff); 305 enable_percpu_irq(clk->irq, 0); 306 307 return 0; 308 } 309 310 static struct local_timer_ops twd_lt_ops __cpuinitdata = { 311 .setup = twd_timer_setup, 312 .stop = twd_timer_stop, 313 }; 314 315 static int __init twd_local_timer_common_register(struct device_node *np) 316 { 317 int err; 318 319 twd_evt = alloc_percpu(struct clock_event_device *); 320 if (!twd_evt) { 321 err = -ENOMEM; 322 goto out_free; 323 } 324 325 err = request_percpu_irq(twd_ppi, twd_handler, "twd", twd_evt); 326 if (err) { 327 pr_err("twd: can't register interrupt %d (%d)\n", twd_ppi, err); 328 goto out_free; 329 } 330 331 err = local_timer_register(&twd_lt_ops); 332 if (err) 333 goto out_irq; 334 335 twd_get_clock(np); 336 337 return 0; 338 339 out_irq: 340 free_percpu_irq(twd_ppi, twd_evt); 341 out_free: 342 iounmap(twd_base); 343 twd_base = NULL; 344 free_percpu(twd_evt); 345 346 return err; 347 } 348 349 int __init twd_local_timer_register(struct twd_local_timer *tlt) 350 { 351 if (twd_base || twd_evt) 352 return -EBUSY; 353 354 twd_ppi = tlt->res[1].start; 355 356 twd_base = ioremap(tlt->res[0].start, resource_size(&tlt->res[0])); 357 if (!twd_base) 358 return -ENOMEM; 359 360 return twd_local_timer_common_register(NULL); 361 } 362 363 #ifdef CONFIG_OF 364 const static struct of_device_id twd_of_match[] __initconst = { 365 { .compatible = "arm,cortex-a9-twd-timer", }, 366 { .compatible = "arm,cortex-a5-twd-timer", }, 367 { .compatible = "arm,arm11mp-twd-timer", }, 368 { }, 369 }; 370 371 void __init twd_local_timer_of_register(void) 372 { 373 struct device_node *np; 374 int err; 375 376 np = of_find_matching_node(NULL, twd_of_match); 377 if (!np) 378 return; 379 380 twd_ppi = irq_of_parse_and_map(np, 0); 381 if (!twd_ppi) { 382 err = -EINVAL; 383 goto out; 384 } 385 386 twd_base = of_iomap(np, 0); 387 if (!twd_base) { 388 err = -ENOMEM; 389 goto out; 390 } 391 392 err = twd_local_timer_common_register(np); 393 394 out: 395 WARN(err, "twd_local_timer_of_register failed (%d)\n", err); 396 } 397 #endif 398