|
|
@ -1,5 +1,6 @@ |
|
|
|
/*
|
|
|
|
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. |
|
|
|
* Copyright (c) 2023, NVIDIA Corporation. All rights reserved. |
|
|
|
* |
|
|
|
* SPDX-License-Identifier: BSD-3-Clause |
|
|
|
*/ |
|
|
@ -10,6 +11,7 @@ |
|
|
|
#include <arch_helpers.h> |
|
|
|
#include <common/debug.h> |
|
|
|
#include <common/interrupt_props.h> |
|
|
|
#include <drivers/arm/gic600_multichip.h> |
|
|
|
#include <drivers/arm/gicv3.h> |
|
|
|
#include <lib/spinlock.h> |
|
|
|
#include <plat/common/platform.h> |
|
|
@ -430,6 +432,7 @@ unsigned int gicv3_get_interrupt_type(unsigned int id, unsigned int proc_num) |
|
|
|
{ |
|
|
|
unsigned int igroup, grpmodr; |
|
|
|
uintptr_t gicr_base; |
|
|
|
uintptr_t gicd_base; |
|
|
|
|
|
|
|
assert(IS_IN_EL3()); |
|
|
|
assert(gicv3_driver_data != NULL); |
|
|
@ -453,8 +456,9 @@ unsigned int gicv3_get_interrupt_type(unsigned int id, unsigned int proc_num) |
|
|
|
} else { |
|
|
|
/* SPIs: 32-1019, ESPIs: 4096-5119 */ |
|
|
|
assert(gicv3_driver_data->gicd_base != 0U); |
|
|
|
igroup = gicd_get_igroupr(gicv3_driver_data->gicd_base, id); |
|
|
|
grpmodr = gicd_get_igrpmodr(gicv3_driver_data->gicd_base, id); |
|
|
|
gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); |
|
|
|
igroup = gicd_get_igroupr(gicd_base, id); |
|
|
|
grpmodr = gicd_get_igrpmodr(gicd_base, id); |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
@ -930,6 +934,8 @@ unsigned int gicv3_get_running_priority(void) |
|
|
|
******************************************************************************/ |
|
|
|
unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num) |
|
|
|
{ |
|
|
|
uintptr_t gicd_base; |
|
|
|
|
|
|
|
assert(gicv3_driver_data != NULL); |
|
|
|
assert(gicv3_driver_data->gicd_base != 0U); |
|
|
|
assert(proc_num < gicv3_driver_data->rdistif_num); |
|
|
@ -943,7 +949,8 @@ unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num) |
|
|
|
} |
|
|
|
|
|
|
|
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */ |
|
|
|
return gicd_get_isactiver(gicv3_driver_data->gicd_base, id); |
|
|
|
gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); |
|
|
|
return gicd_get_isactiver(gicd_base, id); |
|
|
|
} |
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
@ -953,6 +960,8 @@ unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num) |
|
|
|
******************************************************************************/ |
|
|
|
void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num) |
|
|
|
{ |
|
|
|
uintptr_t gicd_base; |
|
|
|
|
|
|
|
assert(gicv3_driver_data != NULL); |
|
|
|
assert(gicv3_driver_data->gicd_base != 0U); |
|
|
|
assert(proc_num < gicv3_driver_data->rdistif_num); |
|
|
@ -971,7 +980,8 @@ void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num) |
|
|
|
gicv3_driver_data->rdistif_base_addrs[proc_num], id); |
|
|
|
} else { |
|
|
|
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */ |
|
|
|
gicd_set_isenabler(gicv3_driver_data->gicd_base, id); |
|
|
|
gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); |
|
|
|
gicd_set_isenabler(gicd_base, id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -982,6 +992,8 @@ void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num) |
|
|
|
******************************************************************************/ |
|
|
|
void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num) |
|
|
|
{ |
|
|
|
uintptr_t gicd_base; |
|
|
|
|
|
|
|
assert(gicv3_driver_data != NULL); |
|
|
|
assert(gicv3_driver_data->gicd_base != 0U); |
|
|
|
assert(proc_num < gicv3_driver_data->rdistif_num); |
|
|
@ -1003,10 +1015,11 @@ void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num) |
|
|
|
gicv3_driver_data->rdistif_base_addrs[proc_num]); |
|
|
|
} else { |
|
|
|
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */ |
|
|
|
gicd_set_icenabler(gicv3_driver_data->gicd_base, id); |
|
|
|
gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); |
|
|
|
gicd_set_icenabler(gicd_base, id); |
|
|
|
|
|
|
|
/* Write to clear enable requires waiting for pending writes */ |
|
|
|
gicd_wait_for_pending_write(gicv3_driver_data->gicd_base); |
|
|
|
gicd_wait_for_pending_write(gicd_base); |
|
|
|
} |
|
|
|
|
|
|
|
dsbishst(); |
|
|
@ -1020,6 +1033,7 @@ void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num, |
|
|
|
unsigned int priority) |
|
|
|
{ |
|
|
|
uintptr_t gicr_base; |
|
|
|
uintptr_t gicd_base; |
|
|
|
|
|
|
|
assert(gicv3_driver_data != NULL); |
|
|
|
assert(gicv3_driver_data->gicd_base != 0U); |
|
|
@ -1033,7 +1047,8 @@ void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num, |
|
|
|
gicr_set_ipriorityr(gicr_base, id, priority); |
|
|
|
} else { |
|
|
|
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */ |
|
|
|
gicd_set_ipriorityr(gicv3_driver_data->gicd_base, id, priority); |
|
|
|
gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); |
|
|
|
gicd_set_ipriorityr(gicd_base, id, priority); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -1047,6 +1062,7 @@ void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num, |
|
|
|
{ |
|
|
|
bool igroup = false, grpmod = false; |
|
|
|
uintptr_t gicr_base; |
|
|
|
uintptr_t gicd_base; |
|
|
|
|
|
|
|
assert(gicv3_driver_data != NULL); |
|
|
|
assert(gicv3_driver_data->gicd_base != 0U); |
|
|
@ -1086,10 +1102,12 @@ void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num, |
|
|
|
/* Serialize read-modify-write to Distributor registers */ |
|
|
|
spin_lock(&gic_lock); |
|
|
|
|
|
|
|
igroup ? gicd_set_igroupr(gicv3_driver_data->gicd_base, id) : |
|
|
|
gicd_clr_igroupr(gicv3_driver_data->gicd_base, id); |
|
|
|
grpmod ? gicd_set_igrpmodr(gicv3_driver_data->gicd_base, id) : |
|
|
|
gicd_clr_igrpmodr(gicv3_driver_data->gicd_base, id); |
|
|
|
gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); |
|
|
|
|
|
|
|
igroup ? gicd_set_igroupr(gicd_base, id) : |
|
|
|
gicd_clr_igroupr(gicd_base, id); |
|
|
|
grpmod ? gicd_set_igrpmodr(gicd_base, id) : |
|
|
|
gicd_clr_igrpmodr(gicd_base, id); |
|
|
|
|
|
|
|
spin_unlock(&gic_lock); |
|
|
|
} |
|
|
@ -1165,6 +1183,7 @@ void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr |
|
|
|
{ |
|
|
|
unsigned long long aff; |
|
|
|
uint64_t router; |
|
|
|
uintptr_t gicd_base; |
|
|
|
|
|
|
|
assert(gicv3_driver_data != NULL); |
|
|
|
assert(gicv3_driver_data->gicd_base != 0U); |
|
|
@ -1174,14 +1193,15 @@ void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr |
|
|
|
assert(IS_SPI(id)); |
|
|
|
|
|
|
|
aff = gicd_irouter_val_from_mpidr(mpidr, irm); |
|
|
|
gicd_write_irouter(gicv3_driver_data->gicd_base, id, aff); |
|
|
|
gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); |
|
|
|
gicd_write_irouter(gicd_base, id, aff); |
|
|
|
|
|
|
|
/*
|
|
|
|
* In implementations that do not require 1 of N distribution of SPIs, |
|
|
|
* IRM might be RAZ/WI. Read back and verify IRM bit. |
|
|
|
*/ |
|
|
|
if (irm == GICV3_IRM_ANY) { |
|
|
|
router = gicd_read_irouter(gicv3_driver_data->gicd_base, id); |
|
|
|
router = gicd_read_irouter(gicd_base, id); |
|
|
|
if (((router >> IROUTER_IRM_SHIFT) & IROUTER_IRM_MASK) == 0U) { |
|
|
|
ERROR("GICv3 implementation doesn't support routing ANY\n"); |
|
|
|
panic(); |
|
|
@ -1196,6 +1216,8 @@ void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr |
|
|
|
******************************************************************************/ |
|
|
|
void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num) |
|
|
|
{ |
|
|
|
uintptr_t gicd_base; |
|
|
|
|
|
|
|
assert(gicv3_driver_data != NULL); |
|
|
|
assert(gicv3_driver_data->gicd_base != 0U); |
|
|
|
assert(proc_num < gicv3_driver_data->rdistif_num); |
|
|
@ -1213,7 +1235,8 @@ void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num) |
|
|
|
gicv3_driver_data->rdistif_base_addrs[proc_num], id); |
|
|
|
} else { |
|
|
|
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */ |
|
|
|
gicd_set_icpendr(gicv3_driver_data->gicd_base, id); |
|
|
|
gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); |
|
|
|
gicd_set_icpendr(gicd_base, id); |
|
|
|
} |
|
|
|
|
|
|
|
dsbishst(); |
|
|
@ -1226,6 +1249,8 @@ void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num) |
|
|
|
******************************************************************************/ |
|
|
|
void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num) |
|
|
|
{ |
|
|
|
uintptr_t gicd_base; |
|
|
|
|
|
|
|
assert(gicv3_driver_data != NULL); |
|
|
|
assert(gicv3_driver_data->gicd_base != 0U); |
|
|
|
assert(proc_num < gicv3_driver_data->rdistif_num); |
|
|
@ -1244,7 +1269,8 @@ void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num) |
|
|
|
gicv3_driver_data->rdistif_base_addrs[proc_num], id); |
|
|
|
} else { |
|
|
|
/* For SPIs: 32-1019 and ESPIs: 4096-5119 */ |
|
|
|
gicd_set_ispendr(gicv3_driver_data->gicd_base, id); |
|
|
|
gicd_base = gicv3_get_multichip_base(id, gicv3_driver_data->gicd_base); |
|
|
|
gicd_set_ispendr(gicd_base, id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|