CSYNC();
}
-static unsigned long __init bfin_clockevent_check(void)
-{
- setup_irq(IRQ_CORETMR, &bfin_timer_irq);
- return get_cclk() / TIME_SCALE;
-}
-
-void __init setup_core_timer(void)
+#ifdef CONFIG_CORE_TIMER_IRQ_L1
+__attribute__((l1_text))
+#endif
+irqreturn_t bfin_coretmr_interrupt(int irq, void *dev_id)
{
- bfin_timer_init();
- bfin_timer_set_mode(CLOCK_EVT_MODE_PERIODIC, NULL);
-}
-#endif /* CONFIG_TICKSOURCE_GPTMR0 */
+ int cpu = smp_processor_id();
+ struct clock_event_device *evt = &per_cpu(coretmr_events, cpu);
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
- struct clock_event_device *evt = dev_id;
smp_mb();
evt->event_handler(evt);
- bfin_timer_ack();
- return IRQ_HANDLED;
-}
-
-static int __init bfin_clockevent_init(void)
-{
- unsigned long timer_clk;
- timer_clk = bfin_clockevent_check();
+ touch_nmi_watchdog();
- bfin_timer_init();
+ return IRQ_HANDLED;
+}
- clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift);
- clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin);
- clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin);
- clockevent_bfin.cpumask = cpumask_of(0);
- clockevents_register_device(&clockevent_bfin);
+static struct irqaction coretmr_irq = {
+ .name = "Blackfin CoreTimer",
+ .flags = IRQF_DISABLED | IRQF_TIMER | \
+ IRQF_IRQPOLL | IRQF_PERCPU,
+ .handler = bfin_coretmr_interrupt,
+};
- return 0;
+void bfin_coretmr_clockevent_init(void)
+{
+ unsigned long clock_tick;
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *evt = &per_cpu(coretmr_events, cpu);
+
+ evt->name = "bfin_core_timer";
+ evt->rating = 350;
+ evt->irq = -1;
+ evt->shift = 32;
+ evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ evt->set_next_event = bfin_coretmr_set_next_event;
+ evt->set_mode = bfin_coretmr_set_mode;
+
+ clock_tick = get_cclk() / TIME_SCALE;
+ evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift);
+ evt->max_delta_ns = clockevent_delta2ns(-1, evt);
+ evt->min_delta_ns = clockevent_delta2ns(100, evt);
+
+ evt->cpumask = cpumask_of(cpu);
+
+ clockevents_register_device(evt);
}
+#endif /* CONFIG_TICKSOURCE_CORETMR */
+
- void __init time_init(void)
+ void read_persistent_clock(struct timespec *ts)
{
time_t secs_since_1970 = (365 * 37 + 9) * 24 * 60 * 60; /* 1 Jan 2007 */
+ ts->tv_sec = secs_since_1970;
+ ts->tv_nsec = 0;
+ }
+
+ void __init time_init(void)
+ {
#ifdef CONFIG_RTC_DRV_BFIN
/* [#2663] hack to filter junk RTC values that would cause
}
#endif
- /* Initialize xtime. From now on, xtime is updated with timer interrupts */
- xtime.tv_sec = secs_since_1970;
- xtime.tv_nsec = 0;
- set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
-
bfin_cs_cycles_init();
bfin_cs_gptimer0_init();
- bfin_clockevent_init();
+
+#if defined(CONFIG_TICKSOURCE_CORETMR)
+ bfin_coretmr_init();
+ setup_irq(IRQ_CORETMR, &coretmr_irq);
+ bfin_coretmr_clockevent_init();
+#endif
+
+#if defined(CONFIG_TICKSOURCE_GPTMR0)
+ bfin_gptmr0_init();
+ setup_irq(IRQ_TIMER0, &gptmr0_irq);
+ gptmr0_irq.dev_id = &clockevent_gptmr0;
+ bfin_gptmr0_clockevent_init(&clockevent_gptmr0);
+#endif
+
+#if !defined(CONFIG_TICKSOURCE_CORETMR) && !defined(CONFIG_TICKSOURCE_GPTMR0)
+# error at least one clock event device is required
+#endif
}