summaryrefslogtreecommitdiff
path: root/framework
diff options
context:
space:
mode:
authorSoby Mathew <soby.mathew@arm.com>2015-11-02 10:56:26 +0000
committerSoby Mathew <soby.mathew@arm.com>2016-02-04 16:59:18 +0000
commitb122cb138c83402a1a5f1b9b04c41bf48ff7cae9 (patch)
tree1b268ab206a73d8f1644e0e374059944deac7982 /framework
parent6c89ade9b2251c81a06759ca3189c8c9e70d0588 (diff)
Introduce the ARM GIC layer and refactor GICv2 driver
The TFTF assumed that the GIC driver architecture is v2.0 and made inherent assumptions about the same in the framework. In order to add support for GICv3 systems, this assumption needs to be removed and a new ARM GIC layer is introduced which abstracts the GIC Architecture details. The `arm_gic.c` and `arm_gic.h` contain the prototypes and definitions for this new layer. Also the GICv2 driver is refactored such that all the functionality is contained within the driver and the driver is accessed through well defined API. This essentially means that the GICv2 specific functionality present earlier in the interrupt framework and SGI framework is now removed. Also certain functionality of GICv2 like clearing the interrupt target register (GICD_ITARGETSR) to leave an interrupt untargeted cannot be supported generically in GICv3 and hence it is removed. The timer framework, which made use of this feature, is modified to not use it anymore. All the framework and testcases are modified to use the ARM GIC layer rather than the GICv2 driver directly. The functionality common across GICv3 and GICv2 drivers are defined in gic_common.c. Change-Id: Idf50fa14be42cb4dfb507087e340b0404e681e98
Diffstat (limited to 'framework')
-rw-r--r--framework/include/tftf.h6
-rw-r--r--framework/main.c4
-rw-r--r--framework/timer/timer_framework.c46
3 files changed, 24 insertions, 32 deletions
diff --git a/framework/include/tftf.h b/framework/include/tftf.h
index 829711b..1ce220b 100644
--- a/framework/include/tftf.h
+++ b/framework/include/tftf.h
@@ -1,6 +1,6 @@
/** @file
*
-* Copyright (c) 2013, ARM Limited. All rights reserved.
+* Copyright (c) 2013-2016, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
@@ -149,10 +149,6 @@ void tftf_report_generate(void);
void __dead2 tftf_exit(void);
void tftf_arch_setup(void);
-void tftf_register_gic_id(void);
-uint8_t tftf_get_gic_cpu_id_from_mpidr(unsigned long mpidr);
-uint8_t tftf_get_gic_cpu_id_from_core_pos(unsigned int core_pos);
-uint8_t tftf_get_cpu_id_from_gic_id(uint8_t gic_id);
/*
* This function detects the power state format used by PSCI which can
diff --git a/framework/main.c b/framework/main.c
index c64aa6d..02f37e3 100644
--- a/framework/main.c
+++ b/framework/main.c
@@ -1,6 +1,6 @@
/** @file
*
-* Copyright (c) 2013, ARM Limited. All rights reserved.
+* Copyright (c) 2013-2016, ARM Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
@@ -13,9 +13,9 @@
**/
#include <arch_helpers.h>
+#include <arm_gic.h>
#include <assert.h>
#include <debug.h>
-#include <gic_v2.h>
#include <irq.h>
#include <mmio.h>
#include <nvm.h>
diff --git a/framework/timer/timer_framework.c b/framework/timer/timer_framework.c
index 67668e4..51ec44a 100644
--- a/framework/timer/timer_framework.c
+++ b/framework/timer/timer_framework.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited. All rights reserved.
+ * Copyright (c) 2015-2016, ARM Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -32,7 +32,6 @@
#include <arch_helpers.h>
#include <arm_gic.h>
#include <debug.h>
-#include <gic_v2.h>
#include <mmio.h>
#include <errno.h>
#include <irq.h>
@@ -47,7 +46,6 @@
#define TIMER_STEP_VALUE (plat_timer_info->timer_step_value)
#define TIMER_IRQ (plat_timer_info->timer_irq)
#define PROGRAM_TIMER(a) plat_timer_info->program(a)
-#define GET_GIC_ID(a) tftf_get_gic_cpu_id_from_core_pos(a)
#define INVALID_CORE UINT32_MAX
#define INVALID_TIME UINT64_MAX
#define MAX_TIME_OUT_MS 10000
@@ -113,8 +111,8 @@ int tftf_initialise_timer(void)
interrupt_req_time[i] = INVALID_TIME;
tftf_irq_register_handler(TIMER_IRQ, tftf_timer_framework_handler);
- arm_gicd_set_ipriorityr(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
- arm_gicd_set_isenabler(TIMER_IRQ);
+ arm_gic_set_intr_priority(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
+ arm_gic_intr_enable(TIMER_IRQ);
/* Save the systicks per millisecond */
systicks_per_ms = read_cntfrq_el0() / 1000;
@@ -203,14 +201,13 @@ int tftf_program_timer(unsigned long time_out_ms)
*/
if ((!get_current_prog_time()) || (interrupt_req_time[core_pos] <
(get_current_prog_time() - TIMER_STEP_VALUE))) {
- if (current_prog_core != INVALID_CORE)
- arm_gicd_clear_itargetsr(TIMER_IRQ,
- GET_GIC_ID(current_prog_core));
+
+ arm_gic_set_intr_target(TIMER_IRQ, core_pos);
+
rc = PROGRAM_TIMER(time_out_ms);
/* We don't expect timer programming to fail */
if (rc)
ERROR("%s %d: rc = %d\n", __func__, __LINE__, rc);
- arm_gicd_set_itargetsr(TIMER_IRQ, GET_GIC_ID(core_pos));
current_prog_core = core_pos;
}
@@ -258,16 +255,15 @@ int tftf_cancel_timer(void)
* cancel timer is executed, the signal remains pending. So,
* clear the Timer IRQ if it is already pending.
*/
- if (arm_gicd_ispend_irq(TIMER_IRQ))
- arm_gicd_set_icpendr(TIMER_IRQ);
+ if (arm_gic_is_intr_pending(TIMER_IRQ))
+ arm_gic_intr_clear(TIMER_IRQ);
- arm_gicd_clear_itargetsr(TIMER_IRQ, GET_GIC_ID(core_pos));
/* Get next timer consumer */
next_timer_req_core_pos = get_lowest_req_core();
if (next_timer_req_core_pos != INVALID_CORE) {
+
/* Retarget to the next_timer_req_core_pos */
- arm_gicd_set_itargetsr(TIMER_IRQ,
- GET_GIC_ID(next_timer_req_core_pos));
+ arm_gic_set_intr_target(TIMER_IRQ, next_timer_req_core_pos);
current_prog_core = next_timer_req_core_pos;
current_time = get_current_time_ms();
@@ -315,15 +311,20 @@ int tftf_timer_framework_handler(void *data)
spin_lock(&timer_lock);
current_time = get_current_time_ms();
-
/* Check if we interrupt is targeted correctly */
assert(handler_core_pos == current_prog_core);
+
interrupt_req_time[handler_core_pos] = INVALID_TIME;
/* Execute the driver handler */
if (plat_timer_info->handler)
plat_timer_info->handler();
+ if (arm_gic_is_intr_pending(TIMER_IRQ)) {
+ ERROR(" Timer IRQ still pending. Fatal error.\n");
+ panic();
+ }
+
/*
* Execute the handler requested by the core, the handlers for the
* other cores will be executed as part of handling IRQ_WAKE_SGI.
@@ -331,9 +332,6 @@ int tftf_timer_framework_handler(void *data)
if (timer_handler[handler_core_pos])
timer_handler[handler_core_pos](data);
- arm_gicd_clear_itargetsr(TIMER_IRQ,
- GET_GIC_ID(handler_core_pos));
-
/* Send interrupts to all the CPUS in the min time block */
for (int i = 0; i < PLATFORM_CORE_COUNT; i++) {
if ((interrupt_req_time[i] <=
@@ -349,11 +347,9 @@ int tftf_timer_framework_handler(void *data)
/* Check we have not exceeded the time for next core */
assert(interrupt_req_time[next_timer_req_core_pos] >
current_time);
- rc = PROGRAM_TIMER(
- interrupt_req_time[next_timer_req_core_pos]
+ arm_gic_set_intr_target(TIMER_IRQ, next_timer_req_core_pos);
+ rc = PROGRAM_TIMER(interrupt_req_time[next_timer_req_core_pos]
- current_time);
- arm_gicd_set_itargetsr(TIMER_IRQ,
- GET_GIC_ID(next_timer_req_core_pos));
}
/* Update current program core to the newer one */
current_prog_core = next_timer_req_core_pos;
@@ -442,15 +438,15 @@ void tftf_timer_gic_state_restore(void)
unsigned int core_pos = platform_get_core_pos(read_mpidr_el1());
spin_lock(&timer_lock);
- arm_gicd_set_ipriorityr(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
- arm_gicd_set_isenabler(TIMER_IRQ);
+ arm_gic_set_intr_priority(TIMER_IRQ, GIC_HIGHEST_NS_PRIORITY);
+ arm_gic_intr_enable(TIMER_IRQ);
/* Check if the programmed core is the woken up core */
if (interrupt_req_time[core_pos] == INVALID_TIME) {
INFO("The programmed core is not the one woken up\n");
} else {
current_prog_core = core_pos;
- arm_gicd_set_itargetsr(TIMER_IRQ, GET_GIC_ID(core_pos));
+ arm_gic_set_intr_target(TIMER_IRQ, core_pos);
}
spin_unlock(&timer_lock);