Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / arch / arm / cpu / armv7 / u8500 / timer.c
diff --git a/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/timer.c b/qemu/roms/u-boot/arch/arm/cpu/armv7/u8500/timer.c
new file mode 100644 (file)
index 0000000..6b74e13
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2010 Linaro Limited
+ * John Rigby <john.rigby@linaro.org>
+ *
+ * Based on original from Linux kernel source and
+ * internal ST-Ericsson U-Boot source.
+ * (C) Copyright 2009 Alessandro Rubini
+ * (C) Copyright 2010 ST-Ericsson
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * The MTU device has some interrupt control registers
+ * followed by 4 timers.
+ */
+
+/* The timers */
+struct u8500_mtu_timer {
+       u32 lr;                 /* Load value */
+       u32 cv;                 /* Current value */
+       u32 cr;                 /* Control reg */
+       u32 bglr;               /* ??? */
+};
+
+/* The MTU that contains the timers */
+struct u8500_mtu {
+       u32 imsc;               /* Interrupt mask set/clear */
+       u32 ris;                /* Raw interrupt status */
+       u32 mis;                /* Masked interrupt status */
+       u32 icr;                /* Interrupt clear register */
+       struct u8500_mtu_timer pt[4];
+};
+
+/* bits for the control register */
+#define MTU_CR_ONESHOT         0x01    /* if 0 = wraps reloading from BGLR */
+#define MTU_CR_32BITS          0x02
+
+#define MTU_CR_PRESCALE_1      0x00
+#define MTU_CR_PRESCALE_16     0x04
+#define MTU_CR_PRESCALE_256    0x08
+#define MTU_CR_PRESCALE_MASK   0x0c
+
+#define MTU_CR_PERIODIC                0x40    /* if 0 = free-running */
+#define MTU_CR_ENA             0x80
+
+/*
+ * The MTU is clocked at 133 MHz by default. (V1 and later)
+ */
+#define TIMER_CLOCK            (133 * 1000 * 1000 / 16)
+#define COUNT_TO_USEC(x)       ((x) * 16 / 133)
+#define USEC_TO_COUNT(x)       ((x) * 133 / 16)
+#define TICKS_PER_HZ           (TIMER_CLOCK / CONFIG_SYS_HZ)
+#define TICKS_TO_HZ(x)         ((x) / TICKS_PER_HZ)
+#define TIMER_LOAD_VAL         0xffffffff
+
+/*
+ * MTU timer to use (from 0 to 3).
+ */
+#define MTU_TIMER 2
+
+static struct u8500_mtu_timer *timer_base =
+       &((struct u8500_mtu *)U8500_MTU0_BASE_V1)->pt[MTU_TIMER];
+
+/* macro to read the 32 bit timer: since it decrements, we invert read value */
+#define READ_TIMER() (~readl(&timer_base->cv))
+
+/* Configure a free-running, auto-wrap counter with /16 prescaler */
+int timer_init(void)
+{
+       writel(MTU_CR_ENA | MTU_CR_PRESCALE_16 | MTU_CR_32BITS,
+              &timer_base->cr);
+       return 0;
+}
+
+ulong get_timer_masked(void)
+{
+       /* current tick value */
+       ulong now = TICKS_TO_HZ(READ_TIMER());
+
+       if (now >= gd->arch.lastinc) {  /* normal (non rollover) */
+               gd->arch.tbl += (now - gd->arch.lastinc);
+       } else {                        /* rollover */
+               gd->arch.tbl += (TICKS_TO_HZ(TIMER_LOAD_VAL) -
+                                       gd->arch.lastinc) + now;
+       }
+       gd->arch.lastinc = now;
+       return gd->arch.tbl;
+}
+
+/* Delay x useconds */
+void __udelay(ulong usec)
+{
+       long tmo = usec * (TIMER_CLOCK / 1000) / 1000;
+       ulong now, last = READ_TIMER();
+
+       while (tmo > 0) {
+               now = READ_TIMER();
+               if (now > last) /* normal (non rollover) */
+                       tmo -= now - last;
+               else            /* rollover */
+                       tmo -= TIMER_LOAD_VAL - last + now;
+               last = now;
+       }
+}
+
+ulong get_timer(ulong base)
+{
+       return get_timer_masked() - base;
+}
+
+/*
+ * Emulation of Power architecture long long timebase.
+ *
+ * TODO: Support gd->arch.tbu for real long long timebase.
+ */
+unsigned long long get_ticks(void)
+{
+       return get_timer(0);
+}
+
+/*
+ * Emulation of Power architecture timebase.
+ * NB: Low resolution compared to Power tbclk.
+ */
+ulong get_tbclk(void)
+{
+       return CONFIG_SYS_HZ;
+}