diff --git a/drivers/arm/gic/v3/gic600.c b/drivers/arm/gic/v3/gic600.c index 9cb2ab2..59652da 100644 --- a/drivers/arm/gic/v3/gic600.c +++ b/drivers/arm/gic/v3/gic600.c @@ -1,14 +1,14 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ /* - * Driver for GIC600-specific features. This driver only overrides APIs that are - * different to those generic ones in GICv3 driver. + * Driver for GIC-600 specific features. This driver only overrides + * APIs that are different to those generic ones in GICv3 driver. * - * GIC600 supports independently power-gating redistributor interface. + * GIC-600 supports independently power-gating redistributor interface. */ #include @@ -18,22 +18,28 @@ #include "gicv3_private.h" -/* GIC600-specific register offsets */ +/* GIC-600 specific register offsets */ #define GICR_PWRR 0x24 /* GICR_PWRR fields */ #define PWRR_RDPD_SHIFT 0 +#define PWRR_RDAG_SHIFT 1 #define PWRR_RDGPD_SHIFT 2 #define PWRR_RDGPO_SHIFT 3 +#define PWRR_RDPD (1 << PWRR_RDPD_SHIFT) +#define PWRR_RDAG (1 << PWRR_RDAG_SHIFT) #define PWRR_RDGPD (1 << PWRR_RDGPD_SHIFT) #define PWRR_RDGPO (1 << PWRR_RDGPO_SHIFT) -/* Values to write to GICR_PWRR register to power redistributor */ +/* + * Values to write to GICR_PWRR register to power redistributor + * for operating through the core (GICR_PWRR.RDAG = 0) + */ #define PWRR_ON (0 << PWRR_RDPD_SHIFT) #define PWRR_OFF (1 << PWRR_RDPD_SHIFT) -/* GIC600-specific accessor functions */ +/* GIC-600 specific accessor functions */ static void gicr_write_pwrr(uintptr_t base, unsigned int val) { mmio_write_32(base + GICR_PWRR, val); @@ -44,39 +50,46 @@ return mmio_read_32(base + GICR_PWRR); } -static int gicr_group_powering_down(uint32_t pwrr) +static void gicr_wait_group_not_in_transit(uintptr_t base) { - /* - * Whether the redistributor group power down operation is in transit: - * i.e. it's intending to, but not finished yet. - */ - return ((pwrr & PWRR_RDGPD) && !(pwrr & PWRR_RDGPO)); + /* Check group not transitioning: RDGPD == RDGPO */ + while (((gicr_read_pwrr(base) & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) != + ((gicr_read_pwrr(base) & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT)) + ; } static void gic600_pwr_on(uintptr_t base) { - /* Power on redistributor */ - gicr_write_pwrr(base, PWRR_ON); + do { /* Wait until group not transitioning */ + gicr_wait_group_not_in_transit(base); - /* Wait until the power on state is reflected */ - while (gicr_read_pwrr(base) & PWRR_RDGPO) - ; + /* Power on redistributor */ + gicr_write_pwrr(base, PWRR_ON); + + /* + * Wait until the power on state is reflected. + * If RDPD == 0 then powered on. + */ + } while ((gicr_read_pwrr(base) & PWRR_RDPD) != PWRR_ON); } static void gic600_pwr_off(uintptr_t base) { + /* Wait until group not transitioning */ + gicr_wait_group_not_in_transit(base); + /* Power off redistributor */ gicr_write_pwrr(base, PWRR_OFF); /* * If this is the last man, turning this redistributor frame off will - * result in the group itself being powered off. In that case, wait as - * long as it's in transition, or has aborted the transition altogether - * for any reason. + * result in the group itself being powered off and RDGPD = 1. + * In that case, wait as long as it's in transition, or has aborted + * the transition altogether for any reason. */ - if (gicr_read_pwrr(base) & PWRR_RDGPD) { - while (gicr_group_powering_down(gicr_read_pwrr(base))) - ; + if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0) { + /* Wait until group not transitioning */ + gicr_wait_group_not_in_transit(base); } } @@ -91,7 +104,7 @@ } /* - * Power off GIC600 redistributor + * Power off GIC-600 redistributor */ void gicv3_rdistif_off(unsigned int proc_num) { @@ -109,7 +122,7 @@ } /* - * Power on GIC600 redistributor + * Power on GIC-600 redistributor */ void gicv3_rdistif_on(unsigned int proc_num) {