2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) ARM Limited, 2014
7 * Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
13 #include <asm/gic_common.h>
14 #include <asm/sysregs.h>
15 #include <inmates/inmate.h>
16 #include <mach/timer.h>
18 #define BEATS_PER_SEC 10
19 #define TICKS_PER_BEAT (TIMER_FREQ / BEATS_PER_SEC)
21 static volatile u64 expected_ticks;
23 static void timer_arm(u64 timeout)
25 arm_write_sysreg(CNTV_TVAL_EL0, timeout);
26 arm_write_sysreg(CNTV_CTL_EL0, 1);
29 static u64 get_actual_ticks(void)
33 arm_read_sysreg(CNTPCT, pct64);
37 static unsigned long emul_division(u64 val, u64 div)
39 unsigned long cnt = 0;
48 static inline unsigned long ticks_to_ns(u64 ticks)
50 return emul_division(ticks * 1000, TIMER_FREQ / 1000 / 1000);
53 static void handle_IRQ(unsigned int irqn)
55 static u64 min_delta = ~0ULL, max_delta = 0;
58 if (irqn != TIMER_IRQ)
61 delta = get_actual_ticks() - expected_ticks;
62 if (delta < min_delta)
64 if (delta > max_delta)
67 printk("Timer fired, jitter: %6ld ns, min: %6ld ns, max: %6ld ns\n",
68 ticks_to_ns(delta), ticks_to_ns(min_delta),
69 ticks_to_ns(max_delta));
71 #ifdef CONFIG_ARCH_SUN7I
72 /* let green LED on Banana Pi blink */
73 #define LED_REG (void *)(0x1c20800 + 7*0x24 + 0x10)
74 mmio_write32(LED_REG, mmio_read32(LED_REG) ^ (1<<24));
77 expected_ticks = get_actual_ticks() + TICKS_PER_BEAT;
78 timer_arm(TICKS_PER_BEAT);
81 void inmate_main(void)
83 printk("Initializing the GIC...\n");
84 gic_setup(handle_IRQ);
85 gic_enable_irq(TIMER_IRQ);
87 printk("Initializing the timer...\n");
88 expected_ticks = get_actual_ticks() + TICKS_PER_BEAT;
89 timer_arm(TICKS_PER_BEAT);
92 asm volatile("wfi" : : : "memory");