60d691b932c3d9c13cf4dfb2771dcdd0a6e3f5d5
[barrelfish] / kernel / arch / armv7 / plat_a15mpcore.c
1 /**
2  * \file
3  * \brief Platform code for the Cortex-A15 MPCore.
4  */
5
6 /*
7  * Copyright (c) 2016 ETH Zurich.
8  * All rights reserved.
9  *
10  * This file is distributed under the terms in the attached LICENSE file.
11  * If you do not find this file, copies can be found by writing to:
12  * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #include <a15_gt.h>
16 #include <maps/a15mpcore_map.h>
17 #include <assert.h>
18 #include <cp15.h>
19 #include <gic.h>
20 #include <kernel.h>
21 #include <init.h>
22 #include <paging_kernel_arch.h>
23 #include <arch/arm/platform.h>
24 #include <systime.h>
25 #include <arch/armv7/irq.h>
26
27 #define MSG(format, ...) \
28     printk( LOG_NOTE, "CortexA15 platform: "format, ## __VA_ARGS__ )
29
30 /* These are called from the A9/A15 common GIC (interrupt controller) code. */
31
32 lpaddr_t platform_gic_cpu_interface_base = 0;
33 lpaddr_t platform_gic_distributor_base = 0;
34
35 /* A15 platforms don't need anything special done. */
36 void platform_revision_init(void)
37 {
38     platform_gic_cpu_interface_base =
39         A15MPCORE_GICC_OFFSET + platform_get_private_region();
40     platform_gic_distributor_base =
41        A15MPCORE_GICD_OFFSET + platform_get_private_region();
42 }
43
44 /*
45  * Return the core count from the interrupt controller
46  */
47 size_t
48 platform_get_core_count(void) {
49     return gic_cpu_count();
50 }
51
52 /* Timeslice counter uses the Non-secure Physical Timer. */
53
54 /* See TRM 8.2.3 */
55 /* This *should* be IRQ 30, for the non-secure timer, but GEM5 only
56  * provides the secure timer, even in NS mode.
57  * The timerirq parameter allows this to be overridden. */
58
59 /// For now, use secure timer
60 #define DEFAULT_TIMER_IRQ 29
61
62 extern uint32_t timerirq;
63 extern uint32_t cntfrq;
64
65 void platform_timer_init(int timeslice)
66 {
67     /* If there was a cntfrq parameter passed, then overwrite the current
68      * CNTFRQ register.  We need to do this if there was no bootloader to set
69      * it for us, as on the FVP simulators. */
70     if(cntfrq != 0) a15_gt_set_cntfrq(cntfrq);
71
72     systime_frequency = a15_gt_frequency();
73
74     /* The timeslice is in ms, so multiply by 1000000. */
75     kernel_timeslice = ns_to_systime(timeslice * 1000000);
76
77     MSG("System counter frequency is %lluHz.\n", systime_frequency);
78     MSG("Timeslice interrupt every %" PRIu64 " ticks (%dms).\n",
79             kernel_timeslice, timeslice);
80
81     a15_gt_init();
82
83     if(timerirq == 0) timerirq = DEFAULT_TIMER_IRQ;
84     MSG("Timer interrupt is %u\n", timerirq);
85
86     ///* Enable the interrupt. */
87     platform_enable_interrupt(timerirq, 0, 0, 0);
88
89     /* Set the first timeout. */
90     systime_set_timer(kernel_timeslice);
91
92     /* We use the system counter for timestamps, which doesn't need any
93      * further initialisation. */
94 }
95
96 bool platform_is_timer_interrupt(uint32_t irq)
97 {
98     if (irq == timerirq) {
99         a15_gt_mask_interrupt();
100
101         /* Reset the timeout. */
102         systime_set_timer(kernel_timeslice);
103         return 1;
104     }
105
106     return 0;
107 }
108
109 systime_t systime_now(void)
110 {
111     return a15_gt_counter();
112 }
113
114 void systime_set_timeout(systime_t absolute_timeout)
115 {
116     a15_gt_set_comparator(absolute_timeout);
117 }
118
119 void systime_set_timer(systime_t relative_timeout)
120 {
121     systime_set_timeout(systime_now() + relative_timeout);
122 }