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