uint32_t cntv_ctl= (1 << 1) /* IMASK */;
__asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r"(cntv_ctl));
- /* Set the compare value high, so that it doesn't trigger until somebody's
- * called a15_gt_timeout(). Note that the rollover period is guaranteed
- * to be at least 40 years. See ARMv7 ARM B8.1.1. */
- uint32_t cval_low= 0xffffffff, cval_high= 0xffffffff;
- __asm volatile("mcrr p15, 2, %0, %1, c14" : :
- "r"(cval_low), "r"(cval_high));
-
- /* CNTP_CTL - physical timer enabled, interrupt unmasked. */
- uint32_t cntp_ctl= (1 << 0) /* ENABLE */;
+ /* CNTP_CTL - physical timer enabled, interrupt masked. */
+ uint32_t cntp_ctl= (1 << 1) | (1 << 0) /* IMASK and ENABLE */;
__asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r"(cntp_ctl));
/* From this point, the current timestamp is available in CNTPCT at PL0 &
#include <init.h>
#include <paging_kernel_arch.h>
#include <platform.h>
+#include <systime.h>
#define MSG(format, ...) \
printk( LOG_NOTE, "CortexA15 platform: "format, ## __VA_ARGS__ )
/* Timeslice counter uses the Non-secure Physical Timer. */
/* See TRM 8.2.3 */
-/* This *should* be IRQ 30, for the non-secure timer, but GEM5 only
+/* This *should* be IRQ 30 (AT: why?), for the non-secure timer, but GEM5 only
* provides the secure timer, even in NS mode.
* The timerirq parameter allows this to be overridden. */
-#define DEFAULT_TIMER_IRQ 30
+#define DEFAULT_TIMER_IRQ 29
extern uint32_t timerirq;
extern uint32_t cntfrq;
* it for us, as on the FVP simulators. */
if(cntfrq != 0) a15_gt_set_cntfrq(cntfrq);
+ systime_frequency = a15_gt_frequency();
+
/* The timeslice is in ms, so divide by 1000. */
- timeslice_ticks= timeslice * a15_gt_frequency() / 1000;
+ timeslice_ticks = ns_to_systime(timeslice * 1000000);
- MSG("System counter frequency is %uHz.\n", a15_gt_frequency());
+ MSG("System counter frequency is %uHz.\n", systime_frequency);
MSG("Timeslice interrupt every %u ticks (%dms).\n",
timeslice_ticks, timeslice);
if(timerirq == 0) timerirq= DEFAULT_TIMER_IRQ;
MSG("Timer interrupt is %u\n", timerirq);
-
/* Enable the interrupt. */
gic_enable_interrupt(timerirq, 0, 0, 0, 0);
/* Set the first timeout. */
- a15_gt_timeout(timeslice_ticks);
+ systime_set_timeout(systime_now() + timeslice_ticks);
/* We use the system counter for timestamps, which doesn't need any
* further initialisation. */
timer_interrupt(uint32_t irq) {
if(irq == timerirq) {
gic_ack_irq(irq);
+ a15_gt_mask_interrupt();
/* Reset the timeout. */
- a15_gt_timeout(timeslice_ticks);
+ uint64_t now = systime_now();
+ systime_set_timeout(now + timeslice_ticks);
return 1;
}
return 0;
}
+
+systime_t systime_now(void)
+{
+ return a15_gt_counter();
+}
+
+void systime_set_timeout(systime_t timeout)
+{
+ a15_gt_set_comparator(timeout);
+}
__asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r"(t));
}
+static inline void a15_gt_set_control(uint32_t cntp_ctl) {
+ __asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r"(cntp_ctl));
+}
+
+static inline void a15_gt_set_comparator(systime_t timeout) {
+ uint32_t lo, hi;
+
+ lo = timeout;
+ hi = timeout >> 32;
+ __asm volatile("mcrr p15, 2, %0, %1, c14" : : "r" (lo), "r" (hi));
+ uint32_t cntp_ctl = (1 << 0) /* ENABLE*/;
+ a15_gt_set_control(cntp_ctl);
+}
+
+static inline void a15_gt_mask_interrupt(void) {
+ uint32_t cntp_ctl = (1 << 1) | (1 << 0) /* IMASK and ENABLE*/;
+ a15_gt_set_control(cntp_ctl);
+}
+
void a15_gt_init(void);