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, Universitaetstr. 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 <platform.h> 24#include <systime.h> 25 26#define MSG(format, ...) \ 27 printk( LOG_NOTE, "CortexA15 platform: "format, ## __VA_ARGS__ ) 28 29/* These are called from the A9/A15 common GIC (interrupt controller) code. */ 30 31lpaddr_t 32platform_get_distributor_address(void) { 33 assert(paging_mmu_enabled()); 34 return platform_get_private_region() + A15MPCORE_GICD_OFFSET; 35} 36 37lpaddr_t 38platform_get_gic_cpu_address(void) { 39 assert(paging_mmu_enabled()); 40 return platform_get_private_region() + A15MPCORE_GICC_OFFSET; 41} 42 43/* A15 platforms don't need anything special done. */ 44void 45platform_revision_init(void) { 46} 47 48/* 49 * Return the core count from the interrupt controller 50 */ 51size_t 52platform_get_core_count(void) { 53 return gic_cpu_count(); 54} 55 56/* Timeslice counter uses the Non-secure Physical Timer. */ 57 58/* See TRM 8.2.3 */ 59/* This *should* be IRQ 30, for the non-secure timer, but GEM5 only 60 * provides the secure timer, even in NS mode. 61 * The timerirq parameter allows this to be overridden. */ 62 63/// For now, use secure timer 64#define DEFAULT_TIMER_IRQ 29 65 66extern uint32_t timerirq; 67extern uint32_t cntfrq; 68 69void 70timers_init(int timeslice) { 71 /* If there was a cntfrq parameter passed, then overwrite the current 72 * CNTFRQ register. We need to do this if there was no bootloader to set 73 * it for us, as on the FVP simulators. */ 74 if(cntfrq != 0) a15_gt_set_cntfrq(cntfrq); 75 76 systime_frequency = a15_gt_frequency(); 77 78 /* The timeslice is in ms, so divide by 1000. */ 79 kernel_timeslice = ns_to_systime(timeslice * 1000000); 80 81 MSG("System counter frequency is %uHz.\n", systime_frequency); 82 MSG("Timeslice interrupt every %u ticks (%dms).\n", 83 kernel_timeslice, timeslice); 84 85 a15_gt_init(); 86 87 if(timerirq == 0) timerirq= DEFAULT_TIMER_IRQ; 88 MSG("Timer interrupt is %u\n", timerirq); 89 90 /* Enable the interrupt. */ 91 gic_enable_interrupt(timerirq, 0, 0, 0, 0); 92 93 /* Set the first timeout. */ 94 systime_set_timeout(systime_now() + kernel_timeslice); 95 96 /* We use the system counter for timestamps, which doesn't need any 97 * further initialisation. */ 98} 99 100uint64_t 101timestamp_read(void) { 102 return a15_gt_counter(); 103} 104 105uint32_t 106timestamp_freq(void) { 107 return a15_gt_frequency(); 108} 109 110bool timer_interrupt(uint32_t irq) 111{ 112 if (irq == timerirq) { 113 gic_ack_irq(irq); 114 a15_gt_mask_interrupt(); 115 116 /* Reset the timeout. */ 117 uint64_t now = systime_now(); 118 systime_set_timeout(now + kernel_timeslice); 119 return 1; 120 } 121 122 return 0; 123} 124 125systime_t systime_now(void) 126{ 127 return a15_gt_counter(); 128} 129 130void systime_set_timeout(systime_t timeout) 131{ 132 a15_gt_set_comparator(timeout); 133} 134