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