int rthal_timer_request(void (*handler) (void), int cpu) { unsigned long flags; if (cpu > 0) goto out; flags = rthal_critical_enter(NULL); rthal_irq_release(RTHAL_TIMER_IRQ); ipipe_tune_timer(0, IPIPE_GRAB_TIMER); if (rthal_irq_request(RTHAL_TIMER_IRQ, (rthal_irq_handler_t) handler, NULL, NULL) < 0) { rthal_critical_exit(flags); return -EINVAL; } if (rthal_irq_request(RTHAL_HOST_TIMER_IRQ, &rthal_adjust_before_relay, NULL, NULL) < 0) { rthal_critical_exit(flags); return -EINVAL; } rthal_critical_exit(flags); rthal_timer_set_irq(RTHAL_TIMER_IRQ); out: return 0; }
unsigned long rthal_timer_calibrate(void) { unsigned long v, flags; rthal_time_t t, dt; int i; v = RTHAL_COMPAT_TIMERFREQ / HZ; flags = rthal_critical_enter(NULL); rthal_timer_program_shot(v); t = rthal_rdtsc(); for (i = 0; i < 100; i++) rthal_timer_program_shot(v); dt = (rthal_rdtsc() - t); rthal_critical_exit(flags); #ifdef CONFIG_IPIPE_TRACE_IRQSOFF /* Reset the max trace, since it contains the calibration time now. */ rthal_trace_max_reset(); #endif /* CONFIG_IPIPE_TRACE_IRQSOFF */ return rthal_ulldiv(dt, i + 5, NULL); }
unsigned long rthal_timer_calibrate(void) { unsigned long long start, end, sum = 0, sum_sq = 0; volatile unsigned const_delay = rthal_clockfreq_arg / HZ; unsigned long result, flags, tsc_lat; unsigned int delay = const_delay; long long diff; int i, j; flags = rthal_critical_enter(NULL); /* * Hw interrupts off, other CPUs quiesced, no migration * possible. We can now fiddle with the timer chip (per-cpu * local or global, rthal_timer_program_shot() will handle * this transparently via the I-pipe). */ steal_timer(1); force_oneshot_hw_mode(); rthal_read_tsc(start); barrier(); rthal_read_tsc(end); tsc_lat = end - start; barrier(); for (i = 0; i < RTHAL_CALIBRATE_LOOPS; i++) { flush_cache_all(); for (j = 0; j < RTHAL_CALIBRATE_LOOPS; j++) { rthal_read_tsc(start); barrier(); #if IPIPE_CORE_APIREV < 2 rthal_timer_program_shot( rthal_nodiv_imuldiv_ceil(delay, rthal_tsc_to_timer)); #else rthal_timer_program_shot(delay); #endif barrier(); rthal_read_tsc(end); diff = end - start - tsc_lat; if (diff > 0) { sum += diff; sum_sq += diff * diff; } } } restore_normal_hw_mode(); rthal_critical_exit(flags); /* Use average + standard deviation as timer programming latency. */ do_div(sum, RTHAL_CALIBRATE_LOOPS * RTHAL_CALIBRATE_LOOPS); do_div(sum_sq, RTHAL_CALIBRATE_LOOPS * RTHAL_CALIBRATE_LOOPS); result = sum + int_sqrt(sum_sq - sum * sum) + 1; return result; }
static void rthal_timer_set_periodic(void) { unsigned long flags; flags = rthal_critical_enter(rthal_critical_sync); rthal_sync_op = RTHAL_SET_PERIODIC; restore_normal_hw_mode(); rthal_critical_exit(flags); }
static void rthal_timer_set_irq(unsigned tick_irq) { unsigned long flags; flags = rthal_critical_enter(&rthal_set_itv); rthal_tick_irq = tick_irq; rthal_set_itv(); rthal_critical_exit(flags); }
static void rthal_timer_set_periodic(void) { unsigned long flags; flags = rthal_critical_enter(&rthal_critical_sync); rthal_sync_op = RTHAL_SET_PERIODIC; rthal_setup_periodic_dec(); rthal_disarm_decr(0); rthal_critical_exit(flags); }
void rthal_timer_release(int cpu) { unsigned long flags; if (cpu > 0) return; rthal_timer_set_irq(RTHAL_HOST_TIMER_IRQ); ipipe_tune_timer(0, IPIPE_RESET_TIMER); flags = rthal_critical_enter(NULL); rthal_irq_release(RTHAL_TIMER_IRQ); rthal_irq_release(RTHAL_HOST_TIMER_IRQ); rthal_critical_exit(flags); }
static void rthal_timer_set_oneshot(int rt_mode) { unsigned long flags; flags = rthal_critical_enter(rthal_critical_sync); if (rt_mode) { rthal_sync_op = RTHAL_SET_ONESHOT_XENOMAI; rthal_setup_oneshot_dec(); rthal_disarm_decr(1); } else { rthal_sync_op = RTHAL_SET_ONESHOT_LINUX; rthal_setup_oneshot_dec(); rthal_disarm_decr(0); /* We need to keep the timing cycle alive for the kernel. */ rthal_trigger_irq(RTHAL_TIMER_IRQ); } rthal_critical_exit(flags); }
unsigned long rthal_timer_calibrate(void) { unsigned long flags, delay; rthal_time_t t, dt; int i; delay = RTHAL_CPU_FREQ; /* 1s */ flags = rthal_critical_enter(NULL); t = rthal_rdtsc(); for (i = 0; i < 10000; i++) rthal_timer_program_shot(delay); dt = rthal_rdtsc() - t; rthal_critical_exit(flags); return rthal_imuldiv(dt, 100000, RTHAL_CPU_FREQ); }