|
@@ -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>
|
|
|
|
|
@@ -429,6 +431,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);
|
|
@@ -452,8 +455,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);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -929,6 +933,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);
|
|
@@ -942,7 +948,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);
|
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
@@ -952,6 +959,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);
|
|
@@ -970,7 +979,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);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -981,6 +991,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);
|
|
@@ -1002,10 +1014,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();
|
|
@@ -1019,6 +1032,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);
|
|
@@ -1032,7 +1046,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);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1046,6 +1061,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);
|
|
@@ -1085,10 +1101,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);
|
|
|
}
|
|
@@ -1164,6 +1182,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);
|
|
@@ -1173,14 +1192,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();
|
|
@@ -1195,6 +1215,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);
|
|
@@ -1212,7 +1234,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();
|
|
@@ -1225,6 +1248,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);
|
|
@@ -1243,7 +1268,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);
|
|
|
}
|
|
|
}
|
|
|
|