diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:01:01 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:01:01 +0000 |
commit | bda097d8fc4ca1ac3d6b28ba00a493cbb089502d (patch) | |
tree | 2ce8a4e341ac9f98fb265347777487eda74eba48 /drivers/arm | |
parent | 9fd1e09b2de3798cc1a98af3bddd5c5436a85091 (diff) | |
parent | 138668cae2394deb5d695c70fe4aa9760c4458ee (diff) | |
download | arm-trusted-firmware-bda097d8fc4ca1ac3d6b28ba00a493cbb089502d.tar.gz |
Snap for 10453563 from 138668cae2394deb5d695c70fe4aa9760c4458ee to mainline-permission-releaseaml_per_341711000aml_per_341614000aml_per_341510010aml_per_341410020aml_per_341311000aml_per_341110020aml_per_341110010aml_per_341011100aml_per_341011020aml_per_340916010android14-mainline-permission-release
Change-Id: I4fca2def31d0e2c8d0f47b9877765e00815f92da
Diffstat (limited to 'drivers/arm')
-rw-r--r-- | drivers/arm/css/scp/css_pm_scmi.c | 2 | ||||
-rw-r--r-- | drivers/arm/ethosn/ethosn_smc.c | 58 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gic-x00.c | 10 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gic600_multichip.c | 26 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gic600_multichip_private.h | 26 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gic600ae_fmu.c | 244 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gic600ae_fmu_helpers.c | 260 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gicv3.mk | 11 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gicv3_helpers.c | 26 | ||||
-rw-r--r-- | drivers/arm/gic/v3/gicv3_main.c | 10 | ||||
-rw-r--r-- | drivers/arm/tzc/tzc400.c | 28 | ||||
-rw-r--r-- | drivers/arm/tzc/tzc_common_private.h | 23 |
12 files changed, 652 insertions, 72 deletions
diff --git a/drivers/arm/css/scp/css_pm_scmi.c b/drivers/arm/css/scp/css_pm_scmi.c index aeb7eda30..5de2604cb 100644 --- a/drivers/arm/css/scp/css_pm_scmi.c +++ b/drivers/arm/css/scp/css_pm_scmi.c @@ -357,7 +357,7 @@ void __init plat_arm_pwrc_setup(void) unsigned int composite_id, idx; for (idx = 0; idx < PLAT_ARM_SCMI_CHANNEL_COUNT; idx++) { - INFO("Initializing driver on Channel %d\n", idx); + INFO("Initializing SCMI driver on channel %d\n", idx); scmi_channels[idx].info = plat_css_get_scmi_info(idx); scmi_channels[idx].lock = ARM_SCMI_LOCK_GET_INSTANCE; diff --git a/drivers/arm/ethosn/ethosn_smc.c b/drivers/arm/ethosn/ethosn_smc.c index 299d07c02..60364cdb2 100644 --- a/drivers/arm/ethosn/ethosn_smc.c +++ b/drivers/arm/ethosn/ethosn_smc.c @@ -14,11 +14,10 @@ #include <lib/mmio.h> #include <plat/arm/common/fconf_ethosn_getter.h> -/* Arm Ethos-N NPU (NPU) status */ -#define ETHOSN_STATUS \ - FCONF_GET_PROPERTY(hw_config, ethosn_config, status) - -/* Number of NPU cores available */ +/* + * Number of Arm Ethos-N NPU (NPU) cores available for a + * particular parent device + */ #define ETHOSN_NUM_CORES \ FCONF_GET_PROPERTY(hw_config, ethosn_config, num_cores) @@ -51,6 +50,17 @@ #define SEC_SYSCTRL0_SOFT_RESET U(3U << 29) #define SEC_SYSCTRL0_HARD_RESET U(1U << 31) +static bool ethosn_is_core_addr_valid(uintptr_t core_addr) +{ + for (uint32_t core_idx = 0U; core_idx < ETHOSN_NUM_CORES; core_idx++) { + if (ETHOSN_CORE_ADDR(core_idx) == core_addr) { + return true; + } + } + + return false; +} + static void ethosn_delegate_to_ns(uintptr_t core_addr) { mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG), @@ -66,9 +76,9 @@ static void ethosn_delegate_to_ns(uintptr_t core_addr) SEC_DEL_ADDR_EXT_VAL); } -static int ethosn_is_sec(void) +static int ethosn_is_sec(uintptr_t core_addr) { - if ((mmio_read_32(ETHOSN_CORE_SEC_REG(ETHOSN_CORE_ADDR(0), SEC_DEL_REG)) + if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG)) & SEC_DEL_EXCC_MASK) != 0U) { return 0; } @@ -101,7 +111,7 @@ static bool ethosn_reset(uintptr_t core_addr, int hard_reset) } uintptr_t ethosn_smc_handler(uint32_t smc_fid, - u_register_t core_idx, + u_register_t core_addr, u_register_t x2, u_register_t x3, u_register_t x4, @@ -109,8 +119,8 @@ uintptr_t ethosn_smc_handler(uint32_t smc_fid, void *handle, u_register_t flags) { - uintptr_t core_addr; int hard_reset = 0; + const uint32_t fid = smc_fid & FUNCID_NUM_MASK; /* Only SiP fast calls are expected */ if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || @@ -120,7 +130,7 @@ uintptr_t ethosn_smc_handler(uint32_t smc_fid, /* Truncate parameters to 32-bits for SMC32 */ if (GET_SMC_CC(smc_fid) == SMC_32) { - core_idx &= 0xFFFFFFFF; + core_addr &= 0xFFFFFFFF; x2 &= 0xFFFFFFFF; x3 &= 0xFFFFFFFF; x4 &= 0xFFFFFFFF; @@ -130,33 +140,29 @@ uintptr_t ethosn_smc_handler(uint32_t smc_fid, SMC_RET1(handle, SMC_UNK); } - if (ETHOSN_STATUS == ETHOSN_STATUS_DISABLED) { - WARN("ETHOSN: Arm Ethos-N NPU not available\n"); - SMC_RET1(handle, ETHOSN_NOT_SUPPORTED); - } - - switch (smc_fid & FUNCID_NUM_MASK) { + /* Commands that do not require a valid core address */ + switch (fid) { case ETHOSN_FNUM_VERSION: SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR); + } + + if (!ethosn_is_core_addr_valid(core_addr)) { + WARN("ETHOSN: Unknown core address given to SMC call.\n"); + SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS); + } + + /* Commands that require a valid addr */ + switch (fid) { case ETHOSN_FNUM_IS_SEC: - SMC_RET1(handle, ethosn_is_sec()); + SMC_RET1(handle, ethosn_is_sec(core_addr)); case ETHOSN_FNUM_HARD_RESET: hard_reset = 1; /* Fallthrough */ case ETHOSN_FNUM_SOFT_RESET: - if (core_idx >= ETHOSN_NUM_CORES) { - WARN("ETHOSN: core index out of range\n"); - SMC_RET1(handle, ETHOSN_CORE_IDX_OUT_OF_RANGE); - } - - core_addr = ETHOSN_CORE_ADDR(core_idx); - if (!ethosn_reset(core_addr, hard_reset)) { SMC_RET1(handle, ETHOSN_FAILURE); } - ethosn_delegate_to_ns(core_addr); - SMC_RET1(handle, ETHOSN_SUCCESS); default: SMC_RET1(handle, SMC_UNK); diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c index 6e106babf..aaef485ff 100644 --- a/drivers/arm/gic/v3/gic-x00.c +++ b/drivers/arm/gic/v3/gic-x00.c @@ -16,15 +16,13 @@ #include <assert.h> #include <arch_helpers.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 @@ -46,7 +44,7 @@ #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 +121,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 */ diff --git a/drivers/arm/gic/v3/gic600_multichip.c b/drivers/arm/gic/v3/gic600_multichip.c index ca7c43bf9..5f42ad994 100644 --- a/drivers/arm/gic/v3/gic600_multichip.c +++ b/drivers/arm/gic/v3/gic600_multichip.c @@ -11,14 +11,13 @@ #include <assert.h> #include <common/debug.h> +#include <drivers/arm/arm_gicv3_common.h> #include <drivers/arm/gic600_multichip.h> #include <drivers/arm/gicv3.h> #include "../common/gic_common_private.h" #include "gic600_multichip_private.h" -#warning "GIC-600 Multichip driver is currently experimental and the API may change in future." - /******************************************************************************* * GIC-600 multichip operation related helper functions ******************************************************************************/ @@ -73,6 +72,7 @@ static void set_gicd_chipr_n(uintptr_t base, unsigned int spi_id_max) { unsigned int spi_block_min, spi_blocks; + unsigned int gicd_iidr_val = gicd_read_iidr(base); uint64_t chipr_n_val; /* @@ -100,8 +100,24 @@ static void set_gicd_chipr_n(uintptr_t base, spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min); spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max); - chipr_n_val = (GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks)) | - GICD_CHIPRx_SOCKET_STATE; + switch ((gicd_iidr_val & IIDR_MODEL_MASK)) { + case IIDR_MODEL_ARM_GIC_600: + chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr, + spi_block_min, + spi_blocks); + break; + case IIDR_MODEL_ARM_GIC_700: + chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr, + spi_block_min, + spi_blocks); + break; + default: + ERROR("Unsupported GIC model 0x%x for multichip setup.\n", + gicd_iidr_val); + panic(); + break; + } + chipr_n_val |= GICD_CHIPRx_SOCKET_STATE; /* * Wait for DCHIPR.PUP to be zero before commencing writes to @@ -194,8 +210,6 @@ void gic600_multichip_init(struct gic600_multichip_data *multichip_data) gic600_multichip_validate_data(multichip_data); - INFO("GIC-600 Multichip driver is experimental\n"); - /* * Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures * that GIC-600 Multichip configuration is done first. diff --git a/drivers/arm/gic/v3/gic600_multichip_private.h b/drivers/arm/gic/v3/gic600_multichip_private.h index fe4134cba..5d1ff6a19 100644 --- a/drivers/arm/gic/v3/gic600_multichip_private.h +++ b/drivers/arm/gic/v3/gic600_multichip_private.h @@ -27,17 +27,11 @@ #define GICD_CHIPSR_RTS_SHIFT 4 #define GICD_DCHIPR_RT_OWNER_SHIFT 4 -/* - * If GIC v4 extension is enabled, then use SPI macros specific to GIC-Clayton. - * Other shifts and mask remains same between GIC-600 and GIC-Clayton. - */ -#if GIC_ENABLE_V4_EXTN -#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT 9 -#define GICD_CHIPRx_SPI_BLOCKS_SHIFT 3 -#else -#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT 10 -#define GICD_CHIPRx_SPI_BLOCKS_SHIFT 5 -#endif +/* Other shifts and masks remain the same between GIC-600 and GIC-700. */ +#define GIC_700_SPI_BLOCK_MIN_SHIFT 9 +#define GIC_700_SPI_BLOCKS_SHIFT 3 +#define GIC_600_SPI_BLOCK_MIN_SHIFT 10 +#define GIC_600_SPI_BLOCKS_SHIFT 5 #define GICD_CHIPSR_RTS_STATE_DISCONNECTED U(0) #define GICD_CHIPSR_RTS_STATE_UPDATING U(1) @@ -59,10 +53,14 @@ #define SPI_BLOCKS_VALUE(spi_id_min, spi_id_max) \ (((spi_id_max) - (spi_id_min) + 1) / \ GIC600_SPI_ID_MIN) -#define GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks) \ +#define GICD_CHIPR_VALUE_GIC_700(chip_addr, spi_block_min, spi_blocks) \ + (((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \ + ((spi_block_min) << GIC_700_SPI_BLOCK_MIN_SHIFT) | \ + ((spi_blocks) << GIC_700_SPI_BLOCKS_SHIFT)) +#define GICD_CHIPR_VALUE_GIC_600(chip_addr, spi_block_min, spi_blocks) \ (((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \ - ((spi_block_min) << GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT) | \ - ((spi_blocks) << GICD_CHIPRx_SPI_BLOCKS_SHIFT)) + ((spi_block_min) << GIC_600_SPI_BLOCK_MIN_SHIFT) | \ + ((spi_blocks) << GIC_600_SPI_BLOCKS_SHIFT)) /* * Multichip data assertion macros diff --git a/drivers/arm/gic/v3/gic600ae_fmu.c b/drivers/arm/gic/v3/gic600ae_fmu.c new file mode 100644 index 000000000..13979fa4d --- /dev/null +++ b/drivers/arm/gic/v3/gic600ae_fmu.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Driver for GIC-600AE Fault Management Unit + */ + +#include <assert.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/gic600ae_fmu.h> +#include <drivers/arm/gicv3.h> + +/* GIC-600 AE FMU specific register offsets */ + +/* GIC-600 AE FMU specific macros */ +#define FMU_ERRIDR_NUM U(44) +#define FMU_ERRIDR_NUM_MASK U(0xFFFF) + +/* Safety mechanisms for GICD block */ +static char *gicd_sm_info[] = { + "Reserved", + "GICD dual lockstep error", + "GICD AXI4 slave interface error", + "GICD-PPI AXI4-Stream interface error", + "GICD-ITS AXI4-Stream interface error", + "GICD-SPI-Collator AXI4-Stream interface error", + "GICD AXI4 master interface error", + "SPI RAM DED error", + "SGI RAM DED error", + "Reserved", + "LPI RAM DED error", + "GICD-remote-GICD AXI4-Stream interface error", + "GICD Q-Channel interface error", + "GICD P-Channel interface error", + "SPI RAM address decode error", + "SGI RAM address decode error", + "Reserved", + "LPI RAM address decode error", + "FMU dual lockstep error", + "FMU ping ACK error", + "FMU APB parity error", + "GICD-Wake AXI4-Stream interface error", + "GICD PageOffset or Chip ID error", + "MBIST REQ error", + "SPI RAM SEC error", + "SGI RAM SEC error", + "Reserved", + "LPI RAM SEC error", + "User custom SM0 error", + "User custom SM1 error", + "GICD-ITS Monolithic switch error", + "GICD-ITS Q-Channel interface error", + "GICD-ITS Monolithic interface error", + "GICD FMU ClkGate override" +}; + +/* Safety mechanisms for PPI block */ +static char *ppi_sm_info[] = { + "Reserved", + "PPI dual lockstep error", + "PPI-GICD AXI4-Stream interface error", + "PPI-CPU-IF AXI4-Stream interface error", + "PPI Q-Channel interface error", + "PPI RAM DED error", + "PPI RAM address decode error", + "PPI RAM SEC error", + "PPI User0 SM", + "PPI User1 SM", + "MBIST REQ error", + "PPI interrupt parity protection error", + "PPI FMU ClkGate override" +}; + +/* Safety mechanisms for ITS block */ +static char *its_sm_info[] = { + "Reserved", + "ITS dual lockstep error", + "ITS-GICD AXI4-Stream interface error", + "ITS AXI4 slave interface error", + "ITS AXI4 master interface error", + "ITS Q-Channel interface error", + "ITS RAM DED error", + "ITS RAM address decode error", + "Bypass ACE switch error", + "ITS RAM SEC error", + "ITS User0 SM", + "ITS User1 SM", + "ITS-GICD Monolithic interface error", + "MBIST REQ error", + "ITS FMU ClkGate override" +}; + +/* Safety mechanisms for SPI Collator block */ +static char *spicol_sm_info[] = { + "Reserved", + "SPI Collator dual lockstep error", + "SPI-Collator-GICD AXI4-Stream interface error", + "SPI Collator Q-Channel interface error", + "SPI Collator Q-Channel clock error", + "SPI interrupt parity error" +}; + +/* Safety mechanisms for Wake Request block */ +static char *wkrqst_sm_info[] = { + "Reserved", + "Wake dual lockstep error", + "Wake-GICD AXI4-Stream interface error" +}; + +/* + * Initialization sequence for the FMU + * + * 1. enable error detection for error records that are passed in the blk_present_mask + * 2. enable MBIST REQ and FMU Clk Gate override safety mechanisms for error records + * that are present on the platform + * + * The platforms are expected to pass `errctlr_ce_en` and `errctlr_ue_en`. + */ +void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, + bool errctlr_ce_en, bool errctlr_ue_en) +{ + unsigned int num_blk = gic_fmu_read_erridr(base) & FMU_ERRIDR_NUM_MASK; + uint64_t errctlr; + uint32_t smen; + + INFO("GIC600-AE FMU supports %d error records\n", num_blk); + + assert(num_blk == FMU_ERRIDR_NUM); + + /* sanitize block present mask */ + blk_present_mask &= FMU_BLK_PRESENT_MASK; + + /* Enable error detection for all error records */ + for (unsigned int i = 0U; i < num_blk; i++) { + + /* Skip next steps if the block is not present */ + if ((blk_present_mask & BIT(i)) == 0U) { + continue; + } + + /* Read the error record control register */ + errctlr = gic_fmu_read_errctlr(base, i); + + /* Enable error reporting and logging, if it is disabled */ + if ((errctlr & FMU_ERRCTLR_ED_BIT) == 0U) { + errctlr |= FMU_ERRCTLR_ED_BIT; + } + + /* Enable client provided ERRCTLR settings */ + errctlr |= (errctlr_ce_en ? (FMU_ERRCTLR_CI_BIT | FMU_ERRCTLR_CE_EN_BIT) : 0); + errctlr |= (errctlr_ue_en ? FMU_ERRCTLR_UI_BIT : 0U); + + gic_fmu_write_errctlr(base, i, errctlr); + } + + /* + * Enable MBIST REQ error and FMU CLK gate override safety mechanisms for + * all blocks + * + * GICD, SMID 23 and SMID 33 + * PPI, SMID 10 and SMID 12 + * ITS, SMID 13 and SMID 14 + */ + if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) { + smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | + (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT); + gic_fmu_write_smen(base, smen); + + smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | + (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT); + gic_fmu_write_smen(base, smen); + } + + for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) { + if ((blk_present_mask & BIT(i)) != 0U) { + smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT); + gic_fmu_write_smen(base, smen); + + smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT); + gic_fmu_write_smen(base, smen); + } + } + + for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) { + if ((blk_present_mask & BIT(i)) != 0U) { + smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT); + gic_fmu_write_smen(base, smen); + + smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT); + gic_fmu_write_smen(base, smen); + } + } +} + +/* + * This function enable the GICD background ping engine. The GICD sends ping + * messages to each remote GIC block, and expects a PING_ACK back within the + * specified timeout. Pings need to be enabled after programming the timeout + * value. + */ +void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask, + unsigned int timeout_val, unsigned int interval_diff) +{ + /* + * Populate the PING Mask to skip a specific block while generating + * background ping messages and enable the ping mechanism. + */ + gic_fmu_write_pingmask(base, ~blk_present_mask); + gic_fmu_write_pingctlr(base, (interval_diff << FMU_PINGCTLR_INTDIFF_SHIFT) | + (timeout_val << FMU_PINGCTLR_TIMEOUTVAL_SHIFT) | FMU_PINGCTLR_EN_BIT); +} + +/* Print the safety mechanism description for a given block */ +void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid) +{ + if (blk == FMU_BLK_GICD && smid <= FMU_SMID_GICD_MAX) { + INFO("GICD, SMID %d: %s\n", smid, gicd_sm_info[smid]); + } + + if (blk == FMU_BLK_SPICOL && smid <= FMU_SMID_SPICOL_MAX) { + INFO("SPI Collator, SMID %d: %s\n", smid, spicol_sm_info[smid]); + } + + if (blk == FMU_BLK_WAKERQ && (smid <= FMU_SMID_WAKERQ_MAX)) { + INFO("Wake Request, SMID %d: %s\n", smid, wkrqst_sm_info[smid]); + } + + if (((blk >= FMU_BLK_ITS0) && (blk <= FMU_BLK_ITS7)) && (smid <= FMU_SMID_ITS_MAX)) { + INFO("ITS, SMID %d: %s\n", smid, its_sm_info[smid]); + } + + if (((blk >= FMU_BLK_PPI0) && (blk <= FMU_BLK_PPI31)) && (smid <= FMU_SMID_PPI_MAX)) { + INFO("PPI, SMID %d: %s\n", smid, ppi_sm_info[smid]); + } +} diff --git a/drivers/arm/gic/v3/gic600ae_fmu_helpers.c b/drivers/arm/gic/v3/gic600ae_fmu_helpers.c new file mode 100644 index 000000000..4aa0efb32 --- /dev/null +++ b/drivers/arm/gic/v3/gic600ae_fmu_helpers.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <arch.h> +#include <arch_helpers.h> +#include <drivers/arm/gic600ae_fmu.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> + +#define GICFMU_IDLE_TIMEOUT_US U(2000000) + +/* Macro to write 32-bit FMU registers */ +#define GIC_FMU_WRITE_32(base, reg, val) \ + do { \ + /* \ + * This register receives the unlock key that is required for \ + * writes to FMU registers to be successful. \ + */ \ + mmio_write_32(base + GICFMU_KEY, 0xBE); \ + /* Perform the actual write */ \ + mmio_write_32((base) + (reg), (val)); \ + } while (false) + +/* Macro to write 64-bit FMU registers */ +#define GIC_FMU_WRITE_64(base, reg, n, val) \ + do { \ + /* \ + * This register receives the unlock key that is required for \ + * writes to FMU registers to be successful. \ + */ \ + mmio_write_32(base + GICFMU_KEY, 0xBE); \ + /* \ + * APB bus is 32-bit wide; so split the 64-bit write into \ + * two 32-bit writes \ + */ \ + mmio_write_32((base) + reg##_LO + (n * 64), (val)); \ + mmio_write_32((base) + reg##_HI + (n * 64), (val)); \ + } while (false) + +/* Helper function to wait until FMU is ready to accept the next command */ +static void wait_until_fmu_is_idle(uintptr_t base) +{ + uint32_t timeout_count = GICFMU_IDLE_TIMEOUT_US; + uint64_t status; + + /* wait until status is 'busy' */ + do { + status = (gic_fmu_read_status(base) & BIT(0)); + + if (timeout_count-- == 0U) { + ERROR("GIC600 AE FMU is not responding\n"); + panic(); + } + + udelay(1U); + + } while (status == U(0)); +} + +#define GIC_FMU_WRITE_ON_IDLE_32(base, reg, val) \ + do { \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + /* Actual register write */ \ + GIC_FMU_WRITE_32(base, reg, val); \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + } while (false) + +#define GIC_FMU_WRITE_ON_IDLE_64(base, reg, n, val) \ + do { \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + /* Actual register write */ \ + GIC_FMU_WRITE_64(base, reg, n, val); \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + } while (false) + +/******************************************************************************* + * GIC FMU functions for accessing the Fault Management Unit registers + ******************************************************************************/ + +/* + * Accessors to read the Error Record Feature Register bits corresponding + * to an error record 'n' + */ +uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRFR_LO + n * 64U); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRFR_HI + n * 64U) << 32); + return reg_val; +} + +/* + * Accessors to read the Error Record Control Register bits corresponding + * to an error record 'n' + */ +uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_LO + n * 64U); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_HI + n * 64U) << 32); + return reg_val; +} + +/* + * Accessors to read the Error Record Primary Status Register bits + * corresponding to an error record 'n' + */ +uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_LO + n * 64U); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_HI + n * 64U) << 32); + return reg_val; +} + +/* + * Accessors to read the Error Group Status Register + */ +uint64_t gic_fmu_read_errgsr(uintptr_t base) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRGSR_LO); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRGSR_HI) << 32); + return reg_val; +} + +/* + * Accessors to read the Ping Control Register + */ +uint32_t gic_fmu_read_pingctlr(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_PINGCTLR); +} + +/* + * Accessors to read the Ping Now Register + */ +uint32_t gic_fmu_read_pingnow(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_PINGNOW); +} + +/* + * Accessors to read the Ping Mask Register + */ +uint64_t gic_fmu_read_pingmask(uintptr_t base) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_PINGMASK_LO); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_PINGMASK_HI) << 32); + return reg_val; +} + +/* + * Accessors to read the FMU Status Register + */ +uint32_t gic_fmu_read_status(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_STATUS); +} + +/* + * Accessors to read the Error Record ID Register + */ +uint32_t gic_fmu_read_erridr(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_ERRIDR); +} + +/* + * Accessors to write a 64 bit value to the Error Record Control Register + */ +void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val) +{ + GIC_FMU_WRITE_64(base, GICFMU_ERRCTLR, n, val); +} + +/* + * Accessors to write a 64 bit value to the Error Record Primary Status + * Register + */ +void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_64(base, GICFMU_ERRSTATUS, n, val); +} + +/* + * Accessors to write a 32 bit value to the Ping Control Register + */ +void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val) +{ + GIC_FMU_WRITE_32(base, GICFMU_PINGCTLR, val); +} + +/* + * Accessors to write a 32 bit value to the Ping Now Register + */ +void gic_fmu_write_pingnow(uintptr_t base, uint32_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_PINGNOW, val); +} + +/* + * Accessors to write a 32 bit value to the Safety Mechanism Enable Register + */ +void gic_fmu_write_smen(uintptr_t base, uint32_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMEN, val); +} + +/* + * Accessors to write a 32 bit value to the Safety Mechanism Inject Error + * Register + */ +void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMINJERR, val); +} + +/* + * Accessors to write a 64 bit value to the Ping Mask Register + */ +void gic_fmu_write_pingmask(uintptr_t base, uint64_t val) +{ + GIC_FMU_WRITE_64(base, GICFMU_PINGMASK, 0, val); +} diff --git a/drivers/arm/gic/v3/gicv3.mk b/drivers/arm/gic/v3/gicv3.mk index a2fc16f9c..d7e3536db 100644 --- a/drivers/arm/gic/v3/gicv3.mk +++ b/drivers/arm/gic/v3/gicv3.mk @@ -1,11 +1,13 @@ # # Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2021, NVIDIA Corporation. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # # Default configuration values GICV3_SUPPORT_GIC600 ?= 0 +GICV3_SUPPORT_GIC600AE_FMU ?= 0 GICV3_IMPL_GIC600_MULTICHIP ?= 0 GICV3_OVERRIDE_DISTIF_PWR_OPS ?= 0 GIC_ENABLE_V4_EXTN ?= 0 @@ -16,6 +18,11 @@ GICV3_SOURCES += drivers/arm/gic/v3/gicv3_main.c \ drivers/arm/gic/v3/gicdv3_helpers.c \ drivers/arm/gic/v3/gicrv3_helpers.c +ifeq (${GICV3_SUPPORT_GIC600AE_FMU}, 1) +GICV3_SOURCES += drivers/arm/gic/v3/gic600ae_fmu.c \ + drivers/arm/gic/v3/gic600ae_fmu_helpers.c +endif + ifeq (${GICV3_OVERRIDE_DISTIF_PWR_OPS}, 0) GICV3_SOURCES += drivers/arm/gic/v3/arm_gicv3_common.c endif @@ -29,6 +36,10 @@ endif $(eval $(call assert_boolean,GICV3_SUPPORT_GIC600)) $(eval $(call add_define,GICV3_SUPPORT_GIC600)) +# Set GIC-600AE FMU support +$(eval $(call assert_boolean,GICV3_SUPPORT_GIC600AE_FMU)) +$(eval $(call add_define,GICV3_SUPPORT_GIC600AE_FMU)) + # Set GICv4 extension $(eval $(call assert_boolean,GIC_ENABLE_V4_EXTN)) $(eval $(call add_define,GIC_ENABLE_V4_EXTN)) diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c index a0f44e966..753d995d7 100644 --- a/drivers/arm/gic/v3/gicv3_helpers.c +++ b/drivers/arm/gic/v3/gicv3_helpers.c @@ -86,8 +86,7 @@ void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs, if (proc_num < rdistif_num) { rdistif_base_addrs[proc_num] = rdistif_base; } - - rdistif_base += (1U << GICR_PCPUBASE_SHIFT); + rdistif_base += gicv3_redist_size(typer_val); } while ((typer_val & TYPER_LAST_BIT) == 0U); } @@ -383,12 +382,29 @@ unsigned int gicv3_rdistif_get_number_frames(const uintptr_t gicr_frame) uintptr_t rdistif_base = gicr_frame; unsigned int count; - for (count = 1; count < PLATFORM_CORE_COUNT; count++) { - if ((gicr_read_typer(rdistif_base) & TYPER_LAST_BIT) != 0U) { + for (count = 1U; count < PLATFORM_CORE_COUNT; count++) { + uint64_t typer_val = gicr_read_typer(rdistif_base); + + if ((typer_val & TYPER_LAST_BIT) != 0U) { break; } - rdistif_base += (1U << GICR_PCPUBASE_SHIFT); + rdistif_base += gicv3_redist_size(typer_val); } return count; } + +unsigned int gicv3_get_component_partnum(const uintptr_t gic_frame) +{ + unsigned int part_id; + + /* + * The lower 8 bits of PIDR0, complemented by the lower 4 bits of + * PIDR1 contain a part number identifying the GIC component at a + * particular base address. + */ + part_id = mmio_read_32(gic_frame + GICD_PIDR0_GICV3) & 0xff; + part_id |= (mmio_read_32(gic_frame + GICD_PIDR1_GICV3) << 8) & 0xf00; + + return part_id; +} diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c index b1139b5e9..53a8fae3b 100644 --- a/drivers/arm/gic/v3/gicv3_main.c +++ b/drivers/arm/gic/v3/gicv3_main.c @@ -123,13 +123,7 @@ void __init gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data) gic_version &= PIDR2_ARCH_REV_MASK; /* Check GIC version */ -#if GIC_ENABLE_V4_EXTN - assert(gic_version == ARCH_REV_GICV4); - - /* GICv4 supports Direct Virtual LPI injection */ - assert((gicd_read_typer(plat_driver_data->gicd_base) - & TYPER_DVIS) != 0); -#else +#if !GIC_ENABLE_V4_EXTN assert(gic_version == ARCH_REV_GICV3); #endif /* @@ -1298,7 +1292,7 @@ int gicv3_rdistif_probe(const uintptr_t gicr_frame) gicr_frame_found = true; break; } - rdistif_base += (uintptr_t)(ULL(1) << GICR_PCPUBASE_SHIFT); + rdistif_base += gicv3_redist_size(typer_val); } while ((typer_val & TYPER_LAST_BIT) == 0U); if (!gicr_frame_found) { diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c index 9fc1578a1..e4fc8c927 100644 --- a/drivers/arm/tzc/tzc400.c +++ b/drivers/arm/tzc/tzc400.c @@ -68,6 +68,7 @@ DEFINE_TZC_COMMON_WRITE_REGION_BASE(400, 400) DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400) DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400) DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400) +DEFINE_TZC_COMMON_UPDATE_FILTERS(400, 400) DEFINE_TZC_COMMON_CONFIGURE_REGION0(400) DEFINE_TZC_COMMON_CONFIGURE_REGION(400) @@ -271,6 +272,15 @@ void tzc400_configure_region(unsigned int filters, sec_attr, nsaid_permissions); } +void tzc400_update_filters(unsigned int region, unsigned int filters) +{ + /* Do range checks on filters and regions. */ + assert(((filters >> tzc400.num_filters) == 0U) && + (region < tzc400.num_regions)); + + _tzc400_update_filters(tzc400.base, region, tzc400.num_filters, filters); +} + void tzc400_enable_filters(void) { unsigned int state; @@ -281,6 +291,11 @@ void tzc400_enable_filters(void) for (filter = 0U; filter < tzc400.num_filters; filter++) { state = _tzc400_get_gate_keeper(tzc400.base, filter); if (state != 0U) { + /* Filter 0 is special and cannot be disabled. + * So here we allow it being already enabled. */ + if (filter == 0U) { + continue; + } /* * The TZC filter is already configured. Changing the * programmer's view in an active system can cause @@ -302,14 +317,17 @@ void tzc400_enable_filters(void) void tzc400_disable_filters(void) { unsigned int filter; + unsigned int state; + unsigned int start = 0U; assert(tzc400.base != 0U); - /* - * We don't do the same state check as above as the Gatekeepers are - * disabled after reset. - */ - for (filter = 0; filter < tzc400.num_filters; filter++) + /* Filter 0 is special and cannot be disabled. */ + state = _tzc400_get_gate_keeper(tzc400.base, 0); + if (state != 0U) { + start++; + } + for (filter = start; filter < tzc400.num_filters; filter++) _tzc400_set_gate_keeper(tzc400.base, filter, 0); } diff --git a/drivers/arm/tzc/tzc_common_private.h b/drivers/arm/tzc/tzc_common_private.h index 1d99077ad..2090944a7 100644 --- a/drivers/arm/tzc/tzc_common_private.h +++ b/drivers/arm/tzc/tzc_common_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -90,6 +90,27 @@ } /* + * It is used to modify the filters status for a defined region. + */ +#define DEFINE_TZC_COMMON_UPDATE_FILTERS(fn_name, macro_name) \ + static inline void _tzc##fn_name##_update_filters( \ + uintptr_t base, \ + unsigned int region_no, \ + unsigned int nbfilters, \ + unsigned int filters) \ + { \ + uint32_t filters_mask = GENMASK(nbfilters - 1U, 0); \ + \ + mmio_clrsetbits_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + region_no) + \ + TZC_##macro_name##_REGION_ATTR_0_OFFSET, \ + filters_mask << TZC_REGION_ATTR_F_EN_SHIFT, \ + filters << TZC_REGION_ATTR_F_EN_SHIFT); \ + } + +/* * It is used to program region 0 ATTRIBUTES and ACCESS register. */ #define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name) \ |