1/* 2 * Based on arm clockevents implementation and old bfin time tick. 3 * 4 * Copyright 2008-2009 Analog Devics Inc. 5 * 2008 GeoTechnologies 6 * Vitja Makarov 7 * 8 * Licensed under the GPL-2 9 */ 10 11#include <linux/module.h> 12#include <linux/profile.h> 13#include <linux/interrupt.h> 14#include <linux/time.h> 15#include <linux/timex.h> 16#include <linux/irq.h> 17#include <linux/clocksource.h> 18#include <linux/clockchips.h> 19#include <linux/cpufreq.h> 20 21#include <asm/blackfin.h> 22#include <asm/time.h> 23#include <asm/gptimers.h> 24#include <asm/nmi.h> 25 26 27#if defined(CONFIG_CYCLES_CLOCKSOURCE) 28 29static notrace cycle_t bfin_read_cycles(struct clocksource *cs) 30{ 31#ifdef CONFIG_CPU_FREQ 32 return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod); 33#else 34 return get_cycles(); 35#endif 36} 37 38static struct clocksource bfin_cs_cycles = { 39 .name = "bfin_cs_cycles", 40 .rating = 400, 41 .read = bfin_read_cycles, 42 .mask = CLOCKSOURCE_MASK(64), 43 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 44}; 45 46static inline unsigned long long bfin_cs_cycles_sched_clock(void) 47{ 48 return clocksource_cyc2ns(bfin_read_cycles(&bfin_cs_cycles), 49 bfin_cs_cycles.mult, bfin_cs_cycles.shift); 50} 51 52static int __init bfin_cs_cycles_init(void) 53{ 54 if (clocksource_register_hz(&bfin_cs_cycles, get_cclk())) 55 panic("failed to register clocksource"); 56 57 return 0; 58} 59#else 60# define bfin_cs_cycles_init() 61#endif 62 63#ifdef CONFIG_GPTMR0_CLOCKSOURCE 64 65void __init setup_gptimer0(void) 66{ 67 disable_gptimers(TIMER0bit); 68 69#ifdef CONFIG_BF60x 70 bfin_write16(TIMER_DATA_IMSK, 0); 71 set_gptimer_config(TIMER0_id, TIMER_OUT_DIS 72 | TIMER_MODE_PWM_CONT | TIMER_PULSE_HI | TIMER_IRQ_PER); 73#else 74 set_gptimer_config(TIMER0_id, \ 75 TIMER_OUT_DIS | TIMER_PERIOD_CNT | TIMER_MODE_PWM); 76#endif 77 set_gptimer_period(TIMER0_id, -1); 78 set_gptimer_pwidth(TIMER0_id, -2); 79 SSYNC(); 80 enable_gptimers(TIMER0bit); 81} 82 83static cycle_t bfin_read_gptimer0(struct clocksource *cs) 84{ 85 return bfin_read_TIMER0_COUNTER(); 86} 87 88static struct clocksource bfin_cs_gptimer0 = { 89 .name = "bfin_cs_gptimer0", 90 .rating = 350, 91 .read = bfin_read_gptimer0, 92 .mask = CLOCKSOURCE_MASK(32), 93 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 94}; 95 96static inline unsigned long long bfin_cs_gptimer0_sched_clock(void) 97{ 98 return clocksource_cyc2ns(bfin_read_TIMER0_COUNTER(), 99 bfin_cs_gptimer0.mult, bfin_cs_gptimer0.shift); 100} 101 102static int __init bfin_cs_gptimer0_init(void) 103{ 104 setup_gptimer0(); 105 106 if (clocksource_register_hz(&bfin_cs_gptimer0, get_sclk())) 107 panic("failed to register clocksource"); 108 109 return 0; 110} 111#else 112# define bfin_cs_gptimer0_init() 113#endif 114 115#if defined(CONFIG_GPTMR0_CLOCKSOURCE) || defined(CONFIG_CYCLES_CLOCKSOURCE) 116/* prefer to use cycles since it has higher rating */ 117notrace unsigned long long sched_clock(void) 118{ 119#if defined(CONFIG_CYCLES_CLOCKSOURCE) 120 return bfin_cs_cycles_sched_clock(); 121#else 122 return bfin_cs_gptimer0_sched_clock(); 123#endif 124} 125#endif 126 127#if defined(CONFIG_TICKSOURCE_GPTMR0) 128static int bfin_gptmr0_set_next_event(unsigned long cycles, 129 struct clock_event_device *evt) 130{ 131 disable_gptimers(TIMER0bit); 132 133 /* it starts counting three SCLK cycles after the TIMENx bit is set */ 134 set_gptimer_pwidth(TIMER0_id, cycles - 3); 135 enable_gptimers(TIMER0bit); 136 return 0; 137} 138 139static int bfin_gptmr0_set_periodic(struct clock_event_device *evt) 140{ 141#ifndef CONFIG_BF60x 142 set_gptimer_config(TIMER0_id, 143 TIMER_OUT_DIS | TIMER_IRQ_ENA | 144 TIMER_PERIOD_CNT | TIMER_MODE_PWM); 145#else 146 set_gptimer_config(TIMER0_id, 147 TIMER_OUT_DIS | TIMER_MODE_PWM_CONT | 148 TIMER_PULSE_HI | TIMER_IRQ_PER); 149#endif 150 151 set_gptimer_period(TIMER0_id, get_sclk() / HZ); 152 set_gptimer_pwidth(TIMER0_id, get_sclk() / HZ - 1); 153 enable_gptimers(TIMER0bit); 154 return 0; 155} 156 157static int bfin_gptmr0_set_oneshot(struct clock_event_device *evt) 158{ 159 disable_gptimers(TIMER0bit); 160#ifndef CONFIG_BF60x 161 set_gptimer_config(TIMER0_id, 162 TIMER_OUT_DIS | TIMER_IRQ_ENA | TIMER_MODE_PWM); 163#else 164 set_gptimer_config(TIMER0_id, 165 TIMER_OUT_DIS | TIMER_MODE_PWM | TIMER_PULSE_HI | 166 TIMER_IRQ_WID_DLY); 167#endif 168 169 set_gptimer_period(TIMER0_id, 0); 170 return 0; 171} 172 173static int bfin_gptmr0_shutdown(struct clock_event_device *evt) 174{ 175 disable_gptimers(TIMER0bit); 176 return 0; 177} 178 179static void bfin_gptmr0_ack(void) 180{ 181 clear_gptimer_intr(TIMER0_id); 182} 183 184static void __init bfin_gptmr0_init(void) 185{ 186 disable_gptimers(TIMER0bit); 187} 188 189#ifdef CONFIG_CORE_TIMER_IRQ_L1 190__attribute__((l1_text)) 191#endif 192irqreturn_t bfin_gptmr0_interrupt(int irq, void *dev_id) 193{ 194 struct clock_event_device *evt = dev_id; 195 smp_mb(); 196 /* 197 * We want to ACK before we handle so that we can handle smaller timer 198 * intervals. This way if the timer expires again while we're handling 199 * things, we're more likely to see that 2nd int rather than swallowing 200 * it by ACKing the int at the end of this handler. 201 */ 202 bfin_gptmr0_ack(); 203 evt->event_handler(evt); 204 return IRQ_HANDLED; 205} 206 207static struct irqaction gptmr0_irq = { 208 .name = "Blackfin GPTimer0", 209 .flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_PERCPU, 210 .handler = bfin_gptmr0_interrupt, 211}; 212 213static struct clock_event_device clockevent_gptmr0 = { 214 .name = "bfin_gptimer0", 215 .rating = 300, 216 .irq = IRQ_TIMER0, 217 .shift = 32, 218 .features = CLOCK_EVT_FEAT_PERIODIC | 219 CLOCK_EVT_FEAT_ONESHOT, 220 .set_next_event = bfin_gptmr0_set_next_event, 221 .set_state_shutdown = bfin_gptmr0_shutdown, 222 .set_state_periodic = bfin_gptmr0_set_periodic, 223 .set_state_oneshot = bfin_gptmr0_set_oneshot, 224}; 225 226static void __init bfin_gptmr0_clockevent_init(struct clock_event_device *evt) 227{ 228 unsigned long clock_tick; 229 230 clock_tick = get_sclk(); 231 evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift); 232 evt->max_delta_ns = clockevent_delta2ns(-1, evt); 233 evt->min_delta_ns = clockevent_delta2ns(100, evt); 234 235 evt->cpumask = cpumask_of(0); 236 237 clockevents_register_device(evt); 238} 239#endif /* CONFIG_TICKSOURCE_GPTMR0 */ 240 241#if defined(CONFIG_TICKSOURCE_CORETMR) 242/* per-cpu local core timer */ 243DEFINE_PER_CPU(struct clock_event_device, coretmr_events); 244 245static int bfin_coretmr_set_next_event(unsigned long cycles, 246 struct clock_event_device *evt) 247{ 248 bfin_write_TCNTL(TMPWR); 249 CSYNC(); 250 bfin_write_TCOUNT(cycles); 251 CSYNC(); 252 bfin_write_TCNTL(TMPWR | TMREN); 253 return 0; 254} 255 256static int bfin_coretmr_set_periodic(struct clock_event_device *evt) 257{ 258 unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1); 259 260 bfin_write_TCNTL(TMPWR); 261 CSYNC(); 262 bfin_write_TSCALE(TIME_SCALE - 1); 263 bfin_write_TPERIOD(tcount); 264 bfin_write_TCOUNT(tcount); 265 CSYNC(); 266 bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD); 267 return 0; 268} 269 270static int bfin_coretmr_set_oneshot(struct clock_event_device *evt) 271{ 272 bfin_write_TCNTL(TMPWR); 273 CSYNC(); 274 bfin_write_TSCALE(TIME_SCALE - 1); 275 bfin_write_TPERIOD(0); 276 bfin_write_TCOUNT(0); 277 return 0; 278} 279 280static int bfin_coretmr_shutdown(struct clock_event_device *evt) 281{ 282 bfin_write_TCNTL(0); 283 CSYNC(); 284 return 0; 285} 286 287void bfin_coretmr_init(void) 288{ 289 /* power up the timer, but don't enable it just yet */ 290 bfin_write_TCNTL(TMPWR); 291 CSYNC(); 292 293 /* the TSCALE prescaler counter. */ 294 bfin_write_TSCALE(TIME_SCALE - 1); 295 bfin_write_TPERIOD(0); 296 bfin_write_TCOUNT(0); 297 298 CSYNC(); 299} 300 301#ifdef CONFIG_CORE_TIMER_IRQ_L1 302__attribute__((l1_text)) 303#endif 304 305irqreturn_t bfin_coretmr_interrupt(int irq, void *dev_id) 306{ 307 int cpu = smp_processor_id(); 308 struct clock_event_device *evt = &per_cpu(coretmr_events, cpu); 309 310 smp_mb(); 311 evt->event_handler(evt); 312 313 touch_nmi_watchdog(); 314 315 return IRQ_HANDLED; 316} 317 318static struct irqaction coretmr_irq = { 319 .name = "Blackfin CoreTimer", 320 .flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_PERCPU, 321 .handler = bfin_coretmr_interrupt, 322}; 323 324void bfin_coretmr_clockevent_init(void) 325{ 326 unsigned long clock_tick; 327 unsigned int cpu = smp_processor_id(); 328 struct clock_event_device *evt = &per_cpu(coretmr_events, cpu); 329 330#ifdef CONFIG_SMP 331 evt->broadcast = smp_timer_broadcast; 332#endif 333 334 evt->name = "bfin_core_timer"; 335 evt->rating = 350; 336 evt->irq = -1; 337 evt->shift = 32; 338 evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; 339 evt->set_next_event = bfin_coretmr_set_next_event; 340 evt->set_state_shutdown = bfin_coretmr_shutdown; 341 evt->set_state_periodic = bfin_coretmr_set_periodic; 342 evt->set_state_oneshot = bfin_coretmr_set_oneshot; 343 344 clock_tick = get_cclk() / TIME_SCALE; 345 evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift); 346 evt->max_delta_ns = clockevent_delta2ns(-1, evt); 347 evt->min_delta_ns = clockevent_delta2ns(100, evt); 348 349 evt->cpumask = cpumask_of(cpu); 350 351 clockevents_register_device(evt); 352} 353#endif /* CONFIG_TICKSOURCE_CORETMR */ 354 355 356void read_persistent_clock(struct timespec *ts) 357{ 358 time_t secs_since_1970 = (365 * 37 + 9) * 24 * 60 * 60; /* 1 Jan 2007 */ 359 ts->tv_sec = secs_since_1970; 360 ts->tv_nsec = 0; 361} 362 363void __init time_init(void) 364{ 365 366#ifdef CONFIG_RTC_DRV_BFIN 367 /* [#2663] hack to filter junk RTC values that would cause 368 * userspace to have to deal with time values greater than 369 * 2^31 seconds (which uClibc cannot cope with yet) 370 */ 371 if ((bfin_read_RTC_STAT() & 0xC0000000) == 0xC0000000) { 372 printk(KERN_NOTICE "bfin-rtc: invalid date; resetting\n"); 373 bfin_write_RTC_STAT(0); 374 } 375#endif 376 377 bfin_cs_cycles_init(); 378 bfin_cs_gptimer0_init(); 379 380#if defined(CONFIG_TICKSOURCE_CORETMR) 381 bfin_coretmr_init(); 382 setup_irq(IRQ_CORETMR, &coretmr_irq); 383 bfin_coretmr_clockevent_init(); 384#endif 385 386#if defined(CONFIG_TICKSOURCE_GPTMR0) 387 bfin_gptmr0_init(); 388 setup_irq(IRQ_TIMER0, &gptmr0_irq); 389 gptmr0_irq.dev_id = &clockevent_gptmr0; 390 bfin_gptmr0_clockevent_init(&clockevent_gptmr0); 391#endif 392 393#if !defined(CONFIG_TICKSOURCE_CORETMR) && !defined(CONFIG_TICKSOURCE_GPTMR0) 394# error at least one clock event device is required 395#endif 396} 397