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
32lpaddr_t platform_gic_cpu_interface_base = 0;
33lpaddr_t platform_gic_distributor_base = 0;
34
35/* A15 platforms don't need anything special done. */
36void 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 */
47size_t
48platform_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
62extern uint32_t timerirq;
63extern uint32_t cntfrq;
64
65void 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
96bool 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
109uint32_t platform_get_timer_interrupt(void){
110    return timerirq;
111}
112
113systime_t systime_now(void)
114{
115    return a15_gt_counter();
116}
117
118void systime_set_timeout(systime_t absolute_timeout)
119{
120    a15_gt_set_comparator(absolute_timeout);
121}
122
123void systime_set_timer(systime_t relative_timeout)
124{
125    systime_set_timeout(systime_now() + relative_timeout);
126}
127