| /* |
| * Copyright (c) 2018, Arm Limited. All rights reserved. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #include <arch.h> |
| #include <arch_helpers.h> |
| #include <assert.h> |
| #include <debug.h> |
| #include <drivers/arm/gic_common.h> |
| #include <drivers/arm/gic_v2.h> |
| #include <drivers/arm/gic_v3.h> |
| |
| /* Record whether a GICv3 was detected on the system */ |
| static unsigned int gicv3_detected; |
| |
| void arm_gic_enable_interrupts_local(void) |
| { |
| if (gicv3_detected) |
| gicv3_enable_cpuif(); |
| else |
| gicv2_enable_cpuif(); |
| } |
| |
| void arm_gic_setup_local(void) |
| { |
| if (gicv3_detected) { |
| gicv3_probe_redistif_addr(); |
| gicv3_setup_cpuif(); |
| } else { |
| gicv2_probe_gic_cpu_id(); |
| gicv2_setup_cpuif(); |
| } |
| } |
| |
| void arm_gic_disable_interrupts_local(void) |
| { |
| if (gicv3_detected) |
| gicv3_disable_cpuif(); |
| else |
| gicv2_disable_cpuif(); |
| } |
| |
| void arm_gic_save_context_local(void) |
| { |
| if (gicv3_detected) |
| gicv3_save_cpuif_context(); |
| else |
| gicv2_save_cpuif_context(); |
| } |
| |
| void arm_gic_restore_context_local(void) |
| { |
| if (gicv3_detected) |
| gicv3_restore_cpuif_context(); |
| else |
| gicv2_restore_cpuif_context(); |
| } |
| |
| void arm_gic_save_context_global(void) |
| { |
| if (gicv3_detected) |
| gicv3_save_sgi_ppi_context(); |
| else |
| gicv2_save_sgi_ppi_context(); |
| } |
| |
| void arm_gic_restore_context_global(void) |
| { |
| if (gicv3_detected) { |
| gicv3_setup_distif(); |
| gicv3_restore_sgi_ppi_context(); |
| } else { |
| gicv2_setup_distif(); |
| gicv2_restore_sgi_ppi_context(); |
| } |
| } |
| |
| void arm_gic_setup_global(void) |
| { |
| if (gicv3_detected) |
| gicv3_setup_distif(); |
| else |
| gicv2_setup_distif(); |
| } |
| |
| unsigned int arm_gic_get_intr_priority(unsigned int num) |
| { |
| if (gicv3_detected) |
| return gicv3_get_ipriorityr(num); |
| else |
| return gicv2_gicd_get_ipriorityr(num); |
| } |
| |
| void arm_gic_set_intr_priority(unsigned int num, |
| unsigned int priority) |
| { |
| if (gicv3_detected) |
| gicv3_set_ipriorityr(num, priority); |
| else |
| gicv2_gicd_set_ipriorityr(num, priority); |
| } |
| |
| void arm_gic_send_sgi(unsigned int sgi_id, unsigned int core_pos) |
| { |
| if (gicv3_detected) |
| gicv3_send_sgi(sgi_id, core_pos); |
| else |
| gicv2_send_sgi(sgi_id, core_pos); |
| } |
| |
| void arm_gic_set_intr_target(unsigned int num, unsigned int core_pos) |
| { |
| if (gicv3_detected) |
| gicv3_set_intr_route(num, core_pos); |
| else |
| gicv2_set_itargetsr(num, core_pos); |
| } |
| |
| unsigned int arm_gic_intr_enabled(unsigned int num) |
| { |
| if (gicv3_detected) |
| return gicv3_get_isenabler(num) != 0; |
| else |
| return gicv2_gicd_get_isenabler(num) != 0; |
| } |
| |
| void arm_gic_intr_enable(unsigned int num) |
| { |
| if (gicv3_detected) |
| gicv3_set_isenabler(num); |
| else |
| gicv2_gicd_set_isenabler(num); |
| } |
| |
| void arm_gic_intr_disable(unsigned int num) |
| { |
| if (gicv3_detected) |
| gicv3_set_icenabler(num); |
| else |
| gicv2_gicd_set_icenabler(num); |
| } |
| |
| unsigned int arm_gic_intr_ack(unsigned int *raw_iar) |
| { |
| assert(raw_iar); |
| |
| if (gicv3_detected) { |
| *raw_iar = gicv3_acknowledge_interrupt(); |
| return *raw_iar; |
| } else { |
| *raw_iar = gicv2_gicc_read_iar(); |
| return get_gicc_iar_intid(*raw_iar); |
| } |
| } |
| |
| unsigned int arm_gic_is_intr_pending(unsigned int num) |
| { |
| if (gicv3_detected) |
| return gicv3_get_ispendr(num); |
| else |
| return gicv2_gicd_get_ispendr(num); |
| } |
| |
| void arm_gic_intr_clear(unsigned int num) |
| { |
| if (gicv3_detected) |
| gicv3_set_icpendr(num); |
| else |
| gicv2_gicd_set_icpendr(num); |
| } |
| |
| void arm_gic_end_of_intr(unsigned int raw_iar) |
| { |
| if (gicv3_detected) |
| gicv3_end_of_interrupt(raw_iar); |
| else |
| gicv2_gicc_write_eoir(raw_iar); |
| } |
| |
| void arm_gic_init(uintptr_t gicc_base, |
| uintptr_t gicd_base, |
| uintptr_t gicr_base) |
| { |
| |
| if (is_gicv3_mode()) { |
| gicv3_detected = 1; |
| gicv3_init(gicr_base, gicd_base); |
| } else { |
| gicv2_init(gicc_base, gicd_base); |
| } |
| |
| INFO("%s mode detected\n", (gicv3_detected) ? |
| "GICv3" : "GICv2"); |
| } |