3 * \brief Platform code for the Cortex-A9 MPCore.
7 * Copyright (c) 2016 ETH Zurich.
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.
15 #include <maps/a9mpcore_map.h>
19 #include <dev/cortex_a9_pit_dev.h>
24 #include <paging_kernel_arch.h>
25 #include <arch/arm/platform.h>
27 #include <arch/armv7/irq.h>
29 #define MSG(format, ...) \
30 printk( LOG_NOTE, "CortexA9 platform: "format, ## __VA_ARGS__ )
32 /* These are called from the A9/A15 common GIC (interrupt controller) code. */
34 lpaddr_t platform_gic_cpu_interface_base = A9MPCORE_GIC_CPU_OFFSET;
35 lpaddr_t platform_gic_distributor_base = A9MPCORE_GIC_DIST_OFFSET;
37 /* These are for A9-specific devices, so are only used here. */
40 platform_get_scu_address(void) {
41 assert(paging_mmu_enabled());
42 return platform_get_private_region() + A9MPCORE_SCU_OFFSET;
46 platform_get_gt_address(void) {
47 assert(paging_mmu_enabled());
48 return platform_get_private_region() + A9MPCORE_TIMER_GBL_OFFSET;
52 platform_get_lt_address(void) {
53 assert(paging_mmu_enabled());
54 return platform_get_private_region() + A9MPCORE_TIMER_LCL_OFFSET;
57 /* On the A9, we need to initialise the snoop control unit. */
59 platform_revision_init(void) {
60 assert(paging_mmu_enabled());
61 a9_scu_init(platform_get_scu_address());
62 platform_gic_cpu_interface_base += platform_get_private_region();
63 platform_gic_distributor_base += platform_get_private_region();
64 if(platform_get_core_count() > 1) a9_scu_enable();
68 * Return the core count from the interrupt controller
71 platform_get_core_count(void) {
72 return gic_cpu_count();
75 static cortex_a9_pit_t tsc;
78 #define GLOBAL_TIMER_IRQ 27
80 void platform_timer_init(int timeslice)
83 /* Time slice counter: use the Cortex-A9 Local Timer
84 (see Cortex-A9 MPCore TRM 4.1). */
86 paging_map_device(platform_get_lt_address(), A9MPCORE_TIMER_LCL_SIZE);
87 cortex_a9_pit_initialize(&tsc, (mackerel_addr_t)lcl_base);
89 /* Global timer: use the Cortex-A9 Global Timer
90 (see Cortex-A9 MPCore TRM 4.3). */
91 a9_gt_init(platform_get_gt_address());
92 err = platform_enable_interrupt(GLOBAL_TIMER_IRQ, 0, 0, 0);
95 "Failed to enable timer interrupt. Will continue without...");
97 /* Discover the clock rate. */
99 assert(systime_frequency != 0);
101 MSG("System counter frequency is %lluHz.\n", systime_frequency);
102 /* Set kernel timeslice value, timeslice is in ms. */
103 kernel_timeslice = ns_to_systime(timeslice * 1000000);
104 MSG("Timeslice interrupt every %llu system ticks (%dms).\n", kernel_timeslice, timeslice);
105 systime_set_timer(kernel_timeslice);
108 bool platform_is_timer_interrupt(uint32_t irq)
110 if (irq == GLOBAL_TIMER_IRQ) {
118 uint32_t platform_get_timer_interrupt(void){
119 return GLOBAL_TIMER_IRQ;
122 systime_t systime_now(void)
127 void systime_set_timeout(systime_t absolute_timeout)
129 a9_gt_set_comparator(absolute_timeout);
132 void systime_set_timer(systime_t relative_timeout)
134 systime_set_timeout(systime_now() + relative_timeout);