Commit 994421a6 authored by Olivier Deprez's avatar Olivier Deprez Committed by TrustedFirmware Code Review
Browse files

Merge changes from topics "af/fvp_gicv4", "af/gicv4", "af/gic_extended" into integration

* changes:
  FVP: Add support for GICv4 extension
  TF-A: Add GICv4 extension for GIC driver
  TF-A GICv3 driver: Add extended PPI and SPI range
parents 91a78198 e6e10ecc
...@@ -693,6 +693,12 @@ makefile: ...@@ -693,6 +693,12 @@ makefile:
functions. This is required for FVP platform which need to simulate GIC save functions. This is required for FVP platform which need to simulate GIC save
and restore during SYSTEM_SUSPEND without powering down GIC. Default is 0. and restore during SYSTEM_SUSPEND without powering down GIC. Default is 0.
- ``GIC_ENABLE_V4_EXTN`` : Enables GICv4 related changes in GICv3 driver.
This option defaults to 0.
- ``GIC_EXT_INTID``: When set to ``1``, GICv3 driver will support extended
PPI (1056-1119) and SPI (4096-5119) range. This option defaults to 0.
Debugging options Debugging options
----------------- -----------------
......
...@@ -9,50 +9,236 @@ ...@@ -9,50 +9,236 @@
#include "gicv3_private.h" #include "gicv3_private.h"
/******************************************************************************* /*******************************************************************************
* GIC Distributor interface accessors for bit operations * GIC Distributor functions for accessing the GIC registers
* corresponding to a single interrupt ID. These functions use bitwise
* operations or appropriate register accesses to modify or return
* the bit-field corresponding the single interrupt ID.
******************************************************************************/ ******************************************************************************/
/* /*
* Accessor to read the GIC Distributor IGRPMODR corresponding to the * Accessors to set the bits corresponding to interrupt ID
* interrupt `id`, 32 interrupt IDs at a time. * in GIC Distributor ICFGR and ICFGRE.
*/ */
uint32_t gicd_read_igrpmodr(uintptr_t base, unsigned int id) void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
{ {
return GICD_READ(IGRPMODR, base, id); /* Interrupt configuration is a 2-bit field */
unsigned int bit_shift = BIT_NUM(ICFG, id) << 1U;
/* Clear the field, and insert required configuration */
mmio_clrsetbits_32(base + GICD_OFFSET(ICFG, id),
(uint32_t)GIC_CFG_MASK << bit_shift,
(cfg & GIC_CFG_MASK) << bit_shift);
} }
/* /*
* Accessor to write the GIC Distributor IGRPMODR corresponding to the * Accessors to get/set/clear the bit corresponding to interrupt ID
* interrupt `id`, 32 interrupt IDs at a time. * in GIC Distributor IGROUPR and IGROUPRE.
*/ */
void gicd_write_igrpmodr(uintptr_t base, unsigned int id, uint32_t val) unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
{
return GICD_GET_BIT(IGROUP, base, id);
}
void gicd_set_igroupr(uintptr_t base, unsigned int id)
{
GICD_SET_BIT(IGROUP, base, id);
}
void gicd_clr_igroupr(uintptr_t base, unsigned int id)
{ {
GICD_WRITE(IGRPMODR, base, id, val); GICD_CLR_BIT(IGROUP, base, id);
} }
/* /*
* Accessor to get the bit corresponding to interrupt ID * Accessors to get/set/clear the bit corresponding to interrupt ID
* in GIC Distributor IGRPMODR. * in GIC Distributor IGRPMODR and IGRPMODRE.
*/ */
unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id) unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id)
{ {
return GICD_GET_BIT(IGRPMODR, base, id); return GICD_GET_BIT(IGRPMOD, base, id);
}
void gicd_set_igrpmodr(uintptr_t base, unsigned int id)
{
GICD_SET_BIT(IGRPMOD, base, id);
}
void gicd_clr_igrpmodr(uintptr_t base, unsigned int id)
{
GICD_CLR_BIT(IGRPMOD, base, id);
} }
/* /*
* Accessor to set the bit corresponding to interrupt ID * Accessors to set the bit corresponding to interrupt ID
* in GIC Distributor IGRPMODR. * in GIC Distributor ICENABLER and ICENABLERE.
*/ */
void gicd_set_igrpmodr(uintptr_t base, unsigned int id) void gicd_set_icenabler(uintptr_t base, unsigned int id)
{ {
GICD_SET_BIT(IGRPMODR, base, id); GICD_WRITE_BIT(ICENABLE, base, id);
} }
/* /*
* Accessor to clear the bit corresponding to interrupt ID * Accessors to set the bit corresponding to interrupt ID
* in GIC Distributor IGRPMODR. * in GIC Distributor ICPENDR and ICPENDRE.
*/ */
void gicd_clr_igrpmodr(uintptr_t base, unsigned int id) void gicd_set_icpendr(uintptr_t base, unsigned int id)
{
GICD_WRITE_BIT(ICPEND, base, id);
}
/*
* Accessors to get/set the bit corresponding to interrupt ID
* in GIC Distributor ISACTIVER and ISACTIVERE.
*/
unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id)
{
return GICD_GET_BIT(ISACTIVE, base, id);
}
void gicd_set_isactiver(uintptr_t base, unsigned int id)
{
GICD_WRITE_BIT(ISACTIVE, base, id);
}
/*
* Accessors to set the bit corresponding to interrupt ID
* in GIC Distributor ISENABLER and ISENABLERE.
*/
void gicd_set_isenabler(uintptr_t base, unsigned int id)
{
GICD_WRITE_BIT(ISENABLE, base, id);
}
/*
* Accessors to set the bit corresponding to interrupt ID
* in GIC Distributor ISPENDR and ISPENDRE.
*/
void gicd_set_ispendr(uintptr_t base, unsigned int id)
{
GICD_WRITE_BIT(ISPEND, base, id);
}
/*
* Accessors to set the bit corresponding to interrupt ID
* in GIC Distributor IPRIORITYR and IPRIORITYRE.
*/
void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
{
GICD_WRITE_8(IPRIORITY, base, id, (uint8_t)(pri & GIC_PRI_MASK));
}
/*******************************************************************************
* GIC Distributor interface accessors for reading/writing entire registers
******************************************************************************/
/*
* Accessors to read/write the GIC Distributor ICGFR and ICGFRE
* corresponding to the interrupt ID, 16 interrupt IDs at a time.
*/
unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
{
return GICD_READ(ICFG, base, id);
}
void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
{
GICD_WRITE(ICFG, base, id, val);
}
/*
* Accessors to read/write the GIC Distributor IGROUPR and IGROUPRE
* corresponding to the interrupt ID, 32 interrupt IDs at a time.
*/
unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
{
return GICD_READ(IGROUP, base, id);
}
void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
{
GICD_WRITE(IGROUP, base, id, val);
}
/*
* Accessors to read/write the GIC Distributor IGRPMODR and IGRPMODRE
* corresponding to the interrupt ID, 32 interrupt IDs at a time.
*/
unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id)
{
return GICD_READ(IGRPMOD, base, id);
}
void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val)
{
GICD_WRITE(IGRPMOD, base, id, val);
}
/*
* Accessors to read/write the GIC Distributor IPRIORITYR and IPRIORITYRE
* corresponding to the interrupt ID, 4 interrupt IDs at a time.
*/
unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
{
return GICD_READ(IPRIORITY, base, id);
}
void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
{
GICD_WRITE(IPRIORITY, base, id, val);
}
/*
* Accessors to read/write the GIC Distributor ISACTIVER and ISACTIVERE
* corresponding to the interrupt ID, 32 interrupt IDs at a time.
*/
unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
{
return GICD_READ(ISACTIVE, base, id);
}
void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
{
GICD_WRITE(ISACTIVE, base, id, val);
}
/*
* Accessors to read/write the GIC Distributor ISENABLER and ISENABLERE
* corresponding to the interrupt ID, 32 interrupt IDs at a time.
*/
unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
{
return GICD_READ(ISENABLE, base, id);
}
void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
{
GICD_WRITE(ISENABLE, base, id, val);
}
/*
* Accessors to read/write the GIC Distributor ISPENDR and ISPENDRE
* corresponding to the interrupt ID, 32 interrupt IDs at a time.
*/
unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
{
return GICD_READ(ISPEND, base, id);
}
void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
{
GICD_WRITE(ISPEND, base, id, val);
}
/*
* Accessors to read/write the GIC Distributor NSACR and NSACRE
* corresponding to the interrupt ID, 16 interrupt IDs at a time.
*/
unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id)
{
return GICD_READ(NSAC, base, id);
}
void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val)
{ {
GICD_CLR_BIT(IGRPMODR, base, id); GICD_WRITE(NSAC, base, id, val);
} }
...@@ -13,203 +13,113 @@ ...@@ -13,203 +13,113 @@
/******************************************************************************* /*******************************************************************************
* GIC Redistributor functions * GIC Redistributor functions
* Note: The raw register values correspond to multiple interrupt IDs and * Note: The raw register values correspond to multiple interrupt `id`s and
* the number of interrupt IDs involved depends on the register accessed. * the number of interrupt `id`s involved depends on the register accessed.
******************************************************************************/ ******************************************************************************/
/* /*
* Accessor to read the GIC Redistributor IPRIORITYR corresponding to the * Accessor to set the byte corresponding to interrupt `id`
* interrupt `id`, 4 interrupts IDs at a time. * in GIC Redistributor IPRIORITYR and IPRIORITYRE.
*/
unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id)
{
unsigned int n = id >> IPRIORITYR_SHIFT;
return mmio_read_32(base + GICR_IPRIORITYR + (n << 2));
}
/*
* Accessor to write the GIC Redistributor IPRIORITYR corresponding to the
* interrupt `id`, 4 interrupts IDs at a time.
*/
void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
{
unsigned int n = id >> IPRIORITYR_SHIFT;
mmio_write_32(base + GICR_IPRIORITYR + (n << 2), val);
}
/*
* Accessor to set the byte corresponding to interrupt ID
* in GIC Redistributor IPRIORITYR.
*/ */
void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
{ {
GICR_WRITE_8(IPRIORITYR, base, id, pri & GIC_PRI_MASK); GICR_WRITE_8(IPRIORITY, base, id, (uint8_t)(pri & GIC_PRI_MASK));
} }
/* /*
* Accessor to get the bit corresponding to interrupt ID * Accessors to get/set/clear the bit corresponding to interrupt `id`
* from GIC Redistributor IGROUPR0. * from GIC Redistributor IGROUPR0 and IGROUPRE
*/ */
unsigned int gicr_get_igroupr0(uintptr_t base, unsigned int id) unsigned int gicr_get_igroupr(uintptr_t base, unsigned int id)
{ {
unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); return GICR_GET_BIT(IGROUP, base, id);
unsigned int reg_val = gicr_read_igroupr0(base);
return (reg_val >> bit_num) & 0x1U;
} }
/* void gicr_set_igroupr(uintptr_t base, unsigned int id)
* Accessor to set the bit corresponding to interrupt ID
* in GIC Redistributor IGROUPR0.
*/
void gicr_set_igroupr0(uintptr_t base, unsigned int id)
{ {
unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); GICR_SET_BIT(IGROUP, base, id);
unsigned int reg_val = gicr_read_igroupr0(base);
gicr_write_igroupr0(base, reg_val | (1U << bit_num));
} }
/* void gicr_clr_igroupr(uintptr_t base, unsigned int id)
* Accessor to clear the bit corresponding to interrupt ID
* in GIC Redistributor IGROUPR0.
*/
void gicr_clr_igroupr0(uintptr_t base, unsigned int id)
{ {
unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); GICR_CLR_BIT(IGROUP, base, id);
unsigned int reg_val = gicr_read_igroupr0(base);
gicr_write_igroupr0(base, reg_val & ~(1U << bit_num));
} }
/* /*
* Accessor to get the bit corresponding to interrupt ID * Accessors to get/set/clear the bit corresponding to interrupt `id`
* from GIC Redistributor IGRPMODR0. * from GIC Redistributor IGRPMODR0 and IGRPMODRE
*/ */
unsigned int gicr_get_igrpmodr0(uintptr_t base, unsigned int id) unsigned int gicr_get_igrpmodr(uintptr_t base, unsigned int id)
{ {
unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U); return GICR_GET_BIT(IGRPMOD, base, id);
unsigned int reg_val = gicr_read_igrpmodr0(base);
return (reg_val >> bit_num) & 0x1U;
} }
/* void gicr_set_igrpmodr(uintptr_t base, unsigned int id)
* Accessor to set the bit corresponding to interrupt ID
* in GIC Redistributor IGRPMODR0.
*/
void gicr_set_igrpmodr0(uintptr_t base, unsigned int id)
{ {
unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U); GICR_SET_BIT(IGRPMOD, base, id);
unsigned int reg_val = gicr_read_igrpmodr0(base);
gicr_write_igrpmodr0(base, reg_val | (1U << bit_num));
} }
/* void gicr_clr_igrpmodr(uintptr_t base, unsigned int id)
* Accessor to clear the bit corresponding to interrupt ID
* in GIC Redistributor IGRPMODR0.
*/
void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id)
{ {
unsigned int bit_num = id & ((1U << IGRPMODR_SHIFT) - 1U); GICR_CLR_BIT(IGRPMOD, base, id);
unsigned int reg_val = gicr_read_igrpmodr0(base);
gicr_write_igrpmodr0(base, reg_val & ~(1U << bit_num));
} }
/* /*
* Accessor to set the bit corresponding to interrupt ID * Accessor to write the bit corresponding to interrupt `id`
* in GIC Redistributor ISENABLER0. * in GIC Redistributor ISENABLER0 and ISENABLERE
*/ */
void gicr_set_isenabler0(uintptr_t base, unsigned int id) void gicr_set_isenabler(uintptr_t base, unsigned int id)
{ {
unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U); GICR_WRITE_BIT(ISENABLE, base, id);
gicr_write_isenabler0(base, (1U << bit_num));
} }
/* /*
* Accessor to set the bit corresponding to interrupt ID in GIC Redistributor * Accessor to write the bit corresponding to interrupt `id`
* ICENABLER0. * in GIC Redistributor ICENABLER0 and ICENABLERE
*/ */
void gicr_set_icenabler0(uintptr_t base, unsigned int id) void gicr_set_icenabler(uintptr_t base, unsigned int id)
{ {
unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U); GICR_WRITE_BIT(ICENABLE, base, id);
gicr_write_icenabler0(base, (1U << bit_num));
} }
/* /*
* Accessor to set the bit corresponding to interrupt ID in GIC Redistributor * Accessor to get the bit corresponding to interrupt `id`
* ISACTIVER0. * in GIC Redistributor ISACTIVER0 and ISACTIVERE
*/ */
unsigned int gicr_get_isactiver0(uintptr_t base, unsigned int id) unsigned int gicr_get_isactiver(uintptr_t base, unsigned int id)
{ {
unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U); return GICR_GET_BIT(ISACTIVE, base, id);
unsigned int reg_val = gicr_read_isactiver0(base);
return (reg_val >> bit_num) & 0x1U;
} }
/* /*
* Accessor to clear the bit corresponding to interrupt ID in GIC Redistributor * Accessor to clear the bit corresponding to interrupt `id`
* ICPENDRR0. * in GIC Redistributor ICPENDR0 and ICPENDRE
*/ */
void gicr_set_icpendr0(uintptr_t base, unsigned int id) void gicr_set_icpendr(uintptr_t base, unsigned int id)
{ {
unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U); GICR_WRITE_BIT(ICPEND, base, id);
gicr_write_icpendr0(base, (1U << bit_num));
} }
/* /*
* Accessor to set the bit corresponding to interrupt ID in GIC Redistributor * Accessor to write the bit corresponding to interrupt `id`
* ISPENDR0. * in GIC Redistributor ISPENDR0 and ISPENDRE
*/ */
void gicr_set_ispendr0(uintptr_t base, unsigned int id) void gicr_set_ispendr(uintptr_t base, unsigned int id)
{ {
unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U); GICR_WRITE_BIT(ISPEND, base, id);
gicr_write_ispendr0(base, (1U << bit_num));
} }
/* /*
* Accessor to set the bit fields corresponding to interrupt ID * Accessor to set the bit fields corresponding to interrupt `id`
* in GIC Redistributor ICFGR0. * in GIC Redistributor ICFGR0, ICFGR1 and ICFGRE
*/ */
void gicr_set_icfgr0(uintptr_t base, unsigned int id, unsigned int cfg) void gicr_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
{ {
/* Interrupt configuration is a 2-bit field */ /* Interrupt configuration is a 2-bit field */
unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U); unsigned int bit_shift = BIT_NUM(ICFG, id) << 1U;
unsigned int bit_shift = bit_num << 1U;
uint32_t reg_val = gicr_read_icfgr0(base);
/* Clear the field, and insert required configuration */ /* Clear the field, and insert required configuration */
reg_val &= ~(GIC_CFG_MASK << bit_shift); mmio_clrsetbits_32(base + GICR_OFFSET(ICFG, id),
reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift); (uint32_t)GIC_CFG_MASK << bit_shift,
(cfg & GIC_CFG_MASK) << bit_shift);
gicr_write_icfgr0(base, reg_val);
}
/*
* Accessor to set the bit fields corresponding to interrupt ID
* in GIC Redistributor ICFGR1.
*/
void gicr_set_icfgr1(uintptr_t base, unsigned int id, unsigned int cfg)
{
/* Interrupt configuration is a 2-bit field */
unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
unsigned int bit_shift = bit_num << 1U;
uint32_t reg_val = gicr_read_icfgr1(base);
/* Clear the field, and insert required configuration */
reg_val &= ~(GIC_CFG_MASK << bit_shift);
reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
gicr_write_icfgr1(base, reg_val);
} }
...@@ -8,9 +8,10 @@ ...@@ -8,9 +8,10 @@
GICV3_IMPL ?= GIC500 GICV3_IMPL ?= GIC500
GICV3_IMPL_GIC600_MULTICHIP ?= 0 GICV3_IMPL_GIC600_MULTICHIP ?= 0
GICV3_OVERRIDE_DISTIF_PWR_OPS ?= 0 GICV3_OVERRIDE_DISTIF_PWR_OPS ?= 0
GIC_ENABLE_V4_EXTN ?= 0
GIC_EXT_INTID ?= 0
GICV3_SOURCES += drivers/arm/gic/common/gic_common.c \ GICV3_SOURCES += drivers/arm/gic/v3/gicv3_main.c \
drivers/arm/gic/v3/gicv3_main.c \
drivers/arm/gic/v3/gicv3_helpers.c \ drivers/arm/gic/v3/gicv3_helpers.c \
drivers/arm/gic/v3/gicdv3_helpers.c \ drivers/arm/gic/v3/gicdv3_helpers.c \
drivers/arm/gic/v3/gicrv3_helpers.c drivers/arm/gic/v3/gicrv3_helpers.c
...@@ -32,3 +33,11 @@ GICV3_SOURCES += drivers/arm/gic/v3/gic500.c ...@@ -32,3 +33,11 @@ GICV3_SOURCES += drivers/arm/gic/v3/gic500.c
else else
$(error "Incorrect GICV3_IMPL value ${GICV3_IMPL}") $(error "Incorrect GICV3_IMPL value ${GICV3_IMPL}")
endif endif
# Set GICv4 extension
$(eval $(call assert_boolean,GIC_ENABLE_V4_EXTN))
$(eval $(call add_define,GIC_ENABLE_V4_EXTN))
# Set support for extended PPI and SPI range
$(eval $(call assert_boolean,GIC_EXT_INTID))
$(eval $(call add_define,GIC_EXT_INTID))
/* /*
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -31,8 +31,8 @@ void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base) ...@@ -31,8 +31,8 @@ void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base)
gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_PS_BIT); gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_PS_BIT);
/* Wait till the WAKER_CA_BIT changes to 0 */ /* Wait till the WAKER_CA_BIT changes to 0 */
while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U) while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U) {
; }
} }
/****************************************************************************** /******************************************************************************
...@@ -45,11 +45,10 @@ void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base) ...@@ -45,11 +45,10 @@ void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base)
gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_PS_BIT); gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_PS_BIT);
/* Wait till the WAKER_CA_BIT changes to 1 */ /* Wait till the WAKER_CA_BIT changes to 1 */
while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) == 0U) while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) == 0U) {
; }
} }
/******************************************************************************* /*******************************************************************************
* This function probes the Redistributor frames when the driver is initialised * This function probes the Redistributor frames when the driver is initialised
* and saves their base addresses. These base addresses are used later to * and saves their base addresses. These base addresses are used later to
...@@ -84,47 +83,78 @@ void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs, ...@@ -84,47 +83,78 @@ void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs,
TYPER_PROC_NUM_MASK; TYPER_PROC_NUM_MASK;
} }
if (proc_num < rdistif_num) if (proc_num < rdistif_num) {
rdistif_base_addrs[proc_num] = rdistif_base; rdistif_base_addrs[proc_num] = rdistif_base;
}
rdistif_base += (1U << GICR_PCPUBASE_SHIFT); rdistif_base += (1U << GICR_PCPUBASE_SHIFT);
} while ((typer_val & TYPER_LAST_BIT) == 0U); } while ((typer_val & TYPER_LAST_BIT) == 0U);
} }
/******************************************************************************* /*******************************************************************************
* Helper function to configure the default attributes of SPIs. * Helper function to configure the default attributes of (E)SPIs.
******************************************************************************/ ******************************************************************************/
void gicv3_spis_config_defaults(uintptr_t gicd_base) void gicv3_spis_config_defaults(uintptr_t gicd_base)
{ {
unsigned int index, num_ints; unsigned int i, num_ints;
#if GIC_EXT_INTID
unsigned int num_eints;
#endif
unsigned int typer_reg = gicd_read_typer(gicd_base);
/* Maximum SPI INTID is 32 * (GICD_TYPER.ITLinesNumber + 1) - 1 */
num_ints = ((typer_reg & TYPER_IT_LINES_NO_MASK) + 1U) << 5;
/* Treat all (E)SPIs as G1NS by default. We do 32 at a time. */
for (i = MIN_SPI_ID; i < num_ints; i += (1U << IGROUPR_SHIFT)) {
gicd_write_igroupr(gicd_base, i, ~0U);
}
num_ints = gicd_read_typer(gicd_base); #if GIC_EXT_INTID
num_ints &= TYPER_IT_LINES_NO_MASK; /* Check if extended SPI range is implemented */
num_ints = (num_ints + 1U) << 5; if ((typer_reg & TYPER_ESPI) != 0U) {
/*
* Maximum ESPI INTID is 32 * (GICD_TYPER.ESPI_range + 1) + 4095
*/
num_eints = ((((typer_reg >> TYPER_ESPI_RANGE_SHIFT) &
TYPER_ESPI_RANGE_MASK) + 1U) << 5) + MIN_ESPI_ID - 1;
/* for (i = MIN_ESPI_ID; i < num_eints;
* Treat all SPIs as G1NS by default. The number of interrupts is i += (1U << IGROUPR_SHIFT)) {
* calculated as 32 * (IT_LINES + 1). We do 32 at a time. gicd_write_igroupr(gicd_base, i, ~0U);
*/ }
for (index = MIN_SPI_ID; index < num_ints; index += 32U) } else {
gicd_write_igroupr(gicd_base, index, ~0U); num_eints = 0U;
}
#endif
/* Setup the default SPI priorities doing four at a time */ /* Setup the default (E)SPI priorities doing four at a time */
for (index = MIN_SPI_ID; index < num_ints; index += 4U) for (i = MIN_SPI_ID; i < num_ints; i += (1U << IPRIORITYR_SHIFT)) {
gicd_write_ipriorityr(gicd_base, gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL);
index, }
GICD_IPRIORITYR_DEF_VAL);
#if GIC_EXT_INTID
for (i = MIN_ESPI_ID; i < num_eints;
i += (1U << IPRIORITYR_SHIFT)) {
gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL);
}
#endif
/* /*
* Treat all SPIs as level triggered by default, write 16 at * Treat all (E)SPIs as level triggered by default, write 16 at a time
* a time
*/ */
for (index = MIN_SPI_ID; index < num_ints; index += 16U) for (i = MIN_SPI_ID; i < num_ints; i += (1U << ICFGR_SHIFT)) {
gicd_write_icfgr(gicd_base, index, 0U); gicd_write_icfgr(gicd_base, i, 0U);
}
#if GIC_EXT_INTID
for (i = MIN_ESPI_ID; i < num_eints; i += (1U << ICFGR_SHIFT)) {
gicd_write_icfgr(gicd_base, i, 0U);
}
#endif
} }
/******************************************************************************* /*******************************************************************************
* Helper function to configure properties of secure SPIs * Helper function to configure properties of secure (E)SPIs
******************************************************************************/ ******************************************************************************/
unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base, unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base,
const interrupt_prop_t *interrupt_props, const interrupt_prop_t *interrupt_props,
...@@ -136,80 +166,108 @@ unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base, ...@@ -136,80 +166,108 @@ unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base,
unsigned int ctlr_enable = 0U; unsigned int ctlr_enable = 0U;
/* Make sure there's a valid property array */ /* Make sure there's a valid property array */
if (interrupt_props_num > 0U) if (interrupt_props_num > 0U) {
assert(interrupt_props != NULL); assert(interrupt_props != NULL);
}
for (i = 0U; i < interrupt_props_num; i++) { for (i = 0U; i < interrupt_props_num; i++) {
current_prop = &interrupt_props[i]; current_prop = &interrupt_props[i];
if (current_prop->intr_num < MIN_SPI_ID) unsigned int intr_num = current_prop->intr_num;
/* Skip SGI, (E)PPI and LPI interrupts */
if (!IS_SPI(intr_num)) {
continue; continue;
}
/* Configure this interrupt as a secure interrupt */ /* Configure this interrupt as a secure interrupt */
gicd_clr_igroupr(gicd_base, current_prop->intr_num); gicd_clr_igroupr(gicd_base, intr_num);
/* Configure this interrupt as G0 or a G1S interrupt */ /* Configure this interrupt as G0 or a G1S interrupt */
assert((current_prop->intr_grp == INTR_GROUP0) || assert((current_prop->intr_grp == INTR_GROUP0) ||
(current_prop->intr_grp == INTR_GROUP1S)); (current_prop->intr_grp == INTR_GROUP1S));
if (current_prop->intr_grp == INTR_GROUP1S) { if (current_prop->intr_grp == INTR_GROUP1S) {
gicd_set_igrpmodr(gicd_base, current_prop->intr_num); gicd_set_igrpmodr(gicd_base, intr_num);
ctlr_enable |= CTLR_ENABLE_G1S_BIT; ctlr_enable |= CTLR_ENABLE_G1S_BIT;
} else { } else {
gicd_clr_igrpmodr(gicd_base, current_prop->intr_num); gicd_clr_igrpmodr(gicd_base, intr_num);
ctlr_enable |= CTLR_ENABLE_G0_BIT; ctlr_enable |= CTLR_ENABLE_G0_BIT;
} }
/* Set interrupt configuration */ /* Set interrupt configuration */
gicd_set_icfgr(gicd_base, current_prop->intr_num, gicd_set_icfgr(gicd_base, intr_num, current_prop->intr_cfg);
current_prop->intr_cfg);
/* Set the priority of this interrupt */ /* Set the priority of this interrupt */
gicd_set_ipriorityr(gicd_base, current_prop->intr_num, gicd_set_ipriorityr(gicd_base, intr_num,
current_prop->intr_pri); current_prop->intr_pri);
/* Target SPIs to the primary CPU */ /* Target (E)SPIs to the primary CPU */
gic_affinity_val = gic_affinity_val =
gicd_irouter_val_from_mpidr(read_mpidr(), 0U); gicd_irouter_val_from_mpidr(read_mpidr(), 0U);
gicd_write_irouter(gicd_base, current_prop->intr_num, gicd_write_irouter(gicd_base, intr_num,
gic_affinity_val); gic_affinity_val);
/* Enable this interrupt */ /* Enable this interrupt */
gicd_set_isenabler(gicd_base, current_prop->intr_num); gicd_set_isenabler(gicd_base, intr_num);
} }
return ctlr_enable; return ctlr_enable;
} }
/******************************************************************************* /*******************************************************************************
* Helper function to configure the default attributes of SPIs. * Helper function to configure the default attributes of (E)SPIs
******************************************************************************/ ******************************************************************************/
void gicv3_ppi_sgi_config_defaults(uintptr_t gicr_base) void gicv3_ppi_sgi_config_defaults(uintptr_t gicr_base)
{ {
unsigned int index; unsigned int i, ppi_regs_num, regs_num;
#if GIC_EXT_INTID
/* Calculate number of PPI registers */
ppi_regs_num = (unsigned int)((gicr_read_typer(gicr_base) >>
TYPER_PPI_NUM_SHIFT) & TYPER_PPI_NUM_MASK) + 1;
/* All other values except PPInum [0-2] are reserved */
if (ppi_regs_num > 3U) {
ppi_regs_num = 1U;
}
#else
ppi_regs_num = 1U;
#endif
/* /*
* Disable all SGIs (imp. def.)/PPIs before configuring them. This is a * Disable all SGIs (imp. def.)/(E)PPIs before configuring them.
* more scalable approach as it avoids clearing the enable bits in the * This is a more scalable approach as it avoids clearing
* GICD_CTLR * the enable bits in the GICD_CTLR.
*/ */
gicr_write_icenabler0(gicr_base, ~0U); for (i = 0U; i < ppi_regs_num; ++i) {
gicr_write_icenabler(gicr_base, i, ~0U);
}
/* Wait for pending writes to GICR_ICENABLER */
gicr_wait_for_pending_write(gicr_base); gicr_wait_for_pending_write(gicr_base);
/* Treat all SGIs/PPIs as G1NS by default. */ /* 32 interrupt IDs per GICR_IGROUPR register */
gicr_write_igroupr0(gicr_base, ~0U); for (i = 0U; i < ppi_regs_num; ++i) {
/* Treat all SGIs/(E)PPIs as G1NS by default */
gicr_write_igroupr(gicr_base, i, ~0U);
}
/* Setup the default PPI/SGI priorities doing four at a time */ /* 4 interrupt IDs per GICR_IPRIORITYR register */
for (index = 0U; index < MIN_SPI_ID; index += 4U) regs_num = ppi_regs_num << 3;
gicr_write_ipriorityr(gicr_base, for (i = 0U; i < regs_num; ++i) {
index, /* Setup the default (E)PPI/SGI priorities doing 4 at a time */
GICD_IPRIORITYR_DEF_VAL); gicr_write_ipriorityr(gicr_base, i, GICD_IPRIORITYR_DEF_VAL);
}
/* Configure all PPIs as level triggered by default */ /* 16 interrupt IDs per GICR_ICFGR register */
gicr_write_icfgr1(gicr_base, 0U); regs_num = ppi_regs_num << 1;
for (i = (MIN_PPI_ID >> ICFGR_SHIFT); i < regs_num; ++i) {
/* Configure all (E)PPIs as level triggered by default */
gicr_write_icfgr(gicr_base, i, 0U);
}
} }
/******************************************************************************* /*******************************************************************************
* Helper function to configure properties of secure G0 and G1S PPIs and SGIs. * Helper function to configure properties of secure G0 and G1S (E)PPIs and SGIs
******************************************************************************/ ******************************************************************************/
unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base, unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base,
const interrupt_prop_t *interrupt_props, const interrupt_prop_t *interrupt_props,
...@@ -220,45 +278,50 @@ unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base, ...@@ -220,45 +278,50 @@ unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base,
unsigned int ctlr_enable = 0U; unsigned int ctlr_enable = 0U;
/* Make sure there's a valid property array */ /* Make sure there's a valid property array */
if (interrupt_props_num > 0U) if (interrupt_props_num > 0U) {
assert(interrupt_props != NULL); assert(interrupt_props != NULL);
}
for (i = 0U; i < interrupt_props_num; i++) { for (i = 0U; i < interrupt_props_num; i++) {
current_prop = &interrupt_props[i]; current_prop = &interrupt_props[i];
if (current_prop->intr_num >= MIN_SPI_ID) unsigned int intr_num = current_prop->intr_num;
/* Skip (E)SPI interrupt */
if (!IS_SGI_PPI(intr_num)) {
continue; continue;
}
/* Configure this interrupt as a secure interrupt */ /* Configure this interrupt as a secure interrupt */
gicr_clr_igroupr0(gicr_base, current_prop->intr_num); gicr_clr_igroupr(gicr_base, intr_num);
/* Configure this interrupt as G0 or a G1S interrupt */ /* Configure this interrupt as G0 or a G1S interrupt */
assert((current_prop->intr_grp == INTR_GROUP0) || assert((current_prop->intr_grp == INTR_GROUP0) ||
(current_prop->intr_grp == INTR_GROUP1S)); (current_prop->intr_grp == INTR_GROUP1S));
if (current_prop->intr_grp == INTR_GROUP1S) { if (current_prop->intr_grp == INTR_GROUP1S) {
gicr_set_igrpmodr0(gicr_base, current_prop->intr_num); gicr_set_igrpmodr(gicr_base, intr_num);
ctlr_enable |= CTLR_ENABLE_G1S_BIT; ctlr_enable |= CTLR_ENABLE_G1S_BIT;
} else { } else {
gicr_clr_igrpmodr0(gicr_base, current_prop->intr_num); gicr_clr_igrpmodr(gicr_base, intr_num);
ctlr_enable |= CTLR_ENABLE_G0_BIT; ctlr_enable |= CTLR_ENABLE_G0_BIT;
} }
/* Set the priority of this interrupt */ /* Set the priority of this interrupt */
gicr_set_ipriorityr(gicr_base, current_prop->intr_num, gicr_set_ipriorityr(gicr_base, intr_num,
current_prop->intr_pri); current_prop->intr_pri);
/* /*
* Set interrupt configuration for PPIs. Configuration for SGIs * Set interrupt configuration for (E)PPIs.
* are ignored. * Configurations for SGIs 0-15 are ignored.
*/ */
if ((current_prop->intr_num >= MIN_PPI_ID) && if (intr_num >= MIN_PPI_ID) {
(current_prop->intr_num < MIN_SPI_ID)) { gicr_set_icfgr(gicr_base, intr_num,
gicr_set_icfgr1(gicr_base, current_prop->intr_num,
current_prop->intr_cfg); current_prop->intr_cfg);
} }
/* Enable this interrupt */ /* Enable this interrupt */
gicr_set_isenabler0(gicr_base, current_prop->intr_num); gicr_set_isenabler(gicr_base, intr_num);
} }
return ctlr_enable; return ctlr_enable;
......
This diff is collapsed.
...@@ -26,39 +26,59 @@ ...@@ -26,39 +26,59 @@
/* Calculate GIC register bit number corresponding to its interrupt ID */ /* Calculate GIC register bit number corresponding to its interrupt ID */
#define BIT_NUM(REG, id) \ #define BIT_NUM(REG, id) \
((id) & ((1U << REG##_SHIFT) - 1U)) ((id) & ((1U << REG##R_SHIFT) - 1U))
/* Calculate 8-bit GICD register offset corresponding to its interrupt ID */ /*
* Calculate 8, 32 and 64-bit GICD register offset
* corresponding to its interrupt ID
*/
#if GIC_EXT_INTID
/* GICv3.1 */
#define GICD_OFFSET_8(REG, id) \
(((id) <= MAX_SPI_ID) ? \
GICD_##REG##R + (uintptr_t)(id) : \
GICD_##REG##RE + (uintptr_t)(id) - MIN_ESPI_ID)
#define GICD_OFFSET(REG, id) \
(((id) <= MAX_SPI_ID) ? \
GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2) : \
GICD_##REG##RE + ((((uintptr_t)(id) - MIN_ESPI_ID) >> \
REG##R_SHIFT) << 2))
#define GICD_OFFSET_64(REG, id) \
(((id) <= MAX_SPI_ID) ? \
GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 3) : \
GICD_##REG##RE + (((uintptr_t)(id) - MIN_ESPI_ID) << 3))
#else /* GICv3 */
#define GICD_OFFSET_8(REG, id) \ #define GICD_OFFSET_8(REG, id) \
GICD_##REG + (id) (GICD_##REG##R + (uintptr_t)(id))
/* Calculate 32-bit GICD register offset corresponding to its interrupt ID */
#define GICD_OFFSET(REG, id) \ #define GICD_OFFSET(REG, id) \
GICD_##REG + (((id) >> REG##_SHIFT) << 2) (GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2))
/* Calculate 64-bit GICD register offset corresponding to its interrupt ID */
#define GICD_OFFSET_64(REG, id) \ #define GICD_OFFSET_64(REG, id) \
GICD_##REG + (((id) >> REG##_SHIFT) << 3) (GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 3))
#endif /* GIC_EXT_INTID */
/* Read 32-bit GIC Distributor register corresponding to its interrupt ID */ /*
* Read/Write 8, 32 and 64-bit GIC Distributor register
* corresponding to its interrupt ID
*/
#define GICD_READ(REG, base, id) \ #define GICD_READ(REG, base, id) \
mmio_read_32((base) + GICD_OFFSET(REG, (id))) mmio_read_32((base) + GICD_OFFSET(REG, (id)))
/* Read 64-bit GIC Distributor register corresponding to its interrupt ID */
#define GICD_READ_64(REG, base, id) \ #define GICD_READ_64(REG, base, id) \
mmio_read_64((base) + GICD_OFFSET_64(REG, (id))) mmio_read_64((base) + GICD_OFFSET_64(REG, (id)))
/* Write to 64-bit GIC Distributor register corresponding to its interrupt ID */ #define GICD_WRITE_8(REG, base, id, val) \
#define GICD_WRITE_64(REG, base, id, val) \ mmio_write_8((base) + GICD_OFFSET_8(REG, (id)), (val))
mmio_write_64((base) + GICD_OFFSET_64(REG, (id)), (val))
/* Write to 32-bit GIC Distributor register corresponding to its interrupt ID */ #define GICD_WRITE(REG, base, id, val) \
#define GICD_WRITE(REG, base, id, val) \
mmio_write_32((base) + GICD_OFFSET(REG, (id)), (val)) mmio_write_32((base) + GICD_OFFSET(REG, (id)), (val))
/* Write to 8-bit GIC Distributor register corresponding to its interrupt ID */ #define GICD_WRITE_64(REG, base, id, val) \
#define GICD_WRITE_8(REG, base, id, val) \ mmio_write_64((base) + GICD_OFFSET_64(REG, (id)), (val))
mmio_write_8((base) + GICD_OFFSET_8(REG, (id)), (val))
/* /*
* Bit operations on GIC Distributor register corresponding * Bit operations on GIC Distributor register corresponding
...@@ -80,19 +100,43 @@ ...@@ -80,19 +100,43 @@
((uint32_t)1 << BIT_NUM(REG, (id)))) ((uint32_t)1 << BIT_NUM(REG, (id))))
/* Write bit in GIC Distributor register */ /* Write bit in GIC Distributor register */
#define GICD_WRITE_BIT(REG, base, id) \ #define GICD_WRITE_BIT(REG, base, id) \
mmio_write_32((base) + GICD_OFFSET(REG, (id)), \ mmio_write_32((base) + GICD_OFFSET(REG, (id)), \
((uint32_t)1 << BIT_NUM(REG, (id)))) ((uint32_t)1 << BIT_NUM(REG, (id))))
/* /*
* Calculate GICv3 GICR register offset * Calculate 8 and 32-bit GICR register offset
* corresponding to its interrupt ID
*/ */
#if GIC_EXT_INTID
/* GICv3.1 */
#define GICR_OFFSET_8(REG, id) \
(((id) <= MAX_PPI_ID) ? \
GICR_##REG##R + (uintptr_t)(id) : \
GICR_##REG##R + (uintptr_t)(id) - (MIN_EPPI_ID - MIN_SPI_ID))
#define GICR_OFFSET(REG, id) \
(((id) <= MAX_PPI_ID) ? \
GICR_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2) : \
GICR_##REG##R + ((((uintptr_t)(id) - (MIN_EPPI_ID - MIN_SPI_ID))\
>> REG##R_SHIFT) << 2))
#else /* GICv3 */
#define GICR_OFFSET_8(REG, id) \
(GICR_##REG##R + (uintptr_t)(id))
#define GICR_OFFSET(REG, id) \ #define GICR_OFFSET(REG, id) \
GICR_##REG + (((id) >> REG##_SHIFT) << 2) (GICR_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2))
#endif
/* Write to GIC Redistributor register corresponding to its interrupt ID */ /* Read/Write GIC Redistributor register corresponding to its interrupt ID */
#define GICR_WRITE_8(REG, base, id, val) \ #define GICR_READ(REG, base, id) \
mmio_write_8((base) + GICR_##REG + (id), (val)) mmio_read_32((base) + GICR_OFFSET(REG, (id)))
#define GICR_WRITE_8(REG, base, id, val) \
mmio_write_8((base) + GICR_OFFSET_8(REG, (id)), (val))
#define GICR_WRITE(REG, base, id, val) \
mmio_write((base) + GICR_OFFSET(REG, (id)), (val))
/* /*
* Bit operations on GIC Redistributor register * Bit operations on GIC Redistributor register
...@@ -105,7 +149,7 @@ ...@@ -105,7 +149,7 @@
/* Write bit in GIC Redistributor register */ /* Write bit in GIC Redistributor register */
#define GICR_WRITE_BIT(REG, base, id) \ #define GICR_WRITE_BIT(REG, base, id) \
mmio_write_32((base) + GICR_OFFSET(REG, (id)), \ mmio_write_32((base) + GICR_OFFSET(REG, (id)), \
((uint32_t)1 << BIT_NUM(REG, (id)))) ((uint32_t)1 << BIT_NUM(REG, (id))))
/* Set bit in GIC Redistributor register */ /* Set bit in GIC Redistributor register */
...@@ -157,10 +201,8 @@ extern const gicv3_driver_data_t *gicv3_driver_data; ...@@ -157,10 +201,8 @@ extern const gicv3_driver_data_t *gicv3_driver_data;
* Note: The raw register values correspond to multiple interrupt IDs and * Note: The raw register values correspond to multiple interrupt IDs and
* the number of interrupt IDs involved depends on the register accessed. * the number of interrupt IDs involved depends on the register accessed.
******************************************************************************/ ******************************************************************************/
uint32_t gicd_read_igrpmodr(uintptr_t base, unsigned int id); unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id);
unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id); void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val);
void gicd_write_igrpmodr(uintptr_t base, unsigned int id, uint32_t val);
void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val);
/******************************************************************************* /*******************************************************************************
* Private GICv3 function prototypes for accessing the GIC registers * Private GICv3 function prototypes for accessing the GIC registers
...@@ -169,22 +211,21 @@ void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val); ...@@ -169,22 +211,21 @@ void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val);
* the bit-field corresponding the single interrupt ID. * the bit-field corresponding the single interrupt ID.
******************************************************************************/ ******************************************************************************/
unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id); unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id);
unsigned int gicr_get_igrpmodr0(uintptr_t base, unsigned int id); unsigned int gicr_get_igrpmodr(uintptr_t base, unsigned int id);
unsigned int gicr_get_igroupr0(uintptr_t base, unsigned int id); unsigned int gicr_get_igroupr(uintptr_t base, unsigned int id);
unsigned int gicr_get_isactiver0(uintptr_t base, unsigned int id); unsigned int gicr_get_isactiver(uintptr_t base, unsigned int id);
void gicd_set_igrpmodr(uintptr_t base, unsigned int id); void gicd_set_igrpmodr(uintptr_t base, unsigned int id);
void gicr_set_igrpmodr0(uintptr_t base, unsigned int id); void gicr_set_igrpmodr(uintptr_t base, unsigned int id);
void gicr_set_isenabler0(uintptr_t base, unsigned int id); void gicr_set_isenabler(uintptr_t base, unsigned int id);
void gicr_set_icenabler0(uintptr_t base, unsigned int id); void gicr_set_icenabler(uintptr_t base, unsigned int id);
void gicr_set_ispendr0(uintptr_t base, unsigned int id); void gicr_set_ispendr(uintptr_t base, unsigned int id);
void gicr_set_icpendr0(uintptr_t base, unsigned int id); void gicr_set_icpendr(uintptr_t base, unsigned int id);
void gicr_set_igroupr0(uintptr_t base, unsigned int id); void gicr_set_igroupr(uintptr_t base, unsigned int id);
void gicd_clr_igrpmodr(uintptr_t base, unsigned int id); void gicd_clr_igrpmodr(uintptr_t base, unsigned int id);
void gicr_clr_igrpmodr0(uintptr_t base, unsigned int id); void gicr_clr_igrpmodr(uintptr_t base, unsigned int id);
void gicr_clr_igroupr0(uintptr_t base, unsigned int id); void gicr_clr_igroupr(uintptr_t base, unsigned int id);
void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri); void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri);
void gicr_set_icfgr0(uintptr_t base, unsigned int id, unsigned int cfg); void gicr_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg);
void gicr_set_icfgr1(uintptr_t base, unsigned int id, unsigned int cfg);
/******************************************************************************* /*******************************************************************************
* Private GICv3 helper function prototypes * Private GICv3 helper function prototypes
...@@ -208,10 +249,10 @@ void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base); ...@@ -208,10 +249,10 @@ void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base);
* GIC Distributor interface accessors * GIC Distributor interface accessors
******************************************************************************/ ******************************************************************************/
/* /*
* Wait for updates to : * Wait for updates to:
* GICD_CTLR[2:0] - the Group Enables * GICD_CTLR[2:0] - the Group Enables
* GICD_CTLR[5:4] - the ARE bits * GICD_CTLR[7:4] - the ARE bits, E1NWF bit and DS bit
* GICD_ICENABLERn - the clearing of enable state for SPIs * GICD_ICENABLER<n> - the clearing of enable state for SPIs
*/ */
static inline void gicd_wait_for_pending_write(uintptr_t gicd_base) static inline void gicd_wait_for_pending_write(uintptr_t gicd_base)
{ {
...@@ -227,7 +268,7 @@ static inline uint32_t gicd_read_pidr2(uintptr_t base) ...@@ -227,7 +268,7 @@ static inline uint32_t gicd_read_pidr2(uintptr_t base)
static inline uint64_t gicd_read_irouter(uintptr_t base, unsigned int id) static inline uint64_t gicd_read_irouter(uintptr_t base, unsigned int id)
{ {
assert(id >= MIN_SPI_ID); assert(id >= MIN_SPI_ID);
return GICD_READ_64(IROUTER, base, id); return GICD_READ_64(IROUTE, base, id);
} }
static inline void gicd_write_irouter(uintptr_t base, static inline void gicd_write_irouter(uintptr_t base,
...@@ -235,7 +276,7 @@ static inline void gicd_write_irouter(uintptr_t base, ...@@ -235,7 +276,7 @@ static inline void gicd_write_irouter(uintptr_t base,
uint64_t affinity) uint64_t affinity)
{ {
assert(id >= MIN_SPI_ID); assert(id >= MIN_SPI_ID);
GICD_WRITE_64(IROUTER, base, id, affinity); GICD_WRITE_64(IROUTE, base, id, affinity);
} }
static inline void gicd_clr_ctlr(uintptr_t base, static inline void gicd_clr_ctlr(uintptr_t base,
...@@ -287,11 +328,12 @@ static inline void gicr_write_waker(uintptr_t base, uint32_t val) ...@@ -287,11 +328,12 @@ static inline void gicr_write_waker(uintptr_t base, uint32_t val)
} }
/* /*
* Wait for updates to : * Wait for updates to:
* GICR_ICENABLER0 * GICR_ICENABLER0
* GICR_CTLR.DPG1S * GICR_CTLR.DPG1S
* GICR_CTLR.DPG1NS * GICR_CTLR.DPG1NS
* GICR_CTLR.DPG0 * GICR_CTLR.DPG0
* GICR_CTLR, which clears EnableLPIs from 1 to 0
*/ */
static inline void gicr_wait_for_pending_write(uintptr_t gicr_base) static inline void gicr_wait_for_pending_write(uintptr_t gicr_base)
{ {
...@@ -314,101 +356,150 @@ void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num); ...@@ -314,101 +356,150 @@ void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num);
* Note: The raw register values correspond to multiple interrupt IDs and * Note: The raw register values correspond to multiple interrupt IDs and
* the number of interrupt IDs involved depends on the register accessed. * the number of interrupt IDs involved depends on the register accessed.
******************************************************************************/ ******************************************************************************/
static inline unsigned int gicr_read_icenabler0(uintptr_t base)
{
return mmio_read_32(base + GICR_ICENABLER0);
}
static inline void gicr_write_icenabler0(uintptr_t base, unsigned int val) /*
* Accessors to read/write GIC Redistributor ICENABLER0 and ICENABLERE
* register corresponding to its number
*/
static inline unsigned int gicr_read_icenabler(uintptr_t base,
unsigned int reg_num)
{ {
mmio_write_32(base + GICR_ICENABLER0, val); return mmio_read_32(base + GICR_ICENABLER + (reg_num << 2));
} }
static inline unsigned int gicr_read_isenabler0(uintptr_t base) static inline void gicr_write_icenabler(uintptr_t base, unsigned int reg_num,
unsigned int val)
{ {
return mmio_read_32(base + GICR_ISENABLER0); mmio_write_32(base + GICR_ICENABLER + (reg_num << 2), val);
} }
static inline void gicr_write_icpendr0(uintptr_t base, unsigned int val) /*
* Accessor to read/write GIC Redistributor ICFGR0, ICFGR1 and ICFGRE
* register corresponding to its number
*/
static inline unsigned int gicr_read_icfgr(uintptr_t base, unsigned int reg_num)
{ {
mmio_write_32(base + GICR_ICPENDR0, val); return mmio_read_32(base + GICR_ICFGR + (reg_num << 2));
} }
static inline void gicr_write_isenabler0(uintptr_t base, unsigned int val) static inline void gicr_write_icfgr(uintptr_t base, unsigned int reg_num,
unsigned int val)
{ {
mmio_write_32(base + GICR_ISENABLER0, val); mmio_write_32(base + GICR_ICFGR + (reg_num << 2), val);
} }
static inline unsigned int gicr_read_igroupr0(uintptr_t base) /*
* Accessors to read/write GIC Redistributor IGROUPR0 and IGROUPRE
* register corresponding to its number
*/
static inline unsigned int gicr_read_igroupr(uintptr_t base,
unsigned int reg_num)
{ {
return mmio_read_32(base + GICR_IGROUPR0); return mmio_read_32(base + GICR_IGROUPR + (reg_num << 2));
} }
static inline unsigned int gicr_read_ispendr0(uintptr_t base) static inline void gicr_write_igroupr(uintptr_t base, unsigned int reg_num,
unsigned int val)
{ {
return mmio_read_32(base + GICR_ISPENDR0); mmio_write_32(base + GICR_IGROUPR + (reg_num << 2), val);
} }
static inline void gicr_write_ispendr0(uintptr_t base, unsigned int val) /*
* Accessors to read/write GIC Redistributor IGRPMODR0 and IGRPMODRE
* register corresponding to its number
*/
static inline unsigned int gicr_read_igrpmodr(uintptr_t base,
unsigned int reg_num)
{ {
mmio_write_32(base + GICR_ISPENDR0, val); return mmio_read_32(base + GICR_IGRPMODR + (reg_num << 2));
} }
static inline void gicr_write_igroupr0(uintptr_t base, unsigned int val) static inline void gicr_write_igrpmodr(uintptr_t base, unsigned int reg_num,
unsigned int val)
{ {
mmio_write_32(base + GICR_IGROUPR0, val); mmio_write_32(base + GICR_IGRPMODR + (reg_num << 2), val);
} }
static inline unsigned int gicr_read_igrpmodr0(uintptr_t base) /*
* Accessors to read/write the GIC Redistributor IPRIORITYR(E) register
* corresponding to its number, 4 interrupts IDs at a time.
*/
static inline unsigned int gicr_read_ipriorityr(uintptr_t base,
unsigned int reg_num)
{ {
return mmio_read_32(base + GICR_IGRPMODR0); return mmio_read_32(base + GICR_IPRIORITYR + (reg_num << 2));
} }
static inline void gicr_write_igrpmodr0(uintptr_t base, unsigned int val) static inline void gicr_write_ipriorityr(uintptr_t base, unsigned int reg_num,
unsigned int val)
{ {
mmio_write_32(base + GICR_IGRPMODR0, val); mmio_write_32(base + GICR_IPRIORITYR + (reg_num << 2), val);
} }
static inline unsigned int gicr_read_nsacr(uintptr_t base) /*
* Accessors to read/write GIC Redistributor ISACTIVER0 and ISACTIVERE
* register corresponding to its number
*/
static inline unsigned int gicr_read_isactiver(uintptr_t base,
unsigned int reg_num)
{ {
return mmio_read_32(base + GICR_NSACR); return mmio_read_32(base + GICR_ISACTIVER + (reg_num << 2));
} }
static inline void gicr_write_nsacr(uintptr_t base, unsigned int val) static inline void gicr_write_isactiver(uintptr_t base, unsigned int reg_num,
unsigned int val)
{ {
mmio_write_32(base + GICR_NSACR, val); mmio_write_32(base + GICR_ISACTIVER + (reg_num << 2), val);
} }
static inline unsigned int gicr_read_isactiver0(uintptr_t base) /*
* Accessors to read/write GIC Redistributor ISENABLER0 and ISENABLERE
* register corresponding to its number
*/
static inline unsigned int gicr_read_isenabler(uintptr_t base,
unsigned int reg_num)
{ {
return mmio_read_32(base + GICR_ISACTIVER0); return mmio_read_32(base + GICR_ISENABLER + (reg_num << 2));
} }
static inline void gicr_write_isactiver0(uintptr_t base, unsigned int val) static inline void gicr_write_isenabler(uintptr_t base, unsigned int reg_num,
unsigned int val)
{ {
mmio_write_32(base + GICR_ISACTIVER0, val); mmio_write_32(base + GICR_ISENABLER + (reg_num << 2), val);
} }
static inline unsigned int gicr_read_icfgr0(uintptr_t base) /*
* Accessors to read/write GIC Redistributor ISPENDR0 and ISPENDRE
* register corresponding to its number
*/
static inline unsigned int gicr_read_ispendr(uintptr_t base,
unsigned int reg_num)
{ {
return mmio_read_32(base + GICR_ICFGR0); return mmio_read_32(base + GICR_ISPENDR + (reg_num << 2));
} }
static inline unsigned int gicr_read_icfgr1(uintptr_t base) static inline void gicr_write_ispendr(uintptr_t base, unsigned int reg_num,
unsigned int val)
{ {
return mmio_read_32(base + GICR_ICFGR1); mmio_write_32(base + GICR_ISPENDR + (reg_num << 2), val);
} }
static inline void gicr_write_icfgr0(uintptr_t base, unsigned int val) /*
* Accessors to read/write GIC Redistributor NSACR register
*/
static inline unsigned int gicr_read_nsacr(uintptr_t base)
{ {
mmio_write_32(base + GICR_ICFGR0, val); return mmio_read_32(base + GICR_NSACR);
} }
static inline void gicr_write_icfgr1(uintptr_t base, unsigned int val) static inline void gicr_write_nsacr(uintptr_t base, unsigned int val)
{ {
mmio_write_32(base + GICR_ICFGR1, val); mmio_write_32(base + GICR_NSACR, val);
} }
/*
* Accessors to read/write GIC Redistributor PROPBASER register
*/
static inline uint64_t gicr_read_propbaser(uintptr_t base) static inline uint64_t gicr_read_propbaser(uintptr_t base)
{ {
return mmio_read_64(base + GICR_PROPBASER); return mmio_read_64(base + GICR_PROPBASER);
...@@ -419,6 +510,9 @@ static inline void gicr_write_propbaser(uintptr_t base, uint64_t val) ...@@ -419,6 +510,9 @@ static inline void gicr_write_propbaser(uintptr_t base, uint64_t val)
mmio_write_64(base + GICR_PROPBASER, val); mmio_write_64(base + GICR_PROPBASER, val);
} }
/*
* Accessors to read/write GIC Redistributor PENDBASER register
*/
static inline uint64_t gicr_read_pendbaser(uintptr_t base) static inline uint64_t gicr_read_pendbaser(uintptr_t base)
{ {
return mmio_read_64(base + GICR_PENDBASER); return mmio_read_64(base + GICR_PENDBASER);
......
/* /*
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#define GIC_HIGHEST_NS_PRIORITY U(0x80) #define GIC_HIGHEST_NS_PRIORITY U(0x80)
/******************************************************************************* /*******************************************************************************
* GIC Distributor interface register offsets that are common to GICv3 & GICv2 * Common GIC Distributor interface register offsets
******************************************************************************/ ******************************************************************************/
#define GICD_CTLR U(0x0) #define GICD_CTLR U(0x0)
#define GICD_TYPER U(0x4) #define GICD_TYPER U(0x4)
...@@ -61,19 +61,17 @@ ...@@ -61,19 +61,17 @@
#define CTLR_ENABLE_G0_MASK U(0x1) #define CTLR_ENABLE_G0_MASK U(0x1)
#define CTLR_ENABLE_G0_BIT BIT_32(CTLR_ENABLE_G0_SHIFT) #define CTLR_ENABLE_G0_BIT BIT_32(CTLR_ENABLE_G0_SHIFT)
/******************************************************************************* /*******************************************************************************
* GIC Distributor interface register constants that are common to GICv3 & GICv2 * Common GIC Distributor interface register constants
******************************************************************************/ ******************************************************************************/
#define PIDR2_ARCH_REV_SHIFT 4 #define PIDR2_ARCH_REV_SHIFT 4
#define PIDR2_ARCH_REV_MASK U(0xf) #define PIDR2_ARCH_REV_MASK U(0xf)
/* GICv3 revision as reported by the PIDR2 register */ /* GIC revision as reported by PIDR2.ArchRev register field */
#define ARCH_REV_GICV3 U(0x3)
/* GICv2 revision as reported by the PIDR2 register */
#define ARCH_REV_GICV2 U(0x2)
/* GICv1 revision as reported by the PIDR2 register */
#define ARCH_REV_GICV1 U(0x1) #define ARCH_REV_GICV1 U(0x1)
#define ARCH_REV_GICV2 U(0x2)
#define ARCH_REV_GICV3 U(0x3)
#define ARCH_REV_GICV4 U(0x4)
#define IGROUPR_SHIFT 5 #define IGROUPR_SHIFT 5
#define ISENABLER_SHIFT 5 #define ISENABLER_SHIFT 5
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#define GICV3_H #define GICV3_H
/******************************************************************************* /*******************************************************************************
* GICv3 miscellaneous definitions * GICv3 and 3.1 miscellaneous definitions
******************************************************************************/ ******************************************************************************/
/* Interrupt group definitions */ /* Interrupt group definitions */
#define INTR_GROUP1S U(0) #define INTR_GROUP1S U(0)
...@@ -25,20 +25,85 @@ ...@@ -25,20 +25,85 @@
/* GICv3 can only target up to 16 PEs with SGI */ /* GICv3 can only target up to 16 PEs with SGI */
#define GICV3_MAX_SGI_TARGETS U(16) #define GICV3_MAX_SGI_TARGETS U(16)
/* PPIs INTIDs 16-31 */
#define MAX_PPI_ID U(31)
#if GIC_EXT_INTID
/* GICv3.1 extended PPIs INTIDs 1056-1119 */
#define MIN_EPPI_ID U(1056)
#define MAX_EPPI_ID U(1119)
/* Total number of GICv3.1 EPPIs */
#define TOTAL_EPPI_INTR_NUM (MAX_EPPI_ID - MIN_EPPI_ID + U(1))
/* Total number of GICv3.1 PPIs and EPPIs */
#define TOTAL_PRIVATE_INTR_NUM (TOTAL_PCPU_INTR_NUM + TOTAL_EPPI_INTR_NUM)
/* GICv3.1 extended SPIs INTIDs 4096 - 5119 */
#define MIN_ESPI_ID U(4096)
#define MAX_ESPI_ID U(5119)
/* Total number of GICv3.1 ESPIs */
#define TOTAL_ESPI_INTR_NUM (MAX_ESPI_ID - MIN_ESPI_ID + U(1))
/* Total number of GICv3.1 SPIs and ESPIs */
#define TOTAL_SHARED_INTR_NUM (TOTAL_SPI_INTR_NUM + TOTAL_ESPI_INTR_NUM)
/* SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119 */
#define IS_SGI_PPI(id) (((id) <= MAX_PPI_ID) || \
(((id) >= MIN_EPPI_ID) && \
((id) <= MAX_EPPI_ID)))
/* SPIs: 32-1019, ESPIs: 4096-5119 */
#define IS_SPI(id) ((((id) >= MIN_SPI_ID) && \
((id) <= MAX_SPI_ID)) || \
(((id) >= MIN_ESPI_ID) && \
((id) <= MAX_ESPI_ID)))
#else /* GICv3 */
/* Total number of GICv3 PPIs */
#define TOTAL_PRIVATE_INTR_NUM TOTAL_PCPU_INTR_NUM
/* Total number of GICv3 SPIs */
#define TOTAL_SHARED_INTR_NUM TOTAL_SPI_INTR_NUM
/* SGIs: 0-15, PPIs: 16-31 */
#define IS_SGI_PPI(id) ((id) <= MAX_PPI_ID)
/* SPIs: 32-1019 */
#define IS_SPI(id) (((id) >= MIN_SPI_ID) && ((id) <= MAX_SPI_ID))
#endif /* GIC_EXT_INTID */
/******************************************************************************* /*******************************************************************************
* GICv3 specific Distributor interface register offsets and constants. * GICv3 and 3.1 specific Distributor interface register offsets and constants
******************************************************************************/ ******************************************************************************/
#define GICD_TYPER2 U(0x0c)
#define GICD_STATUSR U(0x10) #define GICD_STATUSR U(0x10)
#define GICD_SETSPI_NSR U(0x40) #define GICD_SETSPI_NSR U(0x40)
#define GICD_CLRSPI_NSR U(0x48) #define GICD_CLRSPI_NSR U(0x48)
#define GICD_SETSPI_SR U(0x50) #define GICD_SETSPI_SR U(0x50)
#define GICD_CLRSPI_SR U(0x58) #define GICD_CLRSPI_SR U(0x58)
#define GICD_IGRPMODR U(0xd00) #define GICD_IGRPMODR U(0xd00)
#define GICD_IGROUPRE U(0x1000)
#define GICD_ISENABLERE U(0x1200)
#define GICD_ICENABLERE U(0x1400)
#define GICD_ISPENDRE U(0x1600)
#define GICD_ICPENDRE U(0x1800)
#define GICD_ISACTIVERE U(0x1a00)
#define GICD_ICACTIVERE U(0x1c00)
#define GICD_IPRIORITYRE U(0x2000)
#define GICD_ICFGRE U(0x3000)
#define GICD_IGRPMODRE U(0x3400)
#define GICD_NSACRE U(0x3600)
/* /*
* GICD_IROUTER<n> register is at 0x6000 + 8n, where n is the interrupt id and * GICD_IROUTER<n> register is at 0x6000 + 8n, where n is the interrupt ID
* n >= 32, making the effective offset as 0x6100. * and n >= 32, making the effective offset as 0x6100
*/ */
#define GICD_IROUTER U(0x6000) #define GICD_IROUTER U(0x6000)
#define GICD_IROUTERE U(0x8000)
#define GICD_PIDR2_GICV3 U(0xffe8) #define GICD_PIDR2_GICV3 U(0xffe8)
#define IGRPMODR_SHIFT 5 #define IGRPMODR_SHIFT 5
...@@ -78,14 +143,26 @@ ...@@ -78,14 +143,26 @@
#define NUM_OF_DIST_REGS 30 #define NUM_OF_DIST_REGS 30
/* GICD_TYPER shifts and masks */
#define TYPER_ESPI U(1 << 8)
#define TYPER_DVIS U(1 << 18)
#define TYPER_ESPI_RANGE_MASK U(0x1f)
#define TYPER_ESPI_RANGE_SHIFT U(27)
#define TYPER_ESPI_RANGE U(TYPER_ESPI_MASK << TYPER_ESPI_SHIFT)
/******************************************************************************* /*******************************************************************************
* GICv3 Redistributor interface registers & constants * Common GIC Redistributor interface registers & constants
******************************************************************************/ ******************************************************************************/
#if GIC_ENABLE_V4_EXTN
#define GICR_PCPUBASE_SHIFT 0x12
#else
#define GICR_PCPUBASE_SHIFT 0x11 #define GICR_PCPUBASE_SHIFT 0x11
#endif
#define GICR_SGIBASE_OFFSET U(65536) /* 64 KB */ #define GICR_SGIBASE_OFFSET U(65536) /* 64 KB */
#define GICR_CTLR U(0x0) #define GICR_CTLR U(0x0)
#define GICR_IIDR U(0x04) #define GICR_IIDR U(0x04)
#define GICR_TYPER U(0x08) #define GICR_TYPER U(0x08)
#define GICR_STATUSR U(0x10)
#define GICR_WAKER U(0x14) #define GICR_WAKER U(0x14)
#define GICR_PROPBASER U(0x70) #define GICR_PROPBASER U(0x70)
#define GICR_PENDBASER U(0x78) #define GICR_PENDBASER U(0x78)
...@@ -102,6 +179,16 @@ ...@@ -102,6 +179,16 @@
#define GICR_IGRPMODR0 (GICR_SGIBASE_OFFSET + U(0xd00)) #define GICR_IGRPMODR0 (GICR_SGIBASE_OFFSET + U(0xd00))
#define GICR_NSACR (GICR_SGIBASE_OFFSET + U(0xe00)) #define GICR_NSACR (GICR_SGIBASE_OFFSET + U(0xe00))
#define GICR_IGROUPR GICR_IGROUPR0
#define GICR_ISENABLER GICR_ISENABLER0
#define GICR_ICENABLER GICR_ICENABLER0
#define GICR_ISPENDR GICR_ISPENDR0
#define GICR_ICPENDR GICR_ICPENDR0
#define GICR_ISACTIVER GICR_ISACTIVER0
#define GICR_ICACTIVER GICR_ICACTIVER0
#define GICR_ICFGR GICR_ICFGR0
#define GICR_IGRPMODR GICR_IGRPMODR0
/* GICR_CTLR bit definitions */ /* GICR_CTLR bit definitions */
#define GICR_CTLR_UWP_SHIFT 31 #define GICR_CTLR_UWP_SHIFT 31
#define GICR_CTLR_UWP_MASK U(0x1) #define GICR_CTLR_UWP_MASK U(0x1)
...@@ -132,12 +219,13 @@ ...@@ -132,12 +219,13 @@
#define TYPER_LAST_BIT BIT_32(TYPER_LAST_SHIFT) #define TYPER_LAST_BIT BIT_32(TYPER_LAST_SHIFT)
#define NUM_OF_REDIST_REGS 30 #define TYPER_PPI_NUM_SHIFT U(27)
#define TYPER_PPI_NUM_MASK U(0x1f)
/******************************************************************************* /*******************************************************************************
* GICv3 CPU interface registers & constants * GICv3 and 3.1 CPU interface registers & constants
******************************************************************************/ ******************************************************************************/
/* ICC_SRE bit definitions*/ /* ICC_SRE bit definitions */
#define ICC_SRE_EN_BIT BIT_32(3) #define ICC_SRE_EN_BIT BIT_32(3)
#define ICC_SRE_DIB_BIT BIT_32(2) #define ICC_SRE_DIB_BIT BIT_32(2)
#define ICC_SRE_DFB_BIT BIT_32(1) #define ICC_SRE_DFB_BIT BIT_32(1)
...@@ -192,9 +280,8 @@ ...@@ -192,9 +280,8 @@
((_tgt) & SGIR_TGT_MASK)) ((_tgt) & SGIR_TGT_MASK))
/***************************************************************************** /*****************************************************************************
* GICv3 ITS registers and constants * GICv3 and 3.1 ITS registers and constants
*****************************************************************************/ *****************************************************************************/
#define GITS_CTLR U(0x0) #define GITS_CTLR U(0x0)
#define GITS_IIDR U(0x4) #define GITS_IIDR U(0x4)
#define GITS_TYPER U(0x8) #define GITS_TYPER U(0x8)
...@@ -205,8 +292,7 @@ ...@@ -205,8 +292,7 @@
/* GITS_CTLR bit definitions */ /* GITS_CTLR bit definitions */
#define GITS_CTLR_ENABLED_BIT BIT_32(0) #define GITS_CTLR_ENABLED_BIT BIT_32(0)
#define GITS_CTLR_QUIESCENT_SHIFT 31 #define GITS_CTLR_QUIESCENT_BIT BIT_32(1)
#define GITS_CTLR_QUIESCENT_BIT BIT_32(GITS_CTLR_QUIESCENT_SHIFT)
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
...@@ -224,7 +310,7 @@ static inline bool gicv3_is_intr_id_special_identifier(unsigned int id) ...@@ -224,7 +310,7 @@ static inline bool gicv3_is_intr_id_special_identifier(unsigned int id)
} }
/******************************************************************************* /*******************************************************************************
* Helper GICv3 macros for SEL1 * Helper GICv3 and 3.1 macros for SEL1
******************************************************************************/ ******************************************************************************/
static inline uint32_t gicv3_acknowledge_interrupt_sel1(void) static inline uint32_t gicv3_acknowledge_interrupt_sel1(void)
{ {
...@@ -255,14 +341,14 @@ static inline void gicv3_end_of_interrupt(unsigned int id) ...@@ -255,14 +341,14 @@ static inline void gicv3_end_of_interrupt(unsigned int id)
} }
/* /*
* This macro returns the total number of GICD registers corresponding to * This macro returns the total number of GICD/GICR registers corresponding to
* the name. * the register name
*/ */
#define GICD_NUM_REGS(reg_name) \ #define GICD_NUM_REGS(reg_name) \
DIV_ROUND_UP_2EVAL(TOTAL_SPI_INTR_NUM, (1 << reg_name ## _SHIFT)) DIV_ROUND_UP_2EVAL(TOTAL_SHARED_INTR_NUM, (1 << reg_name##_SHIFT))
#define GICR_NUM_REGS(reg_name) \ #define GICR_NUM_REGS(reg_name) \
DIV_ROUND_UP_2EVAL(TOTAL_PCPU_INTR_NUM, (1 << reg_name ## _SHIFT)) DIV_ROUND_UP_2EVAL(TOTAL_PRIVATE_INTR_NUM, (1 << reg_name##_SHIFT))
/* Interrupt ID mask for HPPIR, AHPPIR, IAR and AIAR CPU Interface registers */ /* Interrupt ID mask for HPPIR, AHPPIR, IAR and AIAR CPU Interface registers */
#define INT_ID_MASK U(0xffffff) #define INT_ID_MASK U(0xffffff)
...@@ -325,20 +411,19 @@ typedef struct gicv3_redist_ctx { ...@@ -325,20 +411,19 @@ typedef struct gicv3_redist_ctx {
/* 32 bits registers */ /* 32 bits registers */
uint32_t gicr_ctlr; uint32_t gicr_ctlr;
uint32_t gicr_igroupr0; uint32_t gicr_igroupr[GICR_NUM_REGS(IGROUPR)];
uint32_t gicr_isenabler0; uint32_t gicr_isenabler[GICR_NUM_REGS(ISENABLER)];
uint32_t gicr_ispendr0; uint32_t gicr_ispendr[GICR_NUM_REGS(ISPENDR)];
uint32_t gicr_isactiver0; uint32_t gicr_isactiver[GICR_NUM_REGS(ISACTIVER)];
uint32_t gicr_ipriorityr[GICR_NUM_REGS(IPRIORITYR)]; uint32_t gicr_ipriorityr[GICR_NUM_REGS(IPRIORITYR)];
uint32_t gicr_icfgr0; uint32_t gicr_icfgr[GICR_NUM_REGS(ICFGR)];
uint32_t gicr_icfgr1; uint32_t gicr_igrpmodr[GICR_NUM_REGS(IGRPMODR)];
uint32_t gicr_igrpmodr0;
uint32_t gicr_nsacr; uint32_t gicr_nsacr;
} gicv3_redist_ctx_t; } gicv3_redist_ctx_t;
typedef struct gicv3_dist_ctx { typedef struct gicv3_dist_ctx {
/* 64 bits registers */ /* 64 bits registers */
uint64_t gicd_irouter[TOTAL_SPI_INTR_NUM]; uint64_t gicd_irouter[TOTAL_SHARED_INTR_NUM];
/* 32 bits registers */ /* 32 bits registers */
uint32_t gicd_ctlr; uint32_t gicd_ctlr;
......
...@@ -52,10 +52,18 @@ ...@@ -52,10 +52,18 @@
#define DEVICE1_BASE UL(0x2e000000) #define DEVICE1_BASE UL(0x2e000000)
#define DEVICE1_SIZE UL(0x1A00000) #define DEVICE1_SIZE UL(0x1A00000)
#else #else
/* GICv2 and GICv3 mapping: GICD + CORE_COUNT * 128KB */
#define DEVICE1_BASE BASE_GICD_BASE #define DEVICE1_BASE BASE_GICD_BASE
#if GIC_ENABLE_V4_EXTN
/* GICv4 mapping: GICD + CORE_COUNT * 256KB */
#define DEVICE1_SIZE ((BASE_GICR_BASE - BASE_GICD_BASE) + \
(PLATFORM_CORE_COUNT * 0x40000))
#else
/* GICv2 and GICv3 mapping: GICD + CORE_COUNT * 128KB */
#define DEVICE1_SIZE ((BASE_GICR_BASE - BASE_GICD_BASE) + \ #define DEVICE1_SIZE ((BASE_GICR_BASE - BASE_GICD_BASE) + \
(PLATFORM_CORE_COUNT * 0x20000)) (PLATFORM_CORE_COUNT * 0x20000))
#endif /* GIC_ENABLE_V4_EXTN */
#define NSRAM_BASE UL(0x2e000000) #define NSRAM_BASE UL(0x2e000000)
#define NSRAM_SIZE UL(0x10000) #define NSRAM_SIZE UL(0x10000)
#endif #endif
......
...@@ -50,12 +50,12 @@ $(eval $(call add_define,FVP_INTERCONNECT_DRIVER)) ...@@ -50,12 +50,12 @@ $(eval $(call add_define,FVP_INTERCONNECT_DRIVER))
# Choose the GIC sources depending upon the how the FVP will be invoked # Choose the GIC sources depending upon the how the FVP will be invoked
ifeq (${FVP_USE_GIC_DRIVER},$(filter ${FVP_USE_GIC_DRIVER},FVP_GICV3 FVP_GIC600)) ifeq (${FVP_USE_GIC_DRIVER},$(filter ${FVP_USE_GIC_DRIVER},FVP_GICV3 FVP_GIC600))
# GIC500 is the default option in case GICV3_IMPL is not set
ifeq (${FVP_USE_GIC_DRIVER}, FVP_GIC600) ifeq (${FVP_USE_GIC_DRIVER}, FVP_GIC600)
GICV3_IMPL := GIC600 GICV3_IMPL := GIC600
endif endif
# GIC500 is the default option in case GICV3_IMPL is not set
GICV3_OVERRIDE_DISTIF_PWR_OPS := 1 GICV3_OVERRIDE_DISTIF_PWR_OPS := 1
# Include GICv3 driver files # Include GICv3 driver files
...@@ -66,6 +66,15 @@ FVP_GIC_SOURCES := ${GICV3_SOURCES} \ ...@@ -66,6 +66,15 @@ FVP_GIC_SOURCES := ${GICV3_SOURCES} \
plat/arm/common/arm_gicv3.c plat/arm/common/arm_gicv3.c
else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV2) else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV2)
# No GICv4 extension
GIC_ENABLE_V4_EXTN := 0
$(eval $(call add_define,GIC_ENABLE_V4_EXTN))
# No support for extended PPI and SPI range
GIC_EXT_INTID := 0
$(eval $(call add_define,GIC_EXT_INTID))
FVP_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ FVP_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
drivers/arm/gic/v2/gicv2_main.c \ drivers/arm/gic/v2/gicv2_main.c \
drivers/arm/gic/v2/gicv2_helpers.c \ drivers/arm/gic/v2/gicv2_helpers.c \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment