diff options
Diffstat (limited to 'drivers/arm/gic/v3/gic-x00.c')
-rw-r--r-- | drivers/arm/gic/v3/gic-x00.c | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c index 6e106babfb..83ef32f056 100644 --- a/drivers/arm/gic/v3/gic-x00.c +++ b/drivers/arm/gic/v3/gic-x00.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -16,15 +16,14 @@ #include <assert.h> #include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/arm_gicv3_common.h> #include <drivers/arm/gicv3.h> #include "gicv3_private.h" /* GIC-600 specific register offsets */ #define GICR_PWRR 0x24U -#define IIDR_MODEL_ARM_GIC_600 U(0x0200043b) -#define IIDR_MODEL_ARM_GIC_600AE U(0x0300043b) -#define IIDR_MODEL_ARM_GIC_CLAYTON U(0x0400043b) /* GICR_PWRR fields */ #define PWRR_RDPD_SHIFT 0 @@ -44,9 +43,11 @@ #define PWRR_ON (0U << PWRR_RDPD_SHIFT) #define PWRR_OFF (1U << PWRR_RDPD_SHIFT) +static bool gic600_errata_wa_2384374 __unused; + #if GICV3_SUPPORT_GIC600 -/* GIC-600/Clayton specific accessor functions */ +/* GIC-600/700 specific accessor functions */ static void gicr_write_pwrr(uintptr_t base, unsigned int val) { mmio_write_32(base + GICR_PWRR, val); @@ -123,12 +124,12 @@ static bool gicv3_redists_need_power_mgmt(uintptr_t gicr_base) uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR); /* - * The Arm GIC-600 and GIC-Clayton models have their redistributors + * The Arm GIC-600 and GIC-700 models have their redistributors * powered down at reset. */ return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) || ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) || - ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_CLAYTON)); + ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700)); } #endif /* GICV3_SUPPORT_GIC600 */ @@ -172,3 +173,60 @@ void gicv3_rdistif_on(unsigned int proc_num) } #endif } + +#if GIC600_ERRATA_WA_2384374 +/******************************************************************************* + * Apply part 2 of workaround for errata-2384374 as per SDEN: + * https://developer.arm.com/documentation/sden892601/latest/ + ******************************************************************************/ +void gicv3_apply_errata_wa_2384374(uintptr_t gicr_base) +{ + if (gic600_errata_wa_2384374) { + uint32_t gicr_ctlr_val = gicr_read_ctlr(gicr_base); + + gicr_write_ctlr(gicr_base, gicr_ctlr_val | + (GICR_CTLR_DPG0_BIT | GICR_CTLR_DPG1NS_BIT | + GICR_CTLR_DPG1S_BIT)); + gicr_write_ctlr(gicr_base, gicr_ctlr_val & + ~(GICR_CTLR_DPG0_BIT | GICR_CTLR_DPG1NS_BIT | + GICR_CTLR_DPG1S_BIT)); + } +} +#endif /* GIC600_ERRATA_WA_2384374 */ + +void gicv3_check_erratas_applies(uintptr_t gicd_base) +{ + unsigned int gic_prod_id; + uint8_t gic_rev; + + assert(gicd_base != 0UL); + + gicv3_get_component_prodid_rev(gicd_base, &gic_prod_id, &gic_rev); + + /* + * This workaround applicable only to GIC600 and GIC600AE products with + * revision less than r1p6 and r0p2 respectively. + * As per GIC600/GIC600AE specification - + * r1p6 = 0x17 => GICD_IIDR[19:12] + * r0p2 = 0x04 => GICD_IIDR[19:12] + */ + if ((gic_prod_id == GIC_PRODUCT_ID_GIC600) || + (gic_prod_id == GIC_PRODUCT_ID_GIC600AE)) { + if (((gic_prod_id == GIC_PRODUCT_ID_GIC600) && + (gic_rev <= GIC_REV(GIC_VARIANT_R1, GIC_REV_P6))) || + ((gic_prod_id == GIC_PRODUCT_ID_GIC600AE) && + (gic_rev <= GIC_REV(GIC_VARIANT_R0, GIC_REV_P2)))) { +#if GIC600_ERRATA_WA_2384374 + gic600_errata_wa_2384374 = true; + VERBOSE("%s applies\n", + "GIC600/GIC600AE errata workaround 2384374"); +#else + WARN("%s missing\n", + "GIC600/GIC600AE errata workaround 2384374"); +#endif /* GIC600_ERRATA_WA_2384374 */ + } else { + VERBOSE("%s not applies\n", + "GIC600/GIC600AE errata workaround 2384374"); + } + } +} |