diff options
Diffstat (limited to 'drivers')
49 files changed, 3339 insertions, 548 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) \ diff --git a/drivers/auth/cryptocell/713/cryptocell_crypto.c b/drivers/auth/cryptocell/713/cryptocell_crypto.c index 5f390a226..077317e7b 100644 --- a/drivers/auth/cryptocell/713/cryptocell_crypto.c +++ b/drivers/auth/cryptocell/713/cryptocell_crypto.c @@ -13,6 +13,7 @@ #include <drivers/auth/crypto_mod.h> #include <mbedtls/oid.h> +#include <mbedtls/x509.h> #define LIB_NAME "CryptoCell 713 SBROM" #define RSA_SALT_LEN 32 diff --git a/drivers/auth/tbbr/tbbr_cot_bl1_r64.c b/drivers/auth/tbbr/tbbr_cot_bl1_r64.c new file mode 100644 index 000000000..e8e017c8d --- /dev/null +++ b/drivers/auth/tbbr/tbbr_cot_bl1_r64.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stddef.h> + +#include <drivers/auth/auth_mod.h> +#include <drivers/auth/mbedtls/mbedtls_config.h> +#include <drivers/auth/tbbr_cot_common.h> + +#if USE_TBBR_DEFS +#include <tools_share/tbbr_oid.h> +#else +#include <platform_oid.h> +#endif +#include <platform_def.h> + + +static unsigned char trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char non_trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char content_pk_buf[PK_DER_LEN]; +static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN]; + +static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID); +static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID); +static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID); +/* + * Trusted key certificate + */ +static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &non_trusted_world_pk, + .data = { + .ptr = (void *)non_trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +/* + * Non-Trusted Firmware + */ +static const auth_img_desc_t non_trusted_fw_key_cert = { + .img_id = NON_TRUSTED_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t non_trusted_fw_content_cert = { + .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &non_trusted_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &nt_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_world_bl_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &nt_fw_config_hash, + .data = { + .ptr = (void *)nt_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +static const auth_img_desc_t bl33_image = { + .img_id = BL33_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &non_trusted_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_world_bl_hash + } + } + } +}; + +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_KEY_CERT_ID] = &trusted_key_cert, + [NON_TRUSTED_FW_KEY_CERT_ID] = &non_trusted_fw_key_cert, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert, + [BL33_IMAGE_ID] = &bl33_image, +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/drivers/brcm/emmc/emmc_csl_sdcard.c b/drivers/brcm/emmc/emmc_csl_sdcard.c index d6ad4bc9c..9e2c618d9 100644 --- a/drivers/brcm/emmc/emmc_csl_sdcard.c +++ b/drivers/brcm/emmc/emmc_csl_sdcard.c @@ -4,9 +4,11 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <inttypes.h> +#include <stddef.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> -#include <stddef.h> #include <arch_helpers.h> #include <lib/mmio.h> @@ -521,7 +523,7 @@ static int xfer_data(struct sd_handle *handle, { int rc = SD_OK; - VERBOSE("XFER: dest: 0x%llx, addr: 0x%x, size: 0x%x bytes\n", + VERBOSE("XFER: dest: 0x%" PRIx64 ", addr: 0x%x, size: 0x%x bytes\n", (uint64_t)base, addr, length); if ((length / handle->device->cfg.blockSize) > 1) { diff --git a/drivers/marvell/amb_adec.c b/drivers/marvell/amb_adec.c index 1f671058d..d78fa2517 100644 --- a/drivers/marvell/amb_adec.c +++ b/drivers/marvell/amb_adec.c @@ -7,6 +7,9 @@ /* AXI to M-Bridge decoding unit driver for Marvell Armada 8K and 8K+ SoCs */ +#include <inttypes.h> +#include <stdint.h> + #include <common/debug.h> #include <lib/mmio.h> @@ -44,10 +47,10 @@ static void amb_check_win(struct addr_map_win *win, uint32_t win_num) /* make sure the base address is in 16-bit range */ if (win->base_addr > AMB_BASE_ADDR_MASK) { - WARN("Window %d: base address is too big 0x%llx\n", + WARN("Window %d: base address is too big 0x%" PRIx64 "\n", win_num, win->base_addr); win->base_addr = AMB_BASE_ADDR_MASK; - WARN("Set the base address to 0x%llx\n", win->base_addr); + WARN("Set the base address to 0x%" PRIx64 "\n", win->base_addr); } base_addr = win->base_addr << AMB_BASE_OFFSET; @@ -57,15 +60,15 @@ static void amb_check_win(struct addr_map_win *win, uint32_t win_num) win->base_addr = ALIGN_UP(base_addr, AMB_WIN_ALIGNMENT_1M); WARN("Window %d: base address unaligned to 0x%x\n", win_num, AMB_WIN_ALIGNMENT_1M); - WARN("Align up the base address to 0x%llx\n", win->base_addr); + WARN("Align up the base address to 0x%" PRIx64 "\n", win->base_addr); } /* size parameter validity check */ if (!IS_POWER_OF_2(win->win_size)) { - WARN("Window %d: window size is not power of 2 (0x%llx)\n", + WARN("Window %d: window size is not power of 2 (0x%" PRIx64 ")\n", win_num, win->win_size); win->win_size = ROUND_UP_TO_POW_OF_2(win->win_size); - WARN("Rounding size to 0x%llx\n", win->win_size); + WARN("Rounding size to 0x%" PRIx64 "\n", win->win_size); } } diff --git a/drivers/marvell/ccu.c b/drivers/marvell/ccu.c index b4251f49b..c206f1168 100644 --- a/drivers/marvell/ccu.c +++ b/drivers/marvell/ccu.c @@ -7,6 +7,9 @@ /* CCU unit device driver for Marvell AP807, AP807 and AP810 SoCs */ +#include <inttypes.h> +#include <stdint.h> + #include <common/debug.h> #include <drivers/marvell/ccu.h> #include <lib/mmio.h> @@ -84,7 +87,7 @@ static void dump_ccu(int ap_index) win_id)); start = ((uint64_t)alr << ADDRESS_SHIFT); end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT); - printf("\tccu%d %02x 0x%016llx 0x%016llx\n", + printf("\tccu%d %02x 0x%016" PRIx64 " 0x%016" PRIx64 "\n", win_id, target_id, start, end); } } @@ -99,14 +102,14 @@ void ccu_win_check(struct addr_map_win *win) /* check if address is aligned to 1M */ if (IS_NOT_ALIGN(win->base_addr, CCU_WIN_ALIGNMENT)) { win->base_addr = ALIGN_UP(win->base_addr, CCU_WIN_ALIGNMENT); - NOTICE("%s: Align up the base address to 0x%llx\n", + NOTICE("%s: Align up the base address to 0x%" PRIx64 "\n", __func__, win->base_addr); } /* size parameter validity check */ if (IS_NOT_ALIGN(win->win_size, CCU_WIN_ALIGNMENT)) { win->win_size = ALIGN_UP(win->win_size, CCU_WIN_ALIGNMENT); - NOTICE("%s: Aligning size to 0x%llx\n", + NOTICE("%s: Aligning size to 0x%" PRIx64 "\n", __func__, win->win_size); } } diff --git a/drivers/marvell/comphy/comphy-cp110.h b/drivers/marvell/comphy/comphy-cp110.h index 9b10619ed..af5c71518 100644 --- a/drivers/marvell/comphy/comphy-cp110.h +++ b/drivers/marvell/comphy/comphy-cp110.h @@ -54,7 +54,7 @@ #define COMMON_SELECTOR_PIPE_COMPHY_USBH 0x1 #define COMMON_SELECTOR_PIPE_COMPHY_USBD 0x2 -/* SGMII/HS-SGMII/SFI/RXAUI */ +/* SGMII/Base-X/SFI/RXAUI */ #define COMMON_SELECTOR_COMPHY0_1_2_NETWORK 0x1 #define COMMON_SELECTOR_COMPHY3_RXAUI 0x1 #define COMMON_SELECTOR_COMPHY3_SGMII 0x2 diff --git a/drivers/marvell/comphy/phy-comphy-3700.c b/drivers/marvell/comphy/phy-comphy-3700.c index 7377e5e3d..a3e414c4b 100644 --- a/drivers/marvell/comphy/phy-comphy-3700.c +++ b/drivers/marvell/comphy/phy-comphy-3700.c @@ -118,7 +118,7 @@ static uint16_t sgmii_phy_init[512] = { }; /* PHY selector configures with corresponding modes */ -static void mvebu_a3700_comphy_set_phy_selector(uint8_t comphy_index, +static int mvebu_a3700_comphy_set_phy_selector(uint8_t comphy_index, uint32_t comphy_mode) { uint32_t reg; @@ -135,7 +135,7 @@ static void mvebu_a3700_comphy_set_phy_selector(uint8_t comphy_index, break; case (COMPHY_SGMII_MODE): - case (COMPHY_HS_SGMII_MODE): + case (COMPHY_2500BASEX_MODE): if (comphy_index == COMPHY_LANE0) reg &= ~COMPHY_SELECTOR_USB3_GBE1_SEL_BIT; else if (comphy_index == COMPHY_LANE1) @@ -168,9 +168,10 @@ static void mvebu_a3700_comphy_set_phy_selector(uint8_t comphy_index, } mmio_write_32(MVEBU_COMPHY_REG_BASE + COMPHY_SELECTOR_PHY_REG, reg); - return; + return 0; error: ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index, mode); + return -EINVAL; } /* @@ -183,7 +184,7 @@ error: * with COMPHY_USB3D_MODE or COMPHY_USB3H_MODE. (The usb3 phy initialization * code does not differentiate between these modes.) * Also it returns COMPHY_SGMII_MODE even if the phy was configures with - * COMPHY_HS_SGMII_MODE. (The sgmii phy initialization code does differentiate + * COMPHY_2500BASEX_MODE. (The sgmii phy initialization code does differentiate * between these modes, but it is irrelevant when powering the phy off.) */ static int mvebu_a3700_comphy_get_mode(uint8_t comphy_index) @@ -214,7 +215,7 @@ static int mvebu_a3700_comphy_get_mode(uint8_t comphy_index) /* It is only used for SATA and USB3 on comphy lane2. */ static void comphy_set_indirect(uintptr_t addr, uint32_t offset, uint16_t data, - uint16_t mask, int mode) + uint16_t mask, bool is_sata) { /* * When Lane 2 PHY is for USB3, access the PHY registers @@ -224,27 +225,38 @@ static void comphy_set_indirect(uintptr_t addr, uint32_t offset, uint16_t data, * within the SATA Host Controller registers, Lane 2 base register * offset is 0x200 */ - if (mode == COMPHY_UNUSED) - return; - - if (mode == COMPHY_SATA_MODE) + if (is_sata) { mmio_write_32(addr + COMPHY_LANE2_INDIR_ADDR_OFFSET, offset); - else + } else { mmio_write_32(addr + COMPHY_LANE2_INDIR_ADDR_OFFSET, offset + USB3PHY_LANE2_REG_BASE_OFFSET); + } reg_set(addr + COMPHY_LANE2_INDIR_DATA_OFFSET, data, mask); } -/* It is only used USB3 direct access not on comphy lane2. */ +/* It is only used for SATA on comphy lane2. */ +static void comphy_sata_set_indirect(uintptr_t addr, uint32_t reg_offset, + uint16_t data, uint16_t mask) +{ + comphy_set_indirect(addr, reg_offset, data, mask, true); +} + +/* It is only used for USB3 indirect access on comphy lane2. */ +static void comphy_usb3_set_indirect(uintptr_t addr, uint32_t reg_offset, + uint16_t data, uint16_t mask) +{ + comphy_set_indirect(addr, reg_offset, data, mask, false); +} + +/* It is only used for USB3 direct access not on comphy lane2. */ static void comphy_usb3_set_direct(uintptr_t addr, uint32_t reg_offset, - uint16_t data, uint16_t mask, int mode) + uint16_t data, uint16_t mask) { reg_set16((reg_offset * PHY_SHFT(USB3) + addr), data, mask); } -static void comphy_sgmii_phy_init(uint32_t comphy_index, uint32_t mode, - uintptr_t sd_ip_addr) +static void comphy_sgmii_phy_init(uintptr_t sd_ip_addr, bool is_1gbps) { const int fix_arr_sz = ARRAY_SIZE(sgmii_phy_init_fix); int addr, fix_idx; @@ -259,8 +271,7 @@ static void comphy_sgmii_phy_init(uint32_t comphy_index, uint32_t mode, * comparison to 3.125 Gbps values. These register values are * stored in "sgmii_phy_init_fix" array. */ - if ((mode != COMPHY_SGMII_MODE) && - (sgmii_phy_init_fix[fix_idx].addr == addr)) { + if (!is_1gbps && sgmii_phy_init_fix[fix_idx].addr == addr) { /* Use new value */ val = sgmii_phy_init_fix[fix_idx].value; if (fix_idx < fix_arr_sz) @@ -276,21 +287,22 @@ static void comphy_sgmii_phy_init(uint32_t comphy_index, uint32_t mode, static int mvebu_a3700_comphy_sata_power_on(uint8_t comphy_index, uint32_t comphy_mode) { - int ret = 0; + int ret; uint32_t offset, data = 0, ref_clk; uintptr_t comphy_indir_regs = COMPHY_INDIRECT_REG; - int mode = COMPHY_GET_MODE(comphy_mode); int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode); debug_enter(); /* Configure phy selector for SATA */ - mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } /* Clear phy isolation mode to make it work in normal mode */ offset = COMPHY_ISOLATION_CTRL_REG + SATAPHY_LANE2_REG_BASE_OFFSET; - comphy_set_indirect(comphy_indir_regs, offset, 0, PHY_ISOLATE_MODE, - mode); + comphy_sata_set_indirect(comphy_indir_regs, offset, 0, PHY_ISOLATE_MODE); /* 0. Check the Polarity invert bits */ if (invert & COMPHY_POLARITY_TXD_INVERT) @@ -299,13 +311,13 @@ static int mvebu_a3700_comphy_sata_power_on(uint8_t comphy_index, data |= RXD_INVERT_BIT; offset = COMPHY_SYNC_PATTERN_REG + SATAPHY_LANE2_REG_BASE_OFFSET; - comphy_set_indirect(comphy_indir_regs, offset, data, TXD_INVERT_BIT | - RXD_INVERT_BIT, mode); + comphy_sata_set_indirect(comphy_indir_regs, offset, data, TXD_INVERT_BIT | + RXD_INVERT_BIT); /* 1. Select 40-bit data width width */ offset = COMPHY_LOOPBACK_REG0 + SATAPHY_LANE2_REG_BASE_OFFSET; - comphy_set_indirect(comphy_indir_regs, offset, DATA_WIDTH_40BIT, - SEL_DATA_WIDTH_MASK, mode); + comphy_sata_set_indirect(comphy_indir_regs, offset, DATA_WIDTH_40BIT, + SEL_DATA_WIDTH_MASK); /* 2. Select reference clock(25M) and PHY mode (SATA) */ offset = COMPHY_POWER_PLL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; @@ -314,17 +326,17 @@ static int mvebu_a3700_comphy_sata_power_on(uint8_t comphy_index, else ref_clk = REF_CLOCK_SPEED_25M; - comphy_set_indirect(comphy_indir_regs, offset, ref_clk | PHY_MODE_SATA, - REF_FREF_SEL_MASK | PHY_MODE_MASK, mode); + comphy_sata_set_indirect(comphy_indir_regs, offset, ref_clk | PHY_MODE_SATA, + REF_FREF_SEL_MASK | PHY_MODE_MASK); /* 3. Use maximum PLL rate (no power save) */ offset = COMPHY_KVCO_CAL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; - comphy_set_indirect(comphy_indir_regs, offset, USE_MAX_PLL_RATE_BIT, - USE_MAX_PLL_RATE_BIT, mode); + comphy_sata_set_indirect(comphy_indir_regs, offset, USE_MAX_PLL_RATE_BIT, + USE_MAX_PLL_RATE_BIT); /* 4. Reset reserved bit */ - comphy_set_indirect(comphy_indir_regs, COMPHY_RESERVED_REG, 0, - PHYCTRL_FRM_PIN_BIT, mode); + comphy_sata_set_indirect(comphy_indir_regs, COMPHY_RESERVED_REG, 0, + PHYCTRL_FRM_PIN_BIT); /* 5. Set vendor-specific configuration (It is done in sata driver) */ /* XXX: in U-Boot below sequence was executed in this place, in Linux @@ -346,17 +358,21 @@ static int mvebu_a3700_comphy_sata_power_on(uint8_t comphy_index, COMPHY_LANE2_INDIR_DATA_OFFSET, PLL_READY_TX_BIT, PLL_READY_TX_BIT, COMPHY_PLL_TIMEOUT, REG_32BIT); + if (ret) { + return -ETIMEDOUT; + } debug_exit(); - return ret; + return 0; } static int mvebu_a3700_comphy_sgmii_power_on(uint8_t comphy_index, uint32_t comphy_mode) { - int ret = 0; - uint32_t mask, data, offset; + int ret; + uint32_t mask, data; + uintptr_t offset; uintptr_t sd_ip_addr; int mode = COMPHY_GET_MODE(comphy_mode); int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode); @@ -364,7 +380,10 @@ static int mvebu_a3700_comphy_sgmii_power_on(uint8_t comphy_index, debug_enter(); /* Set selector */ - mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } /* Serdes IP Base address * COMPHY Lane0 -- USB3/GBE1 @@ -401,8 +420,8 @@ static int mvebu_a3700_comphy_sgmii_power_on(uint8_t comphy_index, /* SGMII 1G, SerDes speed 1.25G */ data |= SD_SPEED_1_25_G << GEN_RX_SEL_OFFSET; data |= SD_SPEED_1_25_G << GEN_TX_SEL_OFFSET; - } else if (mode == COMPHY_HS_SGMII_MODE) { - /* HS SGMII (2.5G), SerDes speed 3.125G */ + } else if (mode == COMPHY_2500BASEX_MODE) { + /* 2500Base-X, SerDes speed 3.125G */ data |= SD_SPEED_2_5_G << GEN_RX_SEL_OFFSET; data |= SD_SPEED_2_5_G << GEN_TX_SEL_OFFSET; } else { @@ -479,9 +498,9 @@ static int mvebu_a3700_comphy_sgmii_power_on(uint8_t comphy_index, * 25 MHz the default values stored in PHY registers are OK. */ debug("Running C-DPI phy init %s mode\n", - mode == COMPHY_HS_SGMII_MODE ? "2G5" : "1G"); + mode == COMPHY_2500BASEX_MODE ? "2G5" : "1G"); if (get_ref_clk() == 40) - comphy_sgmii_phy_init(comphy_index, mode, sd_ip_addr); + comphy_sgmii_phy_init(sd_ip_addr, mode != COMPHY_2500BASEX_MODE); /* * 14. [Simulation Only] should not be used for real chip. @@ -525,8 +544,10 @@ static int mvebu_a3700_comphy_sgmii_power_on(uint8_t comphy_index, PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, COMPHY_PLL_TIMEOUT, REG_32BIT); - if (ret) + if (ret) { ERROR("Failed to lock PLL for SGMII PHY %d\n", comphy_index); + return -ETIMEDOUT; + } /* * 19. Set COMPHY input port PIN_TX_IDLE=0 @@ -549,26 +570,29 @@ static int mvebu_a3700_comphy_sgmii_power_on(uint8_t comphy_index, PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, COMPHY_PLL_TIMEOUT, REG_32BIT); - if (ret) + if (ret) { ERROR("Failed to lock PLL for SGMII PHY %d\n", comphy_index); - + return -ETIMEDOUT; + } ret = polling_with_timeout(MVEBU_COMPHY_REG_BASE + COMPHY_PHY_STATUS_OFFSET(comphy_index), PHY_RX_INIT_DONE_BIT, PHY_RX_INIT_DONE_BIT, COMPHY_PLL_TIMEOUT, REG_32BIT); - if (ret) + if (ret) { ERROR("Failed to init RX of SGMII PHY %d\n", comphy_index); + return -ETIMEDOUT; + } debug_exit(); - return ret; + return 0; } static int mvebu_a3700_comphy_sgmii_power_off(uint8_t comphy_index) { - int ret = 0; - uint32_t mask, data, offset; + uintptr_t offset; + uint32_t mask, data; debug_enter(); @@ -579,28 +603,31 @@ static int mvebu_a3700_comphy_sgmii_power_off(uint8_t comphy_index) debug_exit(); - return ret; + return 0; } static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index, uint32_t comphy_mode) { - int ret = 0; + int ret; uintptr_t reg_base = 0; - uint32_t mask, data, addr, cfg, ref_clk; + uintptr_t addr; + uint32_t mask, data, cfg, ref_clk; void (*usb3_reg_set)(uintptr_t addr, uint32_t reg_offset, uint16_t data, - uint16_t mask, int mode); - int mode = COMPHY_GET_MODE(comphy_mode); + uint16_t mask); int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode); debug_enter(); /* Set phy seclector */ - mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } /* Set usb3 reg access func, Lane2 is indirect access */ if (comphy_index == COMPHY_LANE2) { - usb3_reg_set = &comphy_set_indirect; + usb3_reg_set = &comphy_usb3_set_indirect; reg_base = COMPHY_INDIRECT_REG; } else { /* Get the direct access register resource and map */ @@ -619,7 +646,7 @@ static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index, mask = PRD_TXDEEMPH0_MASK | PRD_TXMARGIN_MASK | PRD_TXSWING_MASK | CFG_TX_ALIGN_POS_MASK; usb3_reg_set(reg_base, COMPHY_REG_LANE_CFG0_ADDR, PRD_TXDEEMPH0_MASK, - mask, mode); + mask); /* * 2. Set BIT0: enable transmitter in high impedance mode @@ -631,20 +658,20 @@ static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index, mask = PRD_TXDEEMPH1_MASK | TX_DET_RX_MODE | GEN2_TX_DATA_DLY_MASK | TX_ELEC_IDLE_MODE_EN; data = TX_DET_RX_MODE | GEN2_TX_DATA_DLY_DEFT | TX_ELEC_IDLE_MODE_EN; - usb3_reg_set(reg_base, COMPHY_REG_LANE_CFG1_ADDR, data, mask, mode); + usb3_reg_set(reg_base, COMPHY_REG_LANE_CFG1_ADDR, data, mask); /* * 3. Set Spread Spectrum Clock Enabled */ usb3_reg_set(reg_base, COMPHY_REG_LANE_CFG4_ADDR, - SPREAD_SPECTRUM_CLK_EN, SPREAD_SPECTRUM_CLK_EN, mode); + SPREAD_SPECTRUM_CLK_EN, SPREAD_SPECTRUM_CLK_EN); /* * 4. Set Override Margining Controls From the MAC: * Use margining signals from lane configuration */ usb3_reg_set(reg_base, COMPHY_REG_TEST_MODE_CTRL_ADDR, - MODE_MARGIN_OVERRIDE, REG_16_BIT_MASK, mode); + MODE_MARGIN_OVERRIDE, REG_16_BIT_MASK); /* * 5. Set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles @@ -652,13 +679,13 @@ static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index, */ usb3_reg_set(reg_base, COMPHY_REG_GLOB_CLK_SRC_LO_ADDR, 0x0, (MODE_CLK_SRC | BUNDLE_PERIOD_SEL | BUNDLE_PERIOD_SCALE | - BUNDLE_SAMPLE_CTRL | PLL_READY_DLY), mode); + BUNDLE_SAMPLE_CTRL | PLL_READY_DLY)); /* * 6. Set G2 Spread Spectrum Clock Amplitude at 4K */ usb3_reg_set(reg_base, COMPHY_REG_GEN2_SET_2, - G2_TX_SSC_AMP_VALUE_20, G2_TX_SSC_AMP_MASK, mode); + G2_TX_SSC_AMP_VALUE_20, G2_TX_SSC_AMP_MASK); /* * 7. Unset G3 Spread Spectrum Clock Amplitude @@ -667,7 +694,7 @@ static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index, mask = G3_TX_SSC_AMP_MASK | G3_VREG_RXTX_MAS_ISET_MASK | RSVD_PH03FH_6_0_MASK; usb3_reg_set(reg_base, COMPHY_REG_GEN2_SET_3, - G3_VREG_RXTX_MAS_ISET_60U, mask, mode); + G3_VREG_RXTX_MAS_ISET_60U, mask); /* * 8. Check crystal jumper setting and program the Power and PLL Control @@ -688,39 +715,37 @@ static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index, REF_FREF_SEL_MASK; data = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | PU_TX_INTP_BIT | PU_DFE_BIT | PHY_MODE_USB3 | ref_clk; - usb3_reg_set(reg_base, COMPHY_POWER_PLL_CTRL, data, mask, mode); + usb3_reg_set(reg_base, COMPHY_POWER_PLL_CTRL, data, mask); mask = CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK | CFG_PM_RXDLOZ_WAIT_MASK; data = CFG_PM_RXDEN_WAIT_1_UNIT | cfg; - usb3_reg_set(reg_base, COMPHY_REG_PWR_MGM_TIM1_ADDR, data, mask, mode); + usb3_reg_set(reg_base, COMPHY_REG_PWR_MGM_TIM1_ADDR, data, mask); /* * 9. Enable idle sync */ data = UNIT_CTRL_DEFAULT_VALUE | IDLE_SYNC_EN; - usb3_reg_set(reg_base, COMPHY_REG_UNIT_CTRL_ADDR, data, REG_16_BIT_MASK, - mode); + usb3_reg_set(reg_base, COMPHY_REG_UNIT_CTRL_ADDR, data, REG_16_BIT_MASK); /* * 10. Enable the output of 500M clock */ data = MISC_REG0_DEFAULT_VALUE | CLK500M_EN; - usb3_reg_set(reg_base, COMPHY_MISC_REG0_ADDR, data, REG_16_BIT_MASK, - mode); + usb3_reg_set(reg_base, COMPHY_MISC_REG0_ADDR, data, REG_16_BIT_MASK); /* * 11. Set 20-bit data width */ usb3_reg_set(reg_base, COMPHY_LOOPBACK_REG0, DATA_WIDTH_20BIT, - REG_16_BIT_MASK, mode); + REG_16_BIT_MASK); /* * 12. Override Speed_PLL value and use MAC PLL */ usb3_reg_set(reg_base, COMPHY_KVCO_CAL_CTRL, (SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT), - REG_16_BIT_MASK, mode); + REG_16_BIT_MASK); /* * 13. Check the Polarity invert bit @@ -733,27 +758,26 @@ static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index, data |= RXD_INVERT_BIT; } mask = TXD_INVERT_BIT | RXD_INVERT_BIT; - usb3_reg_set(reg_base, COMPHY_SYNC_PATTERN_REG, data, mask, mode); + usb3_reg_set(reg_base, COMPHY_SYNC_PATTERN_REG, data, mask); /* * 14. Set max speed generation to USB3.0 5Gbps */ usb3_reg_set(reg_base, COMPHY_SYNC_MASK_GEN_REG, PHY_GEN_USB3_5G, - PHY_GEN_MAX_MASK, mode); + PHY_GEN_MAX_MASK); /* * 15. Set capacitor value for FFE gain peaking to 0xF */ usb3_reg_set(reg_base, COMPHY_REG_GEN3_SETTINGS_3, - COMPHY_GEN_FFE_CAP_SEL_VALUE, COMPHY_GEN_FFE_CAP_SEL_MASK, - mode); + COMPHY_GEN_FFE_CAP_SEL_VALUE, COMPHY_GEN_FFE_CAP_SEL_MASK); /* * 16. Release SW reset */ data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32 | MODE_REFDIV_BY_4; usb3_reg_set(reg_base, COMPHY_REG_GLOB_PHY_CTRL0_ADDR, data, - REG_16_BIT_MASK, mode); + REG_16_BIT_MASK); /* Wait for > 55 us to allow PCLK be enabled */ udelay(PLL_SET_DELAY_US); @@ -771,12 +795,14 @@ static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index, TXDCLK_PCLK_EN, TXDCLK_PCLK_EN, COMPHY_PLL_TIMEOUT, REG_16BIT); } - if (ret) + if (ret) { ERROR("Failed to lock USB3 PLL\n"); + return -ETIMEDOUT; + } debug_exit(); - return ret; + return 0; } static int mvebu_a3700_comphy_pcie_power_on(uint8_t comphy_index, @@ -789,6 +815,12 @@ static int mvebu_a3700_comphy_pcie_power_on(uint8_t comphy_index, debug_enter(); + /* Configure phy selector for PCIe */ + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } + /* 1. Enable max PLL. */ reg_set16(LANE_CFG1_ADDR(PCIE) + COMPHY_SD_ADDR, USE_MAX_PLL_RATE_EN, USE_MAX_PLL_RATE_EN); @@ -862,12 +894,14 @@ static int mvebu_a3700_comphy_pcie_power_on(uint8_t comphy_index, ret = polling_with_timeout(LANE_STATUS1_ADDR(PCIE) + COMPHY_SD_ADDR, TXDCLK_PCLK_EN, TXDCLK_PCLK_EN, COMPHY_PLL_TIMEOUT, REG_16BIT); - if (ret) + if (ret) { ERROR("Failed to lock PCIE PLL\n"); + return -ETIMEDOUT; + } debug_exit(); - return ret; + return 0; } int mvebu_3700_comphy_power_on(uint8_t comphy_index, uint32_t comphy_mode) @@ -883,7 +917,7 @@ int mvebu_3700_comphy_power_on(uint8_t comphy_index, uint32_t comphy_mode) comphy_mode); break; case(COMPHY_SGMII_MODE): - case(COMPHY_HS_SGMII_MODE): + case(COMPHY_2500BASEX_MODE): ret = mvebu_a3700_comphy_sgmii_power_on(comphy_index, comphy_mode); break; @@ -919,23 +953,22 @@ static int mvebu_a3700_comphy_usb3_power_off(void) return 0; } -static int mvebu_a3700_comphy_sata_power_off(uint32_t comphy_mode) +static int mvebu_a3700_comphy_sata_power_off(void) { uintptr_t comphy_indir_regs = COMPHY_INDIRECT_REG; - int mode = COMPHY_GET_MODE(comphy_mode); uint32_t offset; debug_enter(); /* Set phy isolation mode */ offset = COMPHY_ISOLATION_CTRL_REG + SATAPHY_LANE2_REG_BASE_OFFSET; - comphy_set_indirect(comphy_indir_regs, offset, PHY_ISOLATE_MODE, - PHY_ISOLATE_MODE, mode); + comphy_sata_set_indirect(comphy_indir_regs, offset, PHY_ISOLATE_MODE, + PHY_ISOLATE_MODE); /* Power off PLL, Tx, Rx */ offset = COMPHY_POWER_PLL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; - comphy_set_indirect(comphy_indir_regs, offset, 0, - PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT, mode); + comphy_sata_set_indirect(comphy_indir_regs, offset, 0, + PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT); debug_exit(); @@ -960,7 +993,7 @@ int mvebu_3700_comphy_power_off(uint8_t comphy_index, uint32_t comphy_mode) switch (mode) { case(COMPHY_SGMII_MODE): - case(COMPHY_HS_SGMII_MODE): + case(COMPHY_2500BASEX_MODE): err = mvebu_a3700_comphy_sgmii_power_off(comphy_index); break; case (COMPHY_USB3_MODE): @@ -968,7 +1001,7 @@ int mvebu_3700_comphy_power_off(uint8_t comphy_index, uint32_t comphy_mode) err = mvebu_a3700_comphy_usb3_power_off(); break; case (COMPHY_SATA_MODE): - err = mvebu_a3700_comphy_sata_power_off(comphy_mode); + err = mvebu_a3700_comphy_sata_power_off(); break; default: diff --git a/drivers/marvell/comphy/phy-comphy-common.h b/drivers/marvell/comphy/phy-comphy-common.h index e3b430a91..c599437a3 100644 --- a/drivers/marvell/comphy/phy-comphy-common.h +++ b/drivers/marvell/comphy/phy-comphy-common.h @@ -87,7 +87,7 @@ #define COMPHY_SATA_MODE 0x1 #define COMPHY_SGMII_MODE 0x2 /* SGMII 1G */ -#define COMPHY_HS_SGMII_MODE 0x3 /* SGMII 2.5G */ +#define COMPHY_2500BASEX_MODE 0x3 /* 2500Base-X */ #define COMPHY_USB3H_MODE 0x4 #define COMPHY_USB3D_MODE 0x5 #define COMPHY_PCIE_MODE 0x6 diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c index 86f4c77c5..fa9fe4100 100644 --- a/drivers/marvell/comphy/phy-comphy-cp110.c +++ b/drivers/marvell/comphy/phy-comphy-cp110.c @@ -8,6 +8,8 @@ /* Marvell CP110 SoC COMPHY unit driver */ #include <errno.h> +#include <inttypes.h> +#include <stdint.h> #include <common/debug.h> #include <drivers/delay_timer.h> @@ -30,7 +32,7 @@ /* COMPHY speed macro */ #define COMPHY_SPEED_1_25G 0 /* SGMII 1G */ #define COMPHY_SPEED_2_5G 1 -#define COMPHY_SPEED_3_125G 2 /* SGMII 2.5G */ +#define COMPHY_SPEED_3_125G 2 /* 2500Base-X */ #define COMPHY_SPEED_5G 3 #define COMPHY_SPEED_5_15625G 4 /* XFI 5G */ #define COMPHY_SPEED_6G 5 @@ -102,7 +104,7 @@ static void mvebu_cp110_get_ap_and_cp_nr(uint8_t *ap_nr, uint8_t *cp_nr, *cp_nr = (((comphy_base & ~0xffffff) - MVEBU_AP_IO_BASE(*ap_nr)) / MVEBU_CP_OFFSET); - debug("cp_base 0x%llx, ap_io_base 0x%lx, cp_offset 0x%lx\n", + debug("cp_base 0x%" PRIx64 ", ap_io_base 0x%lx, cp_offset 0x%lx\n", comphy_base, (unsigned long)MVEBU_AP_IO_BASE(*ap_nr), (unsigned long)MVEBU_CP_OFFSET); } @@ -191,7 +193,7 @@ static void mvebu_cp110_comphy_set_phy_selector(uint64_t comphy_base, case(3): /* For comphy 3: * 0x1 = RXAUI_Lane1 - * 0x2 = SGMII/HS-SGMII Port1 + * 0x2 = SGMII/Base-X Port1 */ if (mode == COMPHY_RXAUI_MODE) reg |= COMMON_SELECTOR_COMPHY3_RXAUI << @@ -202,20 +204,20 @@ static void mvebu_cp110_comphy_set_phy_selector(uint64_t comphy_base, break; case(4): /* For comphy 4: - * 0x1 = SGMII/HS-SGMII Port1, XFI1/SFI1 - * 0x2 = SGMII/HS-SGMII Port0: XFI0/SFI0, RXAUI_Lane0 + * 0x1 = SGMII/Base-X Port1, XFI1/SFI1 + * 0x2 = SGMII/Base-X Port0: XFI0/SFI0, RXAUI_Lane0 * - * We want to check if SGMII1/HS_SGMII1 is the + * We want to check if SGMII1 is the * requested mode in order to determine which value * should be set (all other modes use the same value) * so we need to strip the mode, and check the ID - * because we might handle SGMII0/HS_SGMII0 too. + * because we might handle SGMII0 too. */ /* TODO: need to distinguish between CP110 and CP115 * as SFI1/XFI1 available only for CP115. */ if ((mode == COMPHY_SGMII_MODE || - mode == COMPHY_HS_SGMII_MODE || + mode == COMPHY_2500BASEX_MODE || mode == COMPHY_SFI_MODE || mode == COMPHY_XFI_MODE || mode == COMPHY_AP_MODE) @@ -228,7 +230,7 @@ static void mvebu_cp110_comphy_set_phy_selector(uint64_t comphy_base, break; case(5): /* For comphy 5: - * 0x1 = SGMII/HS-SGMII Port2 + * 0x1 = SGMII/Base-X Port2 * 0x2 = RXAUI Lane1 */ if (mode == COMPHY_RXAUI_MODE) @@ -713,7 +715,7 @@ static int mvebu_cp110_comphy_sgmii_power_on(uint64_t comphy_base, data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; } else if (sgmii_speed == COMPHY_SPEED_3_125G) { - /* HS SGMII (2.5G), SerDes speed 3.125G */ + /* 2500Base-X, SerDes speed 3.125G */ data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; } else { @@ -1730,11 +1732,13 @@ static int mvebu_cp110_comphy_pcie_power_on(uint64_t comphy_base, HPIPE_LANE_STATUS1_REG; data = HPIPE_LANE_STATUS1_PCLK_EN_MASK; mask = data; - ret = polling_with_timeout(addr, data, mask, + data = polling_with_timeout(addr, data, mask, PLL_LOCK_TIMEOUT, REG_32BIT); - if (ret) + if (data) { ERROR("Failed to lock PCIE PLL\n"); + ret = -ETIMEDOUT; + } } } @@ -2343,7 +2347,7 @@ int mvebu_cp110_comphy_digital_reset(uint64_t comphy_base, switch (mode) { case (COMPHY_SGMII_MODE): - case (COMPHY_HS_SGMII_MODE): + case (COMPHY_2500BASEX_MODE): case (COMPHY_XFI_MODE): case (COMPHY_SFI_MODE): case (COMPHY_RXAUI_MODE): @@ -2378,7 +2382,7 @@ int mvebu_cp110_comphy_power_on(uint64_t comphy_base, comphy_mode); break; case(COMPHY_SGMII_MODE): - case(COMPHY_HS_SGMII_MODE): + case(COMPHY_2500BASEX_MODE): err = mvebu_cp110_comphy_sgmii_power_on(comphy_base, comphy_index, comphy_mode); diff --git a/drivers/marvell/gwin.c b/drivers/marvell/gwin.c index 9d9430836..fa59cb033 100644 --- a/drivers/marvell/gwin.c +++ b/drivers/marvell/gwin.c @@ -7,6 +7,9 @@ /* GWIN unit device driver for Marvell AP810 SoC */ +#include <inttypes.h> +#include <stdint.h> + #include <common/debug.h> #include <drivers/marvell/gwin.h> #include <lib/mmio.h> @@ -49,14 +52,14 @@ static void gwin_check(struct addr_map_win *win) /* The base is always 64M aligned */ if (IS_NOT_ALIGN(win->base_addr, GWIN_ALIGNMENT_64M)) { win->base_addr &= ~(GWIN_ALIGNMENT_64M - 1); - NOTICE("%s: Align the base address to 0x%llx\n", + NOTICE("%s: Align the base address to 0x%" PRIx64 "\n", __func__, win->base_addr); } /* size parameter validity check */ if (IS_NOT_ALIGN(win->win_size, GWIN_ALIGNMENT_64M)) { win->win_size = ALIGN_UP(win->win_size, GWIN_ALIGNMENT_64M); - NOTICE("%s: Aligning window size to 0x%llx\n", + NOTICE("%s: Aligning window size to 0x%" PRIx64 "\n", __func__, win->win_size); } } @@ -167,7 +170,7 @@ static void dump_gwin(int ap_index) alr = (alr >> ADDRESS_LSHIFT) << ADDRESS_RSHIFT; ahr = mmio_read_32(GWIN_AHR_OFFSET(ap_index, win_num)); ahr = (ahr >> ADDRESS_LSHIFT) << ADDRESS_RSHIFT; - printf("\tgwin %d 0x%016llx 0x%016llx\n", + printf("\tgwin %d 0x%016" PRIx64 " 0x%016" PRIx64 "\n", (cr >> 8) & 0xF, alr, ahr); } } diff --git a/drivers/marvell/io_win.c b/drivers/marvell/io_win.c index c4257fa7c..124382ad9 100644 --- a/drivers/marvell/io_win.c +++ b/drivers/marvell/io_win.c @@ -7,6 +7,9 @@ /* IO Window unit device driver for Marvell AP807, AP807 and AP810 SoCs */ +#include <inttypes.h> +#include <stdint.h> + #include <common/debug.h> #include <drivers/marvell/io_win.h> #include <lib/mmio.h> @@ -44,14 +47,14 @@ static void io_win_check(struct addr_map_win *win) /* check if address is aligned to 1M */ if (IS_NOT_ALIGN(win->base_addr, IO_WIN_ALIGNMENT_1M)) { win->base_addr = ALIGN_UP(win->base_addr, IO_WIN_ALIGNMENT_1M); - NOTICE("%s: Align up the base address to 0x%llx\n", + NOTICE("%s: Align up the base address to 0x%" PRIx64 "\n", __func__, win->base_addr); } /* size parameter validity check */ if (IS_NOT_ALIGN(win->win_size, IO_WIN_ALIGNMENT_1M)) { win->win_size = ALIGN_UP(win->win_size, IO_WIN_ALIGNMENT_1M); - NOTICE("%s: Aligning size to 0x%llx\n", + NOTICE("%s: Aligning size to 0x%" PRIx64 "\n", __func__, win->win_size); } } @@ -170,7 +173,7 @@ static void dump_io_win(int ap_index) win_id)); start = ((uint64_t)alr << ADDRESS_SHIFT); end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT); - printf("\tio-win %d 0x%016llx 0x%016llx\n", + printf("\tio-win %d 0x%016" PRIx64 " 0x%016" PRIx64 "\n", trgt_id, start, end); } } diff --git a/drivers/marvell/iob.c b/drivers/marvell/iob.c index 29088aa92..1f3939560 100644 --- a/drivers/marvell/iob.c +++ b/drivers/marvell/iob.c @@ -7,6 +7,9 @@ /* IOW unit device driver for Marvell CP110 and CP115 SoCs */ +#include <inttypes.h> +#include <stdint.h> + #include <arch_helpers.h> #include <common/debug.h> #include <drivers/marvell/iob.h> @@ -57,7 +60,7 @@ static void iob_win_check(struct addr_map_win *win, uint32_t win_num) win->base_addr = ALIGN_UP(win->base_addr, IOB_WIN_ALIGNMENT); ERROR("Window %d: base address unaligned to 0x%x\n", win_num, IOB_WIN_ALIGNMENT); - printf("Align up the base address to 0x%llx\n", + printf("Align up the base address to 0x%" PRIx64 "\n", win->base_addr); } @@ -66,7 +69,7 @@ static void iob_win_check(struct addr_map_win *win, uint32_t win_num) win->win_size = ALIGN_UP(win->win_size, IOB_WIN_ALIGNMENT); ERROR("Window %d: window size unaligned to 0x%x\n", win_num, IOB_WIN_ALIGNMENT); - printf("Aligning size to 0x%llx\n", win->win_size); + printf("Aligning size to 0x%" PRIx64 "\n", win->win_size); } } @@ -130,7 +133,7 @@ static void dump_iob(void) */ end = start + (16 << 20); } - printf("iob %02d %s 0x%016llx 0x%016llx\n", + printf("iob %02d %s 0x%016" PRIx64 " 0x%016" PRIx64 "\n", win_id, iob_target_name[target_id], start, end); } diff --git a/drivers/marvell/mc_trustzone/mc_trustzone.c b/drivers/marvell/mc_trustzone/mc_trustzone.c index 52b300676..648bd0e98 100644 --- a/drivers/marvell/mc_trustzone/mc_trustzone.c +++ b/drivers/marvell/mc_trustzone/mc_trustzone.c @@ -5,6 +5,9 @@ * https://spdx.org/licenses */ +#include <inttypes.h> +#include <stdint.h> + #include <common/debug.h> #include <drivers/marvell/addr_map.h> #include <lib/mmio.h> @@ -39,7 +42,7 @@ void tz_enable_win(int ap_index, const struct addr_map_win *win, int win_id) /* map the window size to trustzone register convention */ tz_size = fls(TZ_SIZE(win->win_size)); - VERBOSE("%s: window size = 0x%llx maps to tz_size %d\n", + VERBOSE("%s: window size = 0x%" PRIx64 " maps to tz_size %d\n", __func__, win->win_size, tz_size); if (tz_size < 0 || tz_size > 31) { ERROR("Using not allowed size for MC TrustZone window %d!\n", @@ -49,7 +52,7 @@ void tz_enable_win(int ap_index, const struct addr_map_win *win, int win_id) if (base & 0xfff) { base = base & ~0xfff; - WARN("Attempt to open MC TZ win. at 0x%llx, truncate to 0x%x\n", + WARN("Attempt to open MC TZ win. at 0x%" PRIx64 ", truncate to 0x%x\n", win->base_addr, base); } diff --git a/drivers/measured_boot/event_log.c b/drivers/measured_boot/event_log/event_log.c index 0157b0300..1755dd95e 100644 --- a/drivers/measured_boot/event_log.c +++ b/drivers/measured_boot/event_log/event_log.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Arm Limited. All rights reserved. + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,27 +12,19 @@ #include <common/bl_common.h> #include <common/debug.h> #include <drivers/auth/crypto_mod.h> -#include <drivers/measured_boot/event_log.h> +#include <drivers/measured_boot/event_log/event_log.h> #include <mbedtls/md.h> #include <plat/common/platform.h> -/* Event Log data */ -static uint8_t event_log[EVENT_LOG_SIZE]; +/* Running Event Log Pointer */ +static uint8_t *log_ptr; -/* End of Event Log */ -#define EVENT_LOG_END ((uintptr_t)event_log + sizeof(event_log) - 1U) +/* Pointer to the first byte past end of the Event Log buffer */ +static uintptr_t log_end; -CASSERT(sizeof(event_log) >= LOG_MIN_SIZE, assert_event_log_size); - -/* Pointer in event_log[] */ -static uint8_t *log_ptr = event_log; - -/* Pointer to measured_boot_data_t */ -const static measured_boot_data_t *plat_data_ptr; - -static uintptr_t tos_fw_config_base; -static uintptr_t nt_fw_config_base; +/* Pointer to event_log_metadata_t */ +static const event_log_metadata_t *plat_metadata_ptr; /* TCG_EfiSpecIdEvent */ static const id_event_headers_t id_event_header = { @@ -80,26 +72,30 @@ static const event2_header_t locality_event_header = { }; /* - * Add TCG_PCR_EVENT2 event + * Record a measurement as a TCG_PCR_EVENT2 event * - * @param[in] hash Pointer to hash data of TCG_DIGEST_SIZE bytes - * @param[in] image_ptr Pointer to image_data_t structure + * @param[in] hash Pointer to hash data of TCG_DIGEST_SIZE bytes + * @param[in] metadata_ptr Pointer to event_log_metadata_t structure * * There must be room for storing this new event into the event log buffer. */ -static void add_event2(const uint8_t *hash, const image_data_t *image_ptr) +static void event_log_record(const uint8_t *hash, + const event_log_metadata_t *metadata_ptr) { void *ptr = log_ptr; uint32_t name_len; - assert(image_ptr != NULL); - assert(image_ptr->name != NULL); + assert(hash != NULL); + assert(metadata_ptr != NULL); + assert(metadata_ptr->name != NULL); + /* event_log_init() must have been called prior to this. */ + assert(log_ptr != NULL); - name_len = (uint32_t)strlen(image_ptr->name) + 1U; + name_len = (uint32_t)strlen(metadata_ptr->name) + 1U; /* Check for space in Event Log buffer */ - assert(((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) <= - EVENT_LOG_END); + assert(((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) < + log_end); /* * As per TCG specifications, firmware components that are measured @@ -107,7 +103,7 @@ static void add_event2(const uint8_t *hash, const image_data_t *image_ptr) * EV_POST_CODE. */ /* TCG_PCR_EVENT2.PCRIndex */ - ((event2_header_t *)ptr)->pcr_index = image_ptr->pcr; + ((event2_header_t *)ptr)->pcr_index = metadata_ptr->pcr; /* TCG_PCR_EVENT2.EventType */ ((event2_header_t *)ptr)->event_type = EV_POST_CODE; @@ -126,13 +122,8 @@ static void add_event2(const uint8_t *hash, const image_data_t *image_ptr) /* TCG_PCR_EVENT2.Digests[].Digest[] */ ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest)); - if (hash == NULL) { - /* Get BL2 hash from DTB */ - bl2_plat_get_hash(ptr); - } else { - /* Copy digest */ - (void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE); - } + /* Copy digest */ + (void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE); /* TCG_PCR_EVENT2.EventSize */ ptr = (uint8_t *)((uintptr_t)ptr + TCG_DIGEST_SIZE); @@ -140,7 +131,7 @@ static void add_event2(const uint8_t *hash, const image_data_t *image_ptr) /* Copy event data to TCG_PCR_EVENT2.Event */ (void)memcpy((void *)(((event2_data_t *)ptr)->event), - (const void *)image_ptr->name, name_len); + (const void *)metadata_ptr->name, name_len); /* End of event data */ log_ptr = (uint8_t *)((uintptr_t)ptr + @@ -148,18 +139,38 @@ static void add_event2(const uint8_t *hash, const image_data_t *image_ptr) } /* - * Init Event Log + * Initialise Event Log global variables, used during the recording + * of various payload measurements into the Event Log buffer * + * @param[in] event_log_start Base address of Event Log buffer + * @param[in] event_log_finish End address of Event Log buffer, + * it is a first byte past end of the + * buffer + */ +void event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish) +{ + assert(event_log_start != NULL); + assert(event_log_finish > event_log_start); + + log_ptr = event_log_start; + log_end = (uintptr_t)event_log_finish; + + /* Get pointer to platform's event_log_metadata_t structure */ + plat_metadata_ptr = plat_event_log_get_metadata(); + assert(plat_metadata_ptr != NULL); +} + +/* * Initialises Event Log by writing Specification ID and - * Startup Locality events. + * Startup Locality events */ -void event_log_init(void) +void event_log_write_header(void) { const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE; - void *ptr = event_log; + void *ptr = log_ptr; - /* Get pointer to platform's measured_boot_data_t structure */ - plat_data_ptr = plat_get_measured_boot_data(); + /* event_log_init() must have been called prior to this. */ + assert(log_ptr != NULL); /* * Add Specification ID Event first @@ -217,12 +228,7 @@ void event_log_init(void) * the platform's boot firmware */ ((startup_locality_event_t *)ptr)->startup_locality = 0U; - ptr = (uint8_t *)((uintptr_t)ptr + sizeof(startup_locality_event_t)); - - log_ptr = (uint8_t *)ptr; - - /* Add BL2 event */ - add_event2(NULL, plat_data_ptr->images_data); + log_ptr = (uint8_t *)((uintptr_t)ptr + sizeof(startup_locality_event_t)); } /* @@ -236,26 +242,19 @@ void event_log_init(void) * 0 = success * < 0 = error */ -int tpm_record_measurement(uintptr_t data_base, uint32_t data_size, - uint32_t data_id) +int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size, + uint32_t data_id) { - const image_data_t *data_ptr = plat_data_ptr->images_data; unsigned char hash_data[MBEDTLS_MD_MAX_SIZE]; int rc; + const event_log_metadata_t *metadata_ptr = plat_metadata_ptr; /* Get the metadata associated with this image. */ - while ((data_ptr->id != INVALID_ID) && (data_ptr->id != data_id)) { - data_ptr++; - } - assert(data_ptr->id != INVALID_ID); - - if (data_id == TOS_FW_CONFIG_ID) { - tos_fw_config_base = data_base; - } else if (data_id == NT_FW_CONFIG_ID) { - nt_fw_config_base = data_base; - } else { - /* No action */ + while ((metadata_ptr->id != INVALID_ID) && + (metadata_ptr->id != data_id)) { + metadata_ptr++; } + assert(metadata_ptr->id != INVALID_ID); /* Calculate hash */ rc = crypto_mod_calc_hash((unsigned int)MBEDTLS_MD_ID, @@ -264,96 +263,22 @@ int tpm_record_measurement(uintptr_t data_base, uint32_t data_size, return rc; } - add_event2(hash_data, data_ptr); + event_log_record(hash_data, metadata_ptr); + return 0; } /* - * Finalise Event Log + * Get current Event Log buffer size i.e. used space of Event Log buffer * - * @param[out] log_addr Pointer to return Event Log address - * @param[out] log_size Pointer to return Event Log size - * @return: - * 0 = success - * < 0 = error code + * @param[in] event_log_start Base Pointer to Event Log buffer + * + * @return: current Size of Event Log buffer */ -int event_log_finalise(uint8_t **log_addr, size_t *log_size) +size_t event_log_get_cur_size(uint8_t *event_log_start) { - /* Event Log size */ - size_t num_bytes = (uintptr_t)log_ptr - (uintptr_t)event_log; - int rc; - - assert(log_addr != NULL); - assert(log_size != NULL); - - if (nt_fw_config_base == 0UL) { - ERROR("%s(): %s_FW_CONFIG not loaded\n", __func__, "NT"); - return -ENOENT; - } - - /* - * Set Event Log data in NT_FW_CONFIG and - * get Event Log address in Non-Secure memory - */ - if (plat_data_ptr->set_nt_fw_info != NULL) { - - /* Event Log address in Non-Secure memory */ - uintptr_t ns_log_addr; - - rc = plat_data_ptr->set_nt_fw_info( - nt_fw_config_base, -#ifdef SPD_opteed - (uintptr_t)event_log, -#endif - num_bytes, &ns_log_addr); - if (rc != 0) { - ERROR("%s(): Unable to update %s_FW_CONFIG\n", - __func__, "NT"); - return rc; - } - - /* Copy Event Log to Non-secure memory */ - (void)memcpy((void *)ns_log_addr, (const void *)event_log, - num_bytes); - - /* Ensure that the Event Log is visible in Non-secure memory */ - flush_dcache_range(ns_log_addr, num_bytes); - - /* Return Event Log address in Non-Secure memory */ - *log_addr = (uint8_t *)ns_log_addr; - - } else { - INFO("%s(): set_%s_fw_info not set\n", __func__, "nt"); - - /* Return Event Log address in Secure memory */ - *log_addr = event_log; - } - - if (tos_fw_config_base != 0UL) { - if (plat_data_ptr->set_tos_fw_info != NULL) { - - /* Set Event Log data in TOS_FW_CONFIG */ - rc = plat_data_ptr->set_tos_fw_info( - tos_fw_config_base, - (uintptr_t)event_log, - num_bytes); - if (rc != 0) { - ERROR("%s(): Unable to update %s_FW_CONFIG\n", - __func__, "TOS"); - return rc; - } - } else { - INFO("%s(): set_%s_fw_info not set\n", __func__, "tos"); - } - } else { - INFO("%s(): %s_FW_CONFIG not loaded\n", __func__, "TOS"); - } - - /* Ensure that the Event Log is visible in Secure memory */ - flush_dcache_range((uintptr_t)event_log, num_bytes); + assert(event_log_start != NULL); + assert(log_ptr >= event_log_start); - /* Return Event Log size */ - *log_size = num_bytes; - - return 0; + return (size_t)((uintptr_t)log_ptr - (uintptr_t)event_log_start); } diff --git a/drivers/measured_boot/measured_boot.mk b/drivers/measured_boot/event_log/event_log.mk index 497fdbaae..37e5e291d 100644 --- a/drivers/measured_boot/measured_boot.mk +++ b/drivers/measured_boot/event_log/event_log.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Arm Limited. All rights reserved. +# Copyright (c) 2020-2021, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -7,7 +7,8 @@ # Default log level to dump the event log (LOG_LEVEL_INFO) EVENT_LOG_LEVEL ?= 40 -# TPM hash algorithm +# TPM hash algorithm. +# SHA-256 (or stronger) is required for all devices that are TPM 2.0 compliant. TPM_HASH_ALG := sha256 ifeq (${TPM_HASH_ALG}, sha512) @@ -24,8 +25,6 @@ else TCG_DIGEST_SIZE := 32U endif -# Event Log length in bytes -EVENT_LOG_SIZE := 1024 # Set definitions for mbed TLS library and Measured Boot driver $(eval $(call add_defines,\ @@ -33,20 +32,19 @@ $(eval $(call add_defines,\ MBEDTLS_MD_ID \ TPM_ALG_ID \ TCG_DIGEST_SIZE \ - EVENT_LOG_SIZE \ EVENT_LOG_LEVEL \ ))) ifeq (${HASH_ALG}, sha256) -ifneq (${TPM_HASH_ALG}, sha256) -$(eval $(call add_define,MBEDTLS_SHA512_C)) -endif + ifneq (${TPM_HASH_ALG}, sha256) + $(eval $(call add_define,MBEDTLS_SHA512_C)) + endif endif -MEASURED_BOOT_SRC_DIR := drivers/measured_boot/ +MEASURED_BOOT_SRC_DIR := drivers/measured_boot/event_log/ -MEASURED_BOOT_SOURCES := ${MEASURED_BOOT_SRC_DIR}measured_boot.c \ - ${MEASURED_BOOT_SRC_DIR}event_log.c \ - ${MEASURED_BOOT_SRC_DIR}event_print.c +MEASURED_BOOT_SOURCES := ${MEASURED_BOOT_SRC_DIR}event_log.c \ + ${MEASURED_BOOT_SRC_DIR}event_print.c BL2_SOURCES += ${MEASURED_BOOT_SOURCES} +BL1_SOURCES += ${MEASURED_BOOT_SOURCES} diff --git a/drivers/measured_boot/event_print.c b/drivers/measured_boot/event_log/event_print.c index 84ed4b1cb..e2ba1744d 100644 --- a/drivers/measured_boot/event_print.c +++ b/drivers/measured_boot/event_log/event_print.c @@ -8,7 +8,7 @@ #include <string.h> #include <common/debug.h> -#include <drivers/measured_boot/event_log.h> +#include <drivers/measured_boot/event_log/event_log.h> #if LOG_LEVEL >= EVENT_LOG_LEVEL diff --git a/drivers/measured_boot/measured_boot.c b/drivers/measured_boot/measured_boot.c deleted file mode 100644 index 37fddfbdc..000000000 --- a/drivers/measured_boot/measured_boot.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2020, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include <assert.h> - -#include <common/debug.h> -#include <drivers/measured_boot/measured_boot.h> - -/* - * Init Measured Boot driver - * - * Initialises Event Log. - */ -void measured_boot_init(void) -{ - event_log_init(); -} - -/* - * Finish Measured Boot driver - * - * Finalises Event Log and dumps the records to the debug console. - */ -void measured_boot_finish(void) -{ - uint8_t *log_addr; - size_t log_size; - int rc; - - rc = event_log_finalise(&log_addr, &log_size); - if (rc != 0) { - panic(); - } - - dump_event_log(log_addr, log_size); -} diff --git a/drivers/mtd/nand/spi_nand.c b/drivers/mtd/nand/spi_nand.c index d01a11963..abb524d7f 100644 --- a/drivers/mtd/nand/spi_nand.c +++ b/drivers/mtd/nand/spi_nand.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -286,6 +286,10 @@ int spi_nand_init(unsigned long long *size, unsigned int *erase_size) return -EINVAL; } + assert((spinand_dev.nand_dev->page_size != 0U) && + (spinand_dev.nand_dev->block_size != 0U) && + (spinand_dev.nand_dev->size != 0U)); + ret = spi_nand_reset(); if (ret != 0) { return ret; @@ -301,12 +305,12 @@ int spi_nand_init(unsigned long long *size, unsigned int *erase_size) return ret; } - ret = spi_nand_quad_enable(id[0]); + ret = spi_nand_quad_enable(id[1]); if (ret != 0) { return ret; } - VERBOSE("SPI_NAND Detected ID 0x%x 0x%x\n", id[0], id[1]); + VERBOSE("SPI_NAND Detected ID 0x%x\n", id[1]); VERBOSE("Page size %i, Block size %i, size %lli\n", spinand_dev.nand_dev->page_size, diff --git a/drivers/mtd/spi-mem/spi_mem.c b/drivers/mtd/spi-mem/spi_mem.c index 63ea7699b..010e8b62a 100644 --- a/drivers/mtd/spi-mem/spi_mem.c +++ b/drivers/mtd/spi-mem/spi_mem.c @@ -5,6 +5,8 @@ */ #include <assert.h> +#include <inttypes.h> +#include <stdint.h> #include <libfdt.h> @@ -150,7 +152,7 @@ int spi_mem_exec_op(const struct spi_mem_op *op) const struct spi_bus_ops *ops = spi_slave.ops; int ret; - VERBOSE("%s: cmd:%x mode:%d.%d.%d.%d addqr:%llx len:%x\n", + VERBOSE("%s: cmd:%x mode:%d.%d.%d.%d addqr:%" PRIx64 " len:%x\n", __func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, op->dummy.buswidth, op->data.buswidth, op->addr.val, op->data.nbytes); diff --git a/drivers/nxp/ddr/nxp-ddr/ddr.c b/drivers/nxp/ddr/nxp-ddr/ddr.c index 216e05c7c..c051b3b25 100644 --- a/drivers/nxp/ddr/nxp-ddr/ddr.c +++ b/drivers/nxp/ddr/nxp-ddr/ddr.c @@ -5,6 +5,7 @@ */ #include <errno.h> +#include <inttypes.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -850,7 +851,7 @@ long long dram_init(struct ddr_info *priv priv->ip_rev = ip_rev; #ifndef CONFIG_STATIC_DDR - INFO("time base %llu ms\n", time_base); + INFO("time base %" PRIu64 " ms\n", time_base); debug("Parse DIMM SPD(s)\n"); valid_spd_mask = parse_spd(priv); @@ -870,7 +871,7 @@ long long dram_init(struct ddr_info *priv #endif time = get_timer_val(time_base); - INFO("Time after parsing SPD %llu ms\n", time); + INFO("Time after parsing SPD %" PRIu64 " ms\n", time); debug("Synthesize configurations\n"); ret = synthesize_ctlr(priv); if (ret != 0) { @@ -911,7 +912,7 @@ long long dram_init(struct ddr_info *priv } time = get_timer_val(time_base); - INFO("Time before programming controller %llu ms\n", time); + INFO("Time before programming controller %" PRIu64 " ms\n", time); debug("Program controller registers\n"); ret = write_ddrc_regs(priv); if (ret != 0) { @@ -924,7 +925,7 @@ long long dram_init(struct ddr_info *priv print_ddr_info(priv->ddr[0]); time = get_timer_val(time_base); - INFO("Time used by DDR driver %llu ms\n", time); + INFO("Time used by DDR driver %" PRIu64 " ms\n", time); return dram_size; } diff --git a/drivers/nxp/sfp/fuse_prov.c b/drivers/nxp/sfp/fuse_prov.c index 4d30f5f28..165474fb8 100644 --- a/drivers/nxp/sfp/fuse_prov.c +++ b/drivers/nxp/sfp/fuse_prov.c @@ -326,7 +326,7 @@ static int prog_ospr1(struct fuse_hdr_t *fuse_hdr, struct sfp_ccsr_regs_t *sfp_ccsr_regs) { int ret; - uint32_t mask; + uint32_t mask = 0; #ifdef NXP_SFP_VER_3_4 if (((fuse_hdr->flags >> FLAG_MC_SHIFT) & 0x1) != 0) { diff --git a/drivers/partition/partition.c b/drivers/partition/partition.c index 68133eaf4..fdea10dbd 100644 --- a/drivers/partition/partition.c +++ b/drivers/partition/partition.c @@ -5,6 +5,7 @@ */ #include <assert.h> +#include <inttypes.h> #include <stdio.h> #include <string.h> @@ -31,7 +32,7 @@ static void dump_entries(int num) name[len + j] = ' '; } name[EFI_NAMELEN - 1] = '\0'; - VERBOSE("%d: %s %llx-%llx\n", i + 1, name, list.list[i].start, + VERBOSE("%d: %s %" PRIx64 "-%" PRIx64 "\n", i + 1, name, list.list[i].start, list.list[i].start + list.list[i].length - 4); } } diff --git a/drivers/renesas/common/console/rcar_console.S b/drivers/renesas/common/console/rcar_console.S index 29baa67a4..b683d7bfb 100644 --- a/drivers/renesas/common/console/rcar_console.S +++ b/drivers/renesas/common/console/rcar_console.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -63,7 +63,7 @@ endfunc console_rcar_register * --------------------------------------------- */ func console_rcar_init - mov w0, #0 + mov w0, #1 ret endfunc console_rcar_init diff --git a/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c b/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c index a49510ed5..f0113f111 100644 --- a/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c +++ b/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, Renesas Electronics Corporation. + * Copyright (c) 2015-2021, Renesas Electronics Corporation. * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -11,7 +11,11 @@ #include "rcar_def.h" #include "../ddr_regs.h" -#define RCAR_DDR_VERSION "rev.0.01" +#define RCAR_DDR_VERSION "rev.0.02" + +/* Average periodic refresh interval[ns]. Support 3900,7800 */ +#define REFRESH_RATE 3900 + #if RCAR_LSI != RCAR_D3 #error "Don't have DDR initialize routine." @@ -44,7 +48,7 @@ static void init_ddr_d3_1866(void) mmio_write_32(DBSC_DBTR16, 0x09210507); mmio_write_32(DBSC_DBTR17, 0x040E0000); mmio_write_32(DBSC_DBTR18, 0x00000200); - mmio_write_32(DBSC_DBTR19, 0x012B004B); + mmio_write_32(DBSC_DBTR19, 0x0129004B); mmio_write_32(DBSC_DBTR20, 0x020000FB); mmio_write_32(DBSC_DBTR21, 0x00040004); mmio_write_32(DBSC_DBBL, 0x00000000); @@ -54,8 +58,8 @@ static void init_ddr_d3_1866(void) mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); mmio_write_32(DBSC_DBSCHRW1, 0x00000046); - mmio_write_32(DBSC_SCFCTST0, 0x0D020D04); - mmio_write_32(DBSC_SCFCTST1, 0x0306040C); + mmio_write_32(DBSC_SCFCTST0, 0x0C050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0305030C); mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); mmio_write_32(DBSC_DBCMD, 0x01000001); @@ -101,7 +105,9 @@ static void init_ddr_d3_1866(void) ; mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); - mmio_write_32(DBSC_DBPDRGD_0, 0x0A206F89); + mmio_write_32(DBSC_DBPDRGD_0, + (uint32_t) (REFRESH_RATE * 928 / 125) - 400 + + 0x0A300000); mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); @@ -117,7 +123,11 @@ static void init_ddr_d3_1866(void) mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); mmio_write_32(DBSC_DBPDRGD_0, 0x00000046); mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); - mmio_write_32(DBSC_DBPDRGD_0, 0x000000A0); + if (REFRESH_RATE > 3900) { + mmio_write_32(DBSC_DBPDRGD_0, 0x00000020); + } else { + mmio_write_32(DBSC_DBPDRGD_0, 0x000000A0); + } mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); @@ -225,8 +235,10 @@ static void init_ddr_d3_1866(void) mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); r2 = mmio_read_32(DBSC_DBPDRGD_0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); r2 = mmio_read_32(DBSC_DBPDRGD_0); mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); @@ -296,8 +308,10 @@ static void init_ddr_d3_1866(void) mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); - mmio_write_32(DBSC_DBCALCNF, 0x0100401B); - mmio_write_32(DBSC_DBRFCNF1, 0x00080E23); + mmio_write_32(DBSC_DBCALCNF, + (uint32_t) (64000000 / REFRESH_RATE) + 0x01000000); + mmio_write_32(DBSC_DBRFCNF1, + (uint32_t) (REFRESH_RATE * 116 / 125) + 0x00080000); mmio_write_32(DBSC_DBRFCNF2, 0x00010000); mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); mmio_write_32(DBSC_DBRFEN, 0x00000001); @@ -346,6 +360,19 @@ static void init_ddr_d3_1600(void) { uint32_t i, r2, r3, r5, r6, r7, r12; + mmio_write_32(CPG_CPGWPR, 0x5A5AFFFF); + mmio_write_32(CPG_CPGWPCR, 0xA5A50000); + + mmio_write_32(CPG_SRCR4, 0x20000000); + + mmio_write_32(0xE61500DC, 0xe2200000); + while (!(mmio_read_32(CPG_PLLECR) & BIT(11))) + ; + + mmio_write_32(CPG_SRSTCLR4, 0x20000000); + + mmio_write_32(CPG_CPGWPCR, 0xA5A50001); + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); mmio_write_32(DBSC_DBKIND, 0x00000007); mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a01); @@ -363,14 +390,14 @@ static void init_ddr_d3_1600(void) mmio_write_32(DBSC_DBTR10, 0x0000000C); mmio_write_32(DBSC_DBTR11, 0x0000000A); mmio_write_32(DBSC_DBTR12, 0x00120012); - mmio_write_32(DBSC_DBTR13, 0x000000D0); + mmio_write_32(DBSC_DBTR13, 0x000000CE); mmio_write_32(DBSC_DBTR14, 0x00140005); mmio_write_32(DBSC_DBTR15, 0x00050004); mmio_write_32(DBSC_DBTR16, 0x071F0305); mmio_write_32(DBSC_DBTR17, 0x040C0000); mmio_write_32(DBSC_DBTR18, 0x00000200); mmio_write_32(DBSC_DBTR19, 0x01000040); - mmio_write_32(DBSC_DBTR20, 0x020000D8); + mmio_write_32(DBSC_DBTR20, 0x020000D6); mmio_write_32(DBSC_DBTR21, 0x00040004); mmio_write_32(DBSC_DBBL, 0x00000000); mmio_write_32(DBSC_DBODT0, 0x00000001); @@ -379,8 +406,8 @@ static void init_ddr_d3_1600(void) mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); mmio_write_32(DBSC_DBSCHRW1, 0x00000046); - mmio_write_32(DBSC_SCFCTST0, 0x0D020C04); - mmio_write_32(DBSC_SCFCTST1, 0x0305040C); + mmio_write_32(DBSC_SCFCTST0, 0x0D050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0306030C); mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); mmio_write_32(DBSC_DBCMD, 0x01000001); @@ -426,13 +453,14 @@ static void init_ddr_d3_1600(void) ; mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); - mmio_write_32(DBSC_DBPDRGD_0, 0x08C05FF0); + mmio_write_32(DBSC_DBPDRGD_0, + (uint32_t) (REFRESH_RATE * 792 / 125) - 400 + 0x08B00000); mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); mmio_write_32(DBSC_DBPDRGD_0, 0x2D9C0B66); mmio_write_32(DBSC_DBPDRGA_0, 0x00000024); - mmio_write_32(DBSC_DBPDRGD_0, 0x2A88C400); + mmio_write_32(DBSC_DBPDRGD_0, 0x2A88B400); mmio_write_32(DBSC_DBPDRGA_0, 0x00000025); mmio_write_32(DBSC_DBPDRGD_0, 0x30005200); mmio_write_32(DBSC_DBPDRGA_0, 0x00000026); @@ -442,7 +470,11 @@ static void init_ddr_d3_1600(void) mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); mmio_write_32(DBSC_DBPDRGD_0, 0x00000046); mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); - mmio_write_32(DBSC_DBPDRGD_0, 0x00000098); + if (REFRESH_RATE > 3900) { + mmio_write_32(DBSC_DBPDRGD_0, 0x00000018); + } else { + mmio_write_32(DBSC_DBPDRGD_0, 0x00000098); + } mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); @@ -549,9 +581,11 @@ static void init_ddr_d3_1600(void) mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); r2 = mmio_read_32(DBSC_DBPDRGD_0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); r2 = mmio_read_32(DBSC_DBPDRGD_0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); @@ -620,8 +654,10 @@ static void init_ddr_d3_1600(void) mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); - mmio_write_32(DBSC_DBCALCNF, 0x0100401B); - mmio_write_32(DBSC_DBRFCNF1, 0x00080C30); + mmio_write_32(DBSC_DBCALCNF, + (uint32_t) (64000000 / REFRESH_RATE) + 0x01000000); + mmio_write_32(DBSC_DBRFCNF1, + (uint32_t) (REFRESH_RATE * 99 / 125) + 0x00080000); mmio_write_32(DBSC_DBRFCNF2, 0x00010000); mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); mmio_write_32(DBSC_DBRFEN, 0x00000001); @@ -693,7 +729,7 @@ int32_t rcar_dram_init(void) ddr_mbps = 1600; } - NOTICE("BL2: DDR%d\n", ddr_mbps); + NOTICE("BL2: DDR%d(%s)\n", ddr_mbps, RCAR_DDR_VERSION); return 0; } diff --git a/drivers/renesas/common/io/io_rcar.c b/drivers/renesas/common/io/io_rcar.c index c3e8319de..45ef386ae 100644 --- a/drivers/renesas/common/io/io_rcar.c +++ b/drivers/renesas/common/io/io_rcar.c @@ -151,6 +151,9 @@ int32_t rcar_get_certificate(const int32_t name, uint32_t *cert) return -EINVAL; } +#define MFISBTSTSR (0xE6260604U) +#define MFISBTSTSR_BOOT_PARTITION (0x00000010U) + static int32_t file_to_offset(const int32_t name, uintptr_t *offset, uint32_t *cert, uint32_t *no_load, uintptr_t *partition) @@ -169,6 +172,9 @@ static int32_t file_to_offset(const int32_t name, uintptr_t *offset, } *offset = rcar_image_header[addr]; + + if (mmio_read_32(MFISBTSTSR) & MFISBTSTSR_BOOT_PARTITION) + *offset += 0x800000; *cert = RCAR_CERT_SIZE; *cert *= RCAR_ATTR_GET_CERTOFF(name_offset[i].attr); *cert += RCAR_SDRAM_certESS; @@ -374,7 +380,7 @@ static int32_t load_bl33x(void) static int32_t rcar_dev_init(io_dev_info_t *dev_info, const uintptr_t name) { - uint64_t header[64] __aligned(FLASH_TRANS_SIZE_UNIT) = {0UL}; + static uint64_t header[64] __aligned(FLASH_TRANS_SIZE_UNIT) = {0UL}; uintptr_t handle; ssize_t offset; uint32_t i; @@ -417,15 +423,17 @@ static int32_t rcar_dev_init(io_dev_info_t *dev_info, const uintptr_t name) WARN("Firmware Image Package header failed to seek\n"); goto error; } -#if RCAR_BL2_DCACHE == 1 - inv_dcache_range((uint64_t) header, sizeof(header)); -#endif + rc = io_read(handle, (uintptr_t) &header, sizeof(header), &cnt); if (rc != IO_SUCCESS) { WARN("Firmware Image Package header failed to read\n"); goto error; } +#if RCAR_BL2_DCACHE == 1 + inv_dcache_range((uint64_t) header, sizeof(header)); +#endif + rcar_image_number = header[0]; for (i = 0; i < rcar_image_number + 2; i++) { rcar_image_header[i] = header[i * 2 + 1]; @@ -434,6 +442,7 @@ static int32_t rcar_dev_init(io_dev_info_t *dev_info, const uintptr_t name) if (rcar_image_number == 0 || rcar_image_number > RCAR_MAX_BL3X_IMAGE) { WARN("Firmware Image Package header check failed.\n"); + rc = IO_FAIL; goto error; } @@ -442,10 +451,7 @@ static int32_t rcar_dev_init(io_dev_info_t *dev_info, const uintptr_t name) WARN("Firmware Image Package header failed to seek cert\n"); goto error; } -#if RCAR_BL2_DCACHE == 1 - inv_dcache_range(RCAR_SDRAM_certESS, - RCAR_CERT_SIZE * (2 + rcar_image_number)); -#endif + rc = io_read(handle, RCAR_SDRAM_certESS, RCAR_CERT_SIZE * (2 + rcar_image_number), &cnt); if (rc != IO_SUCCESS) { @@ -453,6 +459,11 @@ static int32_t rcar_dev_init(io_dev_info_t *dev_info, const uintptr_t name) goto error; } +#if RCAR_BL2_DCACHE == 1 + inv_dcache_range(RCAR_SDRAM_certESS, + RCAR_CERT_SIZE * (2 + rcar_image_number)); +#endif + rcar_cert_load = RCAR_CERT_LOAD; error: diff --git a/drivers/renesas/common/pwrc/pwrc.c b/drivers/renesas/common/pwrc/pwrc.c index 3f60fe633..4e175eb97 100644 --- a/drivers/renesas/common/pwrc/pwrc.c +++ b/drivers/renesas/common/pwrc/pwrc.c @@ -44,6 +44,7 @@ RCAR_INSTANTIATE_LOCK #define CPU_PWR_OFF (0x00000003U) #define RCAR_PSTR_MASK (0x00000003U) #define ST_ALL_STANDBY (0x00003333U) +#define SYSCEXTMASK_EXTMSK0 (0x00000001U) /* Suspend to ram */ #define DBSC4_REG_BASE (0xE6790000U) #define DBSC4_REG_DBSYSCNT0 (DBSC4_REG_BASE + 0x0100U) @@ -191,6 +192,8 @@ static void scu_power_up(uint64_t mpidr) { uintptr_t reg_pwrsr, reg_cpumcr, reg_pwron, reg_pwrer; uint32_t c, sysc_reg_bit; + uint32_t lsi_product; + uint32_t lsi_cut; c = rcar_pwrc_get_mpidr_cluster(mpidr); reg_cpumcr = IS_CA57(c) ? RCAR_CA57CPUCMCR : RCAR_CA53CPUCMCR; @@ -205,6 +208,17 @@ static void scu_power_up(uint64_t mpidr) if (mmio_read_32(reg_cpumcr) != 0) mmio_write_32(reg_cpumcr, 0); + lsi_product = mmio_read_32((uintptr_t)RCAR_PRR); + lsi_cut = lsi_product & PRR_CUT_MASK; + lsi_product &= PRR_PRODUCT_MASK; + + if ((lsi_product == PRR_PRODUCT_M3 && lsi_cut >= PRR_PRODUCT_30) || + lsi_product == PRR_PRODUCT_H3 || + lsi_product == PRR_PRODUCT_M3N || + lsi_product == PRR_PRODUCT_E3) { + mmio_setbits_32(RCAR_SYSCEXTMASK, SYSCEXTMASK_EXTMSK0); + } + mmio_setbits_32(RCAR_SYSCIER, sysc_reg_bit); mmio_setbits_32(RCAR_SYSCIMR, sysc_reg_bit); @@ -216,7 +230,15 @@ static void scu_power_up(uint64_t mpidr) while ((mmio_read_32(RCAR_SYSCISR) & sysc_reg_bit) == 0) ; - mmio_write_32(RCAR_SYSCISR, sysc_reg_bit); + mmio_write_32(RCAR_SYSCISCR, sysc_reg_bit); + + if ((lsi_product == PRR_PRODUCT_M3 && lsi_cut >= PRR_PRODUCT_30) || + lsi_product == PRR_PRODUCT_H3 || + lsi_product == PRR_PRODUCT_M3N || + lsi_product == PRR_PRODUCT_E3) { + mmio_clrbits_32(RCAR_SYSCEXTMASK, SYSCEXTMASK_EXTMSK0); + } + while ((mmio_read_32(reg_pwrsr) & STATUS_PWRUP) == 0) ; } @@ -754,14 +776,14 @@ void rcar_pwrc_code_copy_to_system_ram(void) memcpy((void *)sram.base, code.base, code.len); flush_dcache_range((uint64_t) sram.base, code.len); + attr = MT_MEMORY | MT_RO | MT_SECURE | MT_EXECUTE; + ret = xlat_change_mem_attributes(sram.base, sram.len, attr); + assert(ret == 0); + /* Invalidate instruction cache */ plat_invalidate_icache(); dsb(); isb(); - - attr = MT_MEMORY | MT_RO | MT_SECURE | MT_EXECUTE; - ret = xlat_change_mem_attributes(sram.base, sram.len, attr); - assert(ret == 0); } uint32_t rcar_pwrc_get_cluster(void) diff --git a/drivers/renesas/common/scif/scif.S b/drivers/renesas/common/scif/scif.S index beb8dd838..72b5b4bea 100644 --- a/drivers/renesas/common/scif/scif.S +++ b/drivers/renesas/common/scif/scif.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -79,7 +79,7 @@ SCSMR_STOP_1 + \ SCSMR_CKS_DIV1) #define SCBRR_115200BPS (17) -#define SCBRR_115200BPSON (16) +#define SCBRR_115200BPS_D3_SSCG (16) #define SCBRR_115200BPS_E3_SSCG (15) #define SCBRR_230400BPS (8) @@ -216,26 +216,38 @@ func console_rcar_init and w1, w1, #PRR_PRODUCT_MASK mov w2, #PRR_PRODUCT_D3 cmp w1, w2 - beq 4f + beq 5f and w1, w1, #PRR_PRODUCT_MASK mov w2, #PRR_PRODUCT_E3 cmp w1, w2 - bne 5f + bne 4f + /* When SSCG(MD12) on (E3) */ ldr x1, =RST_MODEMR ldr w1, [x1] and w1, w1, #MODEMR_MD12 mov w2, #MODEMR_MD12 cmp w1, w2 - bne 5f + bne 4f + /* When SSCG(MD12) on (E3) */ mov w1, #SCBRR_115200BPS_E3_SSCG b 2f 5: - mov w1, #SCBRR_115200BPS + /* In case of D3 */ + ldr x1, =RST_MODEMR + ldr w1, [x1] + and w1, w1, #MODEMR_MD12 + mov w2, #MODEMR_MD12 + cmp w1, w2 + bne 4f + + /* When SSCG(MD12) on (D3) */ + mov w1, #SCBRR_115200BPS_D3_SSCG b 2f 4: - mov w1, #SCBRR_115200BPSON + /* In case of H3/M3/M3N or when SSCG(MD12) is off in E3/D3 */ + mov w1, #SCBRR_115200BPS b 2f 3: mov w1, #SCBRR_230400BPS diff --git a/drivers/renesas/common/watchdog/swdt.c b/drivers/renesas/common/watchdog/swdt.c index 1a351ca17..29ef6f430 100644 --- a/drivers/renesas/common/watchdog/swdt.c +++ b/drivers/renesas/common/watchdog/swdt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -78,7 +78,7 @@ static void swdt_disable(void) void rcar_swdt_init(void) { uint32_t rmsk, sr; -#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RZ_G2E) +#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RCAR_D3) && (RCAR_LSI != RZ_G2E) uint32_t reg, val, product_cut, chk_data; reg = mmio_read_32(RCAR_PRR); @@ -96,6 +96,8 @@ void rcar_swdt_init(void) #if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2E) mmio_write_32(SWDT_WTCNT, WTCNT_UPPER_BYTE | WTCNT_COUNT_7p81k); +#elif (RCAR_LSI == RCAR_D3) + mmio_write_32(SWDT_WTCNT, WTCNT_UPPER_BYTE | WTCNT_COUNT_8p13k); #else val = WTCNT_UPPER_BYTE; diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index 6ada96a52..3ebc376cd 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -56,6 +56,7 @@ enum stm32mp1_parent_id { _HSI_KER = NB_OSC, _HSE_KER, _HSE_KER_DIV2, + _HSE_RTC, _CSI_KER, _PLL1_P, _PLL1_Q, @@ -107,7 +108,7 @@ enum stm32mp1_parent_sel { _USBPHY_SEL, _USBO_SEL, _MPU_SEL, - _PER_SEL, + _CKPER_SEL, _RTC_SEL, _PARENT_SEL_NB, _UNKNOWN_SEL = 0xff, @@ -125,6 +126,7 @@ static const uint8_t parent_id_clock_id[_PARENT_NB] = { [_HSI_KER] = CK_HSI, [_HSE_KER] = CK_HSE, [_HSE_KER_DIV2] = CK_HSE_DIV2, + [_HSE_RTC] = _UNKNOWN_ID, [_CSI_KER] = CK_CSI, [_PLL1_P] = PLL1_P, [_PLL1_Q] = PLL1_Q, @@ -465,12 +467,12 @@ static const uint8_t fmc_parents[] = { _ACLK, _PLL3_R, _PLL4_P, _CK_PER }; -static const uint8_t ass_parents[] = { - _HSI, _HSE, _PLL2 +static const uint8_t axiss_parents[] = { + _HSI, _HSE, _PLL2_P }; -static const uint8_t mss_parents[] = { - _HSI, _HSE, _CSI, _PLL3 +static const uint8_t mcuss_parents[] = { + _HSI, _HSE, _CSI, _PLL3_P }; static const uint8_t usbphy_parents[] = { @@ -490,7 +492,7 @@ static const uint8_t per_parents[] = { }; static const uint8_t rtc_parents[] = { - _UNKNOWN_ID, _LSE, _LSI, _HSE + _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC }; static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { @@ -502,7 +504,7 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents), _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents), _CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents), - _CLK_PARENT_SEL(PER, RCC_CPERCKSELR, per_parents), + _CLK_PARENT_SEL(CKPER, RCC_CPERCKSELR, per_parents), _CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents), _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents), _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents), @@ -512,8 +514,8 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents), _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents), _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents), - _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, ass_parents), - _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mss_parents), + _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, axiss_parents), + _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mcuss_parents), _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents), _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents), }; @@ -587,6 +589,7 @@ static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = { [_HSI_KER] = "HSI_KER", [_HSE_KER] = "HSE_KER", [_HSE_KER_DIV2] = "HSE_KER_DIV2", + [_HSE_RTC] = "HSE_RTC", [_CSI_KER] = "CSI_KER", [_PLL1_P] = "PLL1_P", [_PLL1_Q] = "PLL1_Q", @@ -847,9 +850,7 @@ static unsigned long get_clock_rate(int p) reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); clkdiv = reg & RCC_MPUDIV_MASK; - if (clkdiv != 0U) { - clock /= stm32mp1_mpu_div[clkdiv]; - } + clock >>= stm32mp1_mpu_div[clkdiv]; break; default: break; @@ -969,6 +970,10 @@ static unsigned long get_clock_rate(int p) case _HSE_KER_DIV2: clock = stm32mp1_clk_get_fixed(_HSE) >> 1; break; + case _HSE_RTC: + clock = stm32mp1_clk_get_fixed(_HSE); + clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U; + break; case _LSI: clock = stm32mp1_clk_get_fixed(_LSI); break; @@ -1086,6 +1091,10 @@ static bool clock_is_always_on(unsigned long id) case PLL3_P: case PLL3_Q: case PLL3_R: + case CK_AXI: + case CK_MPU: + case CK_MCU: + case RTC: return true; default: return false; @@ -1652,7 +1661,7 @@ static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) (clksrc != (uint32_t)CLK_RTC_DISABLED)) { mmio_clrsetbits_32(address, RCC_BDCR_RTCSRC_MASK, - clksrc << RCC_BDCR_RTCSRC_SHIFT); + (clksrc & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT); mmio_setbits_32(address, RCC_BDCR_RTCCKEN); } @@ -2152,6 +2161,7 @@ static void secure_parent_clocks(unsigned long parent_id) case _HSE: case _HSE_KER: case _HSE_KER_DIV2: + case _HSE_RTC: case _LSE: break; @@ -2210,6 +2220,7 @@ static void sync_earlyboot_clocks_state(void) DDRC2, DDRC2LP, DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP, DDRPHYC, DDRPHYCLP, + RTCAPB, TZC1, TZC2, TZPC, STGEN_K, @@ -2218,10 +2229,6 @@ static void sync_earlyboot_clocks_state(void) for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) { stm32mp_clk_enable(secure_enable[idx]); } - - if (!stm32mp_is_single_core()) { - stm32mp1_clk_enable_secure(RTCAPB); - } } int stm32mp1_clk_probe(void) diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c index 8333f6dfb..d57f120b9 100644 --- a/drivers/st/clk/stm32mp_clkfunc.c +++ b/drivers/st/clk/stm32mp_clkfunc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -161,9 +161,15 @@ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, * @param fdt: Device tree reference * @return: Node offset or a negative value on error */ -int fdt_get_rcc_node(void *fdt) +static int fdt_get_rcc_node(void *fdt) { - return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); + static int node; + + if (node <= 0) { + node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); + } + + return node; } /* diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c index cff3a344f..d3adeab13 100644 --- a/drivers/st/mmc/stm32_sdmmc2.c +++ b/drivers/st/mmc/stm32_sdmmc2.c @@ -628,6 +628,7 @@ static int stm32_sdmmc2_dt_get_config(void) int sdmmc_node; void *fdt = NULL; const fdt32_t *cuint; + struct dt_node_info dt_info; if (fdt_get_address(&fdt) == 0) { return -FDT_ERR_NOTFOUND; @@ -637,27 +638,14 @@ static int stm32_sdmmc2_dt_get_config(void) return -FDT_ERR_NOTFOUND; } - sdmmc_node = fdt_node_offset_by_compatible(fdt, -1, DT_SDMMC2_COMPAT); - - while (sdmmc_node != -FDT_ERR_NOTFOUND) { - cuint = fdt_getprop(fdt, sdmmc_node, "reg", NULL); - if (cuint == NULL) { - continue; - } - - if (fdt32_to_cpu(*cuint) == sdmmc2_params.reg_base) { - break; - } - - sdmmc_node = fdt_node_offset_by_compatible(fdt, sdmmc_node, - DT_SDMMC2_COMPAT); - } - + sdmmc_node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, + sdmmc2_params.reg_base); if (sdmmc_node == -FDT_ERR_NOTFOUND) { return -FDT_ERR_NOTFOUND; } - if (fdt_get_status(sdmmc_node) == DT_DISABLED) { + dt_fill_device_info(&dt_info, sdmmc_node); + if (dt_info.status == DT_DISABLED) { return -FDT_ERR_NOTFOUND; } @@ -665,21 +653,8 @@ static int stm32_sdmmc2_dt_get_config(void) return -FDT_ERR_BADVALUE; } - cuint = fdt_getprop(fdt, sdmmc_node, "clocks", NULL); - if (cuint == NULL) { - return -FDT_ERR_NOTFOUND; - } - - cuint++; - sdmmc2_params.clock_id = fdt32_to_cpu(*cuint); - - cuint = fdt_getprop(fdt, sdmmc_node, "resets", NULL); - if (cuint == NULL) { - return -FDT_ERR_NOTFOUND; - } - - cuint++; - sdmmc2_params.reset_id = fdt32_to_cpu(*cuint); + sdmmc2_params.clock_id = dt_info.clock; + sdmmc2_params.reset_id = dt_info.reset; if ((fdt_getprop(fdt, sdmmc_node, "st,use-ckin", NULL)) != NULL) { sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0; diff --git a/drivers/st/pmic/stpmic1.c b/drivers/st/pmic/stpmic1.c index 999963054..0a35df372 100644 --- a/drivers/st/pmic/stpmic1.c +++ b/drivers/st/pmic/stpmic1.c @@ -1,9 +1,10 @@ /* - * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved + * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ +#include <errno.h> #include <string.h> #include <common/debug.h> @@ -16,6 +17,7 @@ struct regul_struct { const uint16_t *voltage_table; uint8_t voltage_table_size; uint8_t control_reg; + uint8_t enable_mask; uint8_t low_power_reg; uint8_t pull_down_reg; uint8_t pull_down; @@ -426,6 +428,7 @@ static const struct regul_struct regulators_table[] = { .voltage_table = buck1_voltage_table, .voltage_table_size = ARRAY_SIZE(buck1_voltage_table), .control_reg = BUCK1_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, .low_power_reg = BUCK1_PWRCTRL_REG, .pull_down_reg = BUCK_PULL_DOWN_REG, .pull_down = BUCK1_PULL_DOWN_SHIFT, @@ -437,6 +440,7 @@ static const struct regul_struct regulators_table[] = { .voltage_table = buck2_voltage_table, .voltage_table_size = ARRAY_SIZE(buck2_voltage_table), .control_reg = BUCK2_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, .low_power_reg = BUCK2_PWRCTRL_REG, .pull_down_reg = BUCK_PULL_DOWN_REG, .pull_down = BUCK2_PULL_DOWN_SHIFT, @@ -448,6 +452,7 @@ static const struct regul_struct regulators_table[] = { .voltage_table = buck3_voltage_table, .voltage_table_size = ARRAY_SIZE(buck3_voltage_table), .control_reg = BUCK3_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, .low_power_reg = BUCK3_PWRCTRL_REG, .pull_down_reg = BUCK_PULL_DOWN_REG, .pull_down = BUCK3_PULL_DOWN_SHIFT, @@ -459,6 +464,7 @@ static const struct regul_struct regulators_table[] = { .voltage_table = buck4_voltage_table, .voltage_table_size = ARRAY_SIZE(buck4_voltage_table), .control_reg = BUCK4_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, .low_power_reg = BUCK4_PWRCTRL_REG, .pull_down_reg = BUCK_PULL_DOWN_REG, .pull_down = BUCK4_PULL_DOWN_SHIFT, @@ -470,6 +476,7 @@ static const struct regul_struct regulators_table[] = { .voltage_table = ldo1_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table), .control_reg = LDO1_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, .low_power_reg = LDO1_PWRCTRL_REG, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset = LDO1_MASK_RESET, @@ -479,6 +486,7 @@ static const struct regul_struct regulators_table[] = { .voltage_table = ldo2_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table), .control_reg = LDO2_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, .low_power_reg = LDO2_PWRCTRL_REG, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset = LDO2_MASK_RESET, @@ -488,6 +496,7 @@ static const struct regul_struct regulators_table[] = { .voltage_table = ldo3_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table), .control_reg = LDO3_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, .low_power_reg = LDO3_PWRCTRL_REG, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset = LDO3_MASK_RESET, @@ -497,6 +506,7 @@ static const struct regul_struct regulators_table[] = { .voltage_table = ldo4_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table), .control_reg = LDO4_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, .low_power_reg = LDO4_PWRCTRL_REG, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset = LDO4_MASK_RESET, @@ -506,6 +516,7 @@ static const struct regul_struct regulators_table[] = { .voltage_table = ldo5_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table), .control_reg = LDO5_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, .low_power_reg = LDO5_PWRCTRL_REG, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset = LDO5_MASK_RESET, @@ -515,6 +526,7 @@ static const struct regul_struct regulators_table[] = { .voltage_table = ldo6_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table), .control_reg = LDO6_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, .low_power_reg = LDO6_PWRCTRL_REG, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset = LDO6_MASK_RESET, @@ -524,6 +536,7 @@ static const struct regul_struct regulators_table[] = { .voltage_table = vref_ddr_voltage_table, .voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table), .control_reg = VREF_DDR_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, .low_power_reg = VREF_DDR_PWRCTRL_REG, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset = VREF_DDR_MASK_RESET, @@ -581,14 +594,16 @@ int stpmic1_regulator_enable(const char *name) { const struct regul_struct *regul = get_regulator_data(name); - return stpmic1_register_update(regul->control_reg, BIT(0), BIT(0)); + return stpmic1_register_update(regul->control_reg, regul->enable_mask, + regul->enable_mask); } int stpmic1_regulator_disable(const char *name) { const struct regul_struct *regul = get_regulator_data(name); - return stpmic1_register_update(regul->control_reg, 0, BIT(0)); + return stpmic1_register_update(regul->control_reg, 0, + regul->enable_mask); } uint8_t stpmic1_is_regulator_enabled(const char *name) @@ -600,7 +615,7 @@ uint8_t stpmic1_is_regulator_enabled(const char *name) panic(); } - return (val & 0x1U); + return (val & regul->enable_mask); } int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) @@ -653,6 +668,7 @@ int stpmic1_regulator_voltage_get(const char *name) const struct regul_struct *regul = get_regulator_data(name); uint8_t value; uint8_t mask; + int status; /* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */ if (strncmp(name, "buck", 4) == 0) { @@ -664,13 +680,16 @@ int stpmic1_regulator_voltage_get(const char *name) return 0; } - if (stpmic1_register_read(regul->control_reg, &value)) - return -1; + status = stpmic1_register_read(regul->control_reg, &value); + if (status < 0) { + return status; + } value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT; - if (value > regul->voltage_table_size) - return -1; + if (value > regul->voltage_table_size) { + return -ERANGE; + } return (int)regul->voltage_table[value]; } @@ -706,7 +725,7 @@ int stpmic1_register_write(uint8_t register_id, uint8_t value) } if (readval != value) { - return -1; + return -EIO; } } #endif @@ -751,12 +770,12 @@ void stpmic1_dump_regulators(void) int stpmic1_get_version(unsigned long *version) { - int rc; uint8_t read_val; + int status; - rc = stpmic1_register_read(VERSION_STATUS_REG, &read_val); - if (rc) { - return -1; + status = stpmic1_register_read(VERSION_STATUS_REG, &read_val); + if (status < 0) { + return status; } *version = (unsigned long)read_val; diff --git a/drivers/st/spi/stm32_qspi.c b/drivers/st/spi/stm32_qspi.c index d67f8313f..4b1a0296c 100644 --- a/drivers/st/spi/stm32_qspi.c +++ b/drivers/st/spi/stm32_qspi.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +#include <inttypes.h> #include <libfdt.h> #include <platform_def.h> @@ -244,7 +245,7 @@ static int stm32_qspi_exec_op(const struct spi_mem_op *op) uint8_t mode = QSPI_CCR_IND_WRITE; int ret; - VERBOSE("%s: cmd:%x mode:%d.%d.%d.%d addr:%llx len:%x\n", + VERBOSE("%s: cmd:%x mode:%d.%d.%d.%d addr:%" PRIx64 " len:%x\n", __func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, op->dummy.buswidth, op->data.buswidth, op->addr.val, op->data.nbytes); diff --git a/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S index 686b18b96..2b8879a11 100644 --- a/drivers/st/uart/aarch32/stm32_console.S +++ b/drivers/st/uart/aarch32/stm32_console.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -45,7 +45,12 @@ func console_stm32_core_init /* Check the input base address */ cmp r0, #0 beq core_init_fail -#if defined(IMAGE_BL2) +#if !defined(IMAGE_BL2) + /* Skip UART initialization if it is already enabled */ + ldr r3, [r0, #USART_CR1] + ands r3, r3, #USART_CR1_UE + bne 1f +#endif /* IMAGE_BL2 */ /* Check baud rate and uart clock for sanity */ cmp r1, #0 beq core_init_fail @@ -78,7 +83,7 @@ teack_loop: ldr r3, [r0, #USART_ISR] tst r3, #USART_ISR_TEACK beq teack_loop -#endif /* IMAGE_BL2 */ +1: mov r0, #1 bx lr core_init_fail: diff --git a/drivers/st/usb/stm32mp1_usb.c b/drivers/st/usb/stm32mp1_usb.c new file mode 100644 index 000000000..9a4969036 --- /dev/null +++ b/drivers/st/usb/stm32mp1_usb.c @@ -0,0 +1,1091 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <drivers/st/stm32mp1_usb.h> +#include <lib/mmio.h> + +#include <platform_def.h> + +#define USB_OTG_MODE_DEVICE 0U +#define USB_OTG_MODE_HOST 1U +#define USB_OTG_MODE_DRD 2U + +#define EP_TYPE_CTRL 0U +#define EP_TYPE_ISOC 1U +#define EP_TYPE_BULK 2U +#define EP_TYPE_INTR 3U + +#define USBD_FIFO_FLUSH_TIMEOUT_US 1000U +#define EP0_FIFO_SIZE 64U + +/* OTG registers offsets */ +#define OTG_GOTGINT 0x004U +#define OTG_GAHBCFG 0x008U +#define OTG_GUSBCFG 0x00CU +#define OTG_GRSTCTL 0x010U +#define OTG_GINTSTS 0x014U +#define OTG_GINTMSK 0x018U +#define OTG_GRXSTSP 0x020U +#define OTG_GLPMCFG 0x054U +#define OTG_DCFG 0x800U +#define OTG_DCTL 0x804U +#define OTG_DSTS 0x808U +#define OTG_DIEPMSK 0x810U +#define OTG_DOEPMSK 0x814U +#define OTG_DAINT 0x818U +#define OTG_DAINTMSK 0x81CU +#define OTG_DIEPEMPMSK 0x834U + +/* Definitions for OTG_DIEPx registers */ +#define OTG_DIEP_BASE 0x900U +#define OTG_DIEP_SIZE 0x20U +#define OTG_DIEPCTL 0x00U +#define OTG_DIEPINT 0x08U +#define OTG_DIEPTSIZ 0x10U +#define OTG_DIEPDMA 0x14U +#define OTG_DTXFSTS 0x18U +#define OTG_DIEP_MAX_NB 9U + +/* Definitions for OTG_DOEPx registers */ +#define OTG_DOEP_BASE 0xB00U +#define OTG_DOEP_SIZE 0x20U +#define OTG_DOEPCTL 0x00U +#define OTG_DOEPINT 0x08U +#define OTG_DOEPTSIZ 0x10U +#define OTG_DOEPDMA 0x14U +#define OTG_D0EP_MAX_NB 9U + +/* Definitions for OTG_DAINT registers */ +#define OTG_DAINT_OUT_MASK GENMASK(31, 16) +#define OTG_DAINT_OUT_SHIFT 16U +#define OTG_DAINT_IN_MASK GENMASK(15, 0) +#define OTG_DAINT_IN_SHIFT 0U + +#define OTG_DAINT_EP0_IN BIT(16) +#define OTG_DAINT_EP0_OUT BIT(0) + +/* Definitions for FIFOs */ +#define OTG_FIFO_BASE 0x1000U +#define OTG_FIFO_SIZE 0x1000U + +/* Bit definitions for OTG_GOTGINT register */ +#define OTG_GOTGINT_SEDET BIT(2) + +/* Bit definitions for OTG_GAHBCFG register */ +#define OTG_GAHBCFG_GINT BIT(0) + +/* Bit definitions for OTG_GUSBCFG register */ +#define OTG_GUSBCFG_TRDT GENMASK(13, 10) +#define OTG_GUSBCFG_TRDT_SHIFT 10U + +#define USBD_HS_TRDT_VALUE 9U + +/* Bit definitions for OTG_GRSTCTL register */ +#define OTG_GRSTCTL_RXFFLSH BIT(4) +#define OTG_GRSTCTL_TXFFLSH BIT(5) +#define OTG_GRSTCTL_TXFNUM_SHIFT 6U + +/* Bit definitions for OTG_GINTSTS register */ +#define OTG_GINTSTS_CMOD BIT(0) +#define OTG_GINTSTS_MMIS BIT(1) +#define OTG_GINTSTS_OTGINT BIT(2) +#define OTG_GINTSTS_SOF BIT(3) +#define OTG_GINTSTS_RXFLVL BIT(4) +#define OTG_GINTSTS_USBSUSP BIT(11) +#define OTG_GINTSTS_USBRST BIT(12) +#define OTG_GINTSTS_ENUMDNE BIT(13) +#define OTG_GINTSTS_IEPINT BIT(18) +#define OTG_GINTSTS_OEPINT BIT(19) +#define OTG_GINTSTS_IISOIXFR BIT(20) +#define OTG_GINTSTS_IPXFR_INCOMPISOOUT BIT(21) +#define OTG_GINTSTS_LPMINT BIT(27) +#define OTG_GINTSTS_SRQINT BIT(30) +#define OTG_GINTSTS_WKUPINT BIT(31) + +/* Bit definitions for OTG_GRXSTSP register */ +#define OTG_GRXSTSP_EPNUM GENMASK(3, 0) +#define OTG_GRXSTSP_BCNT GENMASK(14, 4) +#define OTG_GRXSTSP_BCNT_SHIFT 4U +#define OTG_GRXSTSP_PKTSTS GENMASK(20, 17) +#define OTG_GRXSTSP_PKTSTS_SHIFT 17U + +#define STS_GOUT_NAK 1U +#define STS_DATA_UPDT 2U +#define STS_XFER_COMP 3U +#define STS_SETUP_COMP 4U +#define STS_SETUP_UPDT 6U + +/* Bit definitions for OTG_GLPMCFG register */ +#define OTG_GLPMCFG_BESL GENMASK(5, 2) + +/* Bit definitions for OTG_DCFG register */ +#define OTG_DCFG_DAD GENMASK(10, 4) +#define OTG_DCFG_DAD_SHIFT 4U + +/* Bit definitions for OTG_DCTL register */ +#define OTG_DCTL_RWUSIG BIT(0) +#define OTG_DCTL_SDIS BIT(1) +#define OTG_DCTL_CGINAK BIT(8) + +/* Bit definitions for OTG_DSTS register */ +#define OTG_DSTS_SUSPSTS BIT(0) +#define OTG_DSTS_ENUMSPD_MASK GENMASK(2, 1) +#define OTG_DSTS_FNSOF0 BIT(8) + +#define OTG_DSTS_ENUMSPD(val) ((val) << 1) +#define OTG_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ OTG_DSTS_ENUMSPD(0U) +#define OTG_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ OTG_DSTS_ENUMSPD(1U) +#define OTG_DSTS_ENUMSPD_LS_PHY_6MHZ OTG_DSTS_ENUMSPD(2U) +#define OTG_DSTS_ENUMSPD_FS_PHY_48MHZ OTG_DSTS_ENUMSPD(3U) + +/* Bit definitions for OTG_DIEPMSK register */ +#define OTG_DIEPMSK_XFRCM BIT(0) +#define OTG_DIEPMSK_EPDM BIT(1) +#define OTG_DIEPMSK_TOM BIT(3) + +/* Bit definitions for OTG_DOEPMSK register */ +#define OTG_DOEPMSK_XFRCM BIT(0) +#define OTG_DOEPMSK_EPDM BIT(1) +#define OTG_DOEPMSK_STUPM BIT(3) + +/* Bit definitions for OTG_DIEPCTLx registers */ +#define OTG_DIEPCTL_MPSIZ GENMASK(10, 0) +#define OTG_DIEPCTL_STALL BIT(21) +#define OTG_DIEPCTL_CNAK BIT(26) +#define OTG_DIEPCTL_SD0PID_SEVNFRM BIT(28) +#define OTG_DIEPCTL_SODDFRM BIT(29) +#define OTG_DIEPCTL_EPDIS BIT(30) +#define OTG_DIEPCTL_EPENA BIT(31) + +/* Bit definitions for OTG_DIEPINTx registers */ +#define OTG_DIEPINT_XFRC BIT(0) +#define OTG_DIEPINT_EPDISD BIT(1) +#define OTG_DIEPINT_TOC BIT(3) +#define OTG_DIEPINT_ITTXFE BIT(4) +#define OTG_DIEPINT_INEPNE BIT(6) +#define OTG_DIEPINT_TXFE BIT(7) +#define OTG_DIEPINT_TXFE_SHIFT 7U + +#define OTG_DIEPINT_MASK (BIT(13) | BIT(11) | GENMASK(9, 0)) + +/* Bit definitions for OTG_DIEPTSIZx registers */ +#define OTG_DIEPTSIZ_XFRSIZ GENMASK(18, 0) +#define OTG_DIEPTSIZ_PKTCNT GENMASK(28, 19) +#define OTG_DIEPTSIZ_PKTCNT_SHIFT 19U +#define OTG_DIEPTSIZ_MCNT_MASK GENMASK(30, 29) +#define OTG_DIEPTSIZ_MCNT_DATA0 BIT(29) + +#define OTG_DIEPTSIZ_PKTCNT_1 BIT(19) + +/* Bit definitions for OTG_DTXFSTSx registers */ +#define OTG_DTXFSTS_INEPTFSAV GENMASK(15, 0) + +/* Bit definitions for OTG_DOEPCTLx registers */ +#define OTG_DOEPCTL_STALL BIT(21) +#define OTG_DOEPCTL_CNAK BIT(26) +#define OTG_DOEPCTL_SD0PID_SEVNFRM BIT(28) /* other than endpoint 0 */ +#define OTG_DOEPCTL_SD1PID_SODDFRM BIT(29) /* other than endpoint 0 */ +#define OTG_DOEPCTL_EPDIS BIT(30) +#define OTG_DOEPCTL_EPENA BIT(31) + +/* Bit definitions for OTG_DOEPTSIZx registers */ +#define OTG_DOEPTSIZ_XFRSIZ GENMASK(18, 0) +#define OTG_DOEPTSIZ_PKTCNT GENMASK(28, 19) +#define OTG_DOEPTSIZ_RXDPID_STUPCNT GENMASK(30, 29) + +/* Bit definitions for OTG_DOEPINTx registers */ +#define OTG_DOEPINT_XFRC BIT(0) +#define OTG_DOEPINT_STUP BIT(3) +#define OTG_DOEPINT_OTEPDIS BIT(4) + +#define OTG_DOEPINT_MASK (GENMASK(15, 12) | GENMASK(9, 8) | GENMASK(6, 0)) + +#define EP_NB 15U +#define EP_ALL 0x10U + +/* + * Flush TX FIFO. + * handle: PCD handle. + * num: FIFO number. + * This parameter can be a value from 1 to 15 or EP_ALL. + * EP_ALL= 0x10 means Flush all TX FIFOs + * return: USB status. + */ +static enum usb_status usb_dwc2_flush_tx_fifo(void *handle, uint32_t num) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US); + + mmio_write_32(usb_base_addr + OTG_GRSTCTL, + OTG_GRSTCTL_TXFFLSH | (uint32_t)(num << OTG_GRSTCTL_TXFNUM_SHIFT)); + + while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) & + OTG_GRSTCTL_TXFFLSH) == OTG_GRSTCTL_TXFFLSH) { + if (timeout_elapsed(timeout)) { + return USBD_TIMEOUT; + } + } + + return USBD_OK; +} + +/* + * Flush RX FIFO. + * handle: PCD handle. + * return: USB status. + */ +static enum usb_status usb_dwc2_flush_rx_fifo(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US); + + mmio_write_32(usb_base_addr + OTG_GRSTCTL, OTG_GRSTCTL_RXFFLSH); + + while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) & + OTG_GRSTCTL_RXFFLSH) == OTG_GRSTCTL_RXFFLSH) { + if (timeout_elapsed(timeout)) { + return USBD_TIMEOUT; + } + } + + return USBD_OK; +} + +/* + * Return the global USB interrupt status. + * handle: PCD handle. + * return: Interrupt register value. + */ +static uint32_t usb_dwc2_read_int(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return mmio_read_32(usb_base_addr + OTG_GINTSTS) & + mmio_read_32(usb_base_addr + OTG_GINTMSK); +} + +/* + * Return the USB device OUT endpoints interrupt. + * handle: PCD handle. + * return: Device OUT endpoint interrupts. + */ +static uint32_t usb_dwc2_all_out_ep_int(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return ((mmio_read_32(usb_base_addr + OTG_DAINT) & + mmio_read_32(usb_base_addr + OTG_DAINTMSK)) & + OTG_DAINT_OUT_MASK) >> OTG_DAINT_OUT_SHIFT; +} + +/* + * Return the USB device IN endpoints interrupt. + * handle: PCD handle. + * return: Device IN endpoint interrupts. + */ +static uint32_t usb_dwc2_all_in_ep_int(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return ((mmio_read_32(usb_base_addr + OTG_DAINT) & + mmio_read_32(usb_base_addr + OTG_DAINTMSK)) & + OTG_DAINT_IN_MASK) >> OTG_DAINT_IN_SHIFT; +} + +/* + * Return Device OUT EP interrupt register. + * handle: PCD handle. + * epnum: Endpoint number. + * This parameter can be a value from 0 to 15. + * return: Device OUT EP Interrupt register. + */ +static uint32_t usb_dwc2_out_ep_int(void *handle, uint8_t epnum) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return mmio_read_32(usb_base_addr + OTG_DOEP_BASE + + (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT) & + mmio_read_32(usb_base_addr + OTG_DOEPMSK); +} + +/* + * Return Device IN EP interrupt register. + * handle: PCD handle. + * epnum: Endpoint number. + * This parameter can be a value from 0 to 15. + * return: Device IN EP Interrupt register. + */ +static uint32_t usb_dwc2_in_ep_int(void *handle, uint8_t epnum) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t msk; + uint32_t emp; + + msk = mmio_read_32(usb_base_addr + OTG_DIEPMSK); + emp = mmio_read_32(usb_base_addr + OTG_DIEPEMPMSK); + msk |= ((emp >> epnum) << OTG_DIEPINT_TXFE_SHIFT) & OTG_DIEPINT_TXFE; + + return mmio_read_32(usb_base_addr + OTG_DIEP_BASE + + (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT) & msk; +} + +/* + * Return USB core mode. + * handle: PCD handle. + * return: Core mode. + * This parameter can be 0 (host) or 1 (device). + */ +static uint32_t usb_dwc2_get_mode(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return mmio_read_32(usb_base_addr + OTG_GINTSTS) & OTG_GINTSTS_CMOD; +} + +/* + * Activate EP0 for detup transactions. + * handle: PCD handle. + * return: USB status. + */ +static enum usb_status usb_dwc2_activate_setup(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE; + + /* Set the MPS of the IN EP based on the enumeration speed */ + mmio_clrbits_32(reg_offset + OTG_DIEPCTL, OTG_DIEPCTL_MPSIZ); + + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_ENUMSPD_MASK) == + OTG_DSTS_ENUMSPD_LS_PHY_6MHZ) { + mmio_setbits_32(reg_offset + OTG_DIEPCTL, 3U); + } + + mmio_setbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_CGINAK); + + return USBD_OK; +} + +/* + * Prepare the EP0 to start the first control setup. + * handle: Selected device. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep0_out_start(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE + OTG_DIEPTSIZ; + uint32_t reg_value = 0U; + + /* PKTCNT = 1 and XFRSIZ = 24 bytes for endpoint 0 */ + reg_value |= OTG_DIEPTSIZ_PKTCNT_1; + reg_value |= (EP0_FIFO_SIZE & OTG_DIEPTSIZ_XFRSIZ); + reg_value |= OTG_DOEPTSIZ_RXDPID_STUPCNT; + + mmio_write_32(reg_offset, reg_value); + + return USBD_OK; +} + +/* + * Write a packet into the TX FIFO associated with the EP/channel. + * handle: Selected device. + * src: Pointer to source buffer. + * ch_ep_num: Endpoint or host channel number. + * len: Number of bytes to write. + * return: USB status. + */ +static enum usb_status usb_dwc2_write_packet(void *handle, uint8_t *src, + uint8_t ch_ep_num, uint16_t len) +{ + uint32_t reg_offset; + uint32_t count32b = (len + 3U) / 4U; + uint32_t i; + + reg_offset = (uintptr_t)handle + OTG_FIFO_BASE + + (ch_ep_num * OTG_FIFO_SIZE); + + for (i = 0U; i < count32b; i++) { + uint32_t src_copy = 0U; + uint32_t j; + + /* Data written to FIFO need to be 4 bytes aligned */ + for (j = 0U; j < 4U; j++) { + src_copy += (*(src + j)) << (8U * j); + } + + mmio_write_32(reg_offset, src_copy); + src += 4U; + } + + return USBD_OK; +} + +/* + * Read a packet from the RX FIFO associated with the EP/channel. + * handle: Selected device. + * dst: Destination pointer. + * len: Number of bytes to read. + * return: Pointer to destination buffer. + */ +static void *usb_dwc2_read_packet(void *handle, uint8_t *dest, uint16_t len) +{ + uint32_t reg_offset; + uint32_t count32b = (len + 3U) / 4U; + uint32_t i; + + VERBOSE("read packet length %i to 0x%lx\n", len, (uintptr_t)dest); + + reg_offset = (uintptr_t)handle + OTG_FIFO_BASE; + + for (i = 0U; i < count32b; i++) { + *(uint32_t *)dest = mmio_read_32(reg_offset); + dest += 4U; + dsb(); + } + + return (void *)dest; +} + +/* + * Setup and start a transfer over an EP. + * handle: Selected device + * ep: Pointer to endpoint structure. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep_start_xfer(void *handle, struct usbd_ep *ep) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + uint32_t reg_value; + uint32_t clear_value; + + if (ep->is_in) { + reg_offset = usb_base_addr + OTG_DIEP_BASE + (ep->num * OTG_DIEP_SIZE); + clear_value = OTG_DIEPTSIZ_PKTCNT | OTG_DIEPTSIZ_XFRSIZ; + if (ep->xfer_len == 0U) { + reg_value = OTG_DIEPTSIZ_PKTCNT_1; + } else { + /* + * Program the transfer size and packet count + * as follows: + * xfersize = N * maxpacket + short_packet + * pktcnt = N + (short_packet exist ? 1 : 0) + */ + reg_value = (OTG_DIEPTSIZ_PKTCNT & + (((ep->xfer_len + ep->maxpacket - 1U) / + ep->maxpacket) << OTG_DIEPTSIZ_PKTCNT_SHIFT)) + | ep->xfer_len; + + if (ep->type == EP_TYPE_ISOC) { + clear_value |= OTG_DIEPTSIZ_MCNT_MASK; + reg_value |= OTG_DIEPTSIZ_MCNT_DATA0; + } + } + + mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, clear_value, reg_value); + + if ((ep->type != EP_TYPE_ISOC) && (ep->xfer_len > 0U)) { + /* Enable the TX FIFO empty interrupt for this EP */ + mmio_setbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(ep->num)); + } + + /* EP enable, IN data in FIFO */ + reg_value = OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA; + + if (ep->type == EP_TYPE_ISOC) { + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) { + reg_value |= OTG_DIEPCTL_SODDFRM; + } else { + reg_value |= OTG_DIEPCTL_SD0PID_SEVNFRM; + } + } + + mmio_setbits_32(reg_offset + OTG_DIEPCTL, reg_value); + + if (ep->type == EP_TYPE_ISOC) { + usb_dwc2_write_packet(handle, ep->xfer_buff, ep->num, ep->xfer_len); + } + } else { + reg_offset = usb_base_addr + OTG_DOEP_BASE + (ep->num * OTG_DOEP_SIZE); + /* + * Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + if (ep->xfer_len == 0U) { + reg_value = ep->maxpacket | OTG_DIEPTSIZ_PKTCNT_1; + } else { + uint16_t pktcnt = (ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket; + + reg_value = (pktcnt << OTG_DIEPTSIZ_PKTCNT_SHIFT) | + (ep->maxpacket * pktcnt); + } + + mmio_clrsetbits_32(reg_offset + OTG_DOEPTSIZ, + OTG_DOEPTSIZ_XFRSIZ & OTG_DOEPTSIZ_PKTCNT, + reg_value); + + /* EP enable */ + reg_value = OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA; + + if (ep->type == EP_TYPE_ISOC) { + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) { + reg_value |= OTG_DOEPCTL_SD1PID_SODDFRM; + } else { + reg_value |= OTG_DOEPCTL_SD0PID_SEVNFRM; + } + } + + mmio_setbits_32(reg_offset + OTG_DOEPCTL, reg_value); + } + + return USBD_OK; +} + +/* + * Setup and start a transfer over the EP0. + * handle: Selected device. + * ep: Pointer to endpoint structure. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep0_start_xfer(void *handle, struct usbd_ep *ep) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + uint32_t reg_value; + + if (ep->is_in) { + reg_offset = usb_base_addr + OTG_DIEP_BASE + + (ep->num * OTG_DIEP_SIZE); + + if (ep->xfer_len == 0U) { + reg_value = OTG_DIEPTSIZ_PKTCNT_1; + } else { + /* + * Program the transfer size and packet count + * as follows: + * xfersize = N * maxpacket + short_packet + * pktcnt = N + (short_packet exist ? 1 : 0) + */ + + if (ep->xfer_len > ep->maxpacket) { + ep->xfer_len = ep->maxpacket; + } + + reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->xfer_len; + } + + mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, + OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT, + reg_value); + + /* Enable the TX FIFO empty interrupt for this EP */ + if (ep->xfer_len > 0U) { + mmio_setbits_32(usb_base_addr + OTG_DIEPEMPMSK, + BIT(ep->num)); + } + + /* EP enable, IN data in FIFO */ + mmio_setbits_32(reg_offset + OTG_DIEPCTL, + OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA); + } else { + reg_offset = usb_base_addr + OTG_DOEP_BASE + + (ep->num * OTG_DOEP_SIZE); + + /* + * Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + if (ep->xfer_len > 0U) { + ep->xfer_len = ep->maxpacket; + } + + reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->maxpacket; + + mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, + OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT, + reg_value); + + /* EP enable */ + mmio_setbits_32(reg_offset + OTG_DOEPCTL, + OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA); + } + + return USBD_OK; +} + +/* + * Set a stall condition over an EP. + * handle: Selected device. + * ep: Pointer to endpoint structure. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep_set_stall(void *handle, struct usbd_ep *ep) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + uint32_t reg_value; + + if (ep->is_in) { + reg_offset = usb_base_addr + OTG_DIEP_BASE + + (ep->num * OTG_DIEP_SIZE); + reg_value = mmio_read_32(reg_offset + OTG_DIEPCTL); + + if ((reg_value & OTG_DIEPCTL_EPENA) == 0U) { + reg_value &= ~OTG_DIEPCTL_EPDIS; + } + + reg_value |= OTG_DIEPCTL_STALL; + + mmio_write_32(reg_offset + OTG_DIEPCTL, reg_value); + } else { + reg_offset = usb_base_addr + OTG_DOEP_BASE + + (ep->num * OTG_DOEP_SIZE); + reg_value = mmio_read_32(reg_offset + OTG_DOEPCTL); + + if ((reg_value & OTG_DOEPCTL_EPENA) == 0U) { + reg_value &= ~OTG_DOEPCTL_EPDIS; + } + + reg_value |= OTG_DOEPCTL_STALL; + + mmio_write_32(reg_offset + OTG_DOEPCTL, reg_value); + } + + return USBD_OK; +} + +/* + * Stop the USB device mode. + * handle: Selected device. + * return: USB status. + */ +static enum usb_status usb_dwc2_stop_device(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t i; + + /* Disable Int */ + mmio_clrbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT); + + /* Clear pending interrupts */ + for (i = 0U; i < EP_NB; i++) { + mmio_write_32(usb_base_addr + OTG_DIEP_BASE + (i * OTG_DIEP_SIZE) + OTG_DIEPINT, + OTG_DIEPINT_MASK); + mmio_write_32(usb_base_addr + OTG_DOEP_BASE + (i * OTG_DOEP_SIZE) + OTG_DOEPINT, + OTG_DOEPINT_MASK); + } + + mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK); + + /* Clear interrupt masks */ + mmio_write_32(usb_base_addr + OTG_DIEPMSK, 0U); + mmio_write_32(usb_base_addr + OTG_DOEPMSK, 0U); + mmio_write_32(usb_base_addr + OTG_DAINTMSK, 0U); + + /* Flush the FIFO */ + usb_dwc2_flush_rx_fifo(handle); + usb_dwc2_flush_tx_fifo(handle, EP_ALL); + + /* Disconnect the USB device by disabling the pull-up/pull-down */ + mmio_setbits_32((uintptr_t)handle + OTG_DCTL, OTG_DCTL_SDIS); + + return USBD_OK; +} + +/* + * Stop the USB device mode. + * handle: Selected device. + * address: New device address to be assigned. + * This parameter can be a value from 0 to 255. + * return: USB status. + */ +static enum usb_status usb_dwc2_set_address(void *handle, uint8_t address) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + mmio_clrsetbits_32(usb_base_addr + OTG_DCFG, + OTG_DCFG_DAD, + address << OTG_DCFG_DAD_SHIFT); + + return USBD_OK; +} + +/* + * Check FIFO for the next packet to be loaded. + * handle: Selected device. + * epnum : Endpoint number. + * xfer_len: Block length. + * xfer_count: Number of blocks. + * maxpacket: Max packet length. + * xfer_buff: Buffer pointer. + * return: USB status. + */ +static enum usb_status usb_dwc2_write_empty_tx_fifo(void *handle, + uint32_t epnum, + uint32_t xfer_len, + uint32_t *xfer_count, + uint32_t maxpacket, + uint8_t **xfer_buff) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + int32_t len; + uint32_t len32b; + enum usb_status ret; + + len = xfer_len - *xfer_count; + + if ((len > 0) && ((uint32_t)len > maxpacket)) { + len = maxpacket; + } + + len32b = (len + 3U) / 4U; + + reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE); + + while (((mmio_read_32(reg_offset + OTG_DTXFSTS) & + OTG_DTXFSTS_INEPTFSAV) > len32b) && + (*xfer_count < xfer_len) && (xfer_len != 0U)) { + /* Write the FIFO */ + len = xfer_len - *xfer_count; + + if ((len > 0) && ((uint32_t)len > maxpacket)) { + len = maxpacket; + } + + len32b = (len + 3U) / 4U; + + ret = usb_dwc2_write_packet(handle, *xfer_buff, epnum, len); + if (ret != USBD_OK) { + return ret; + } + + *xfer_buff += len; + *xfer_count += len; + } + + if (len <= 0) { + mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum)); + } + + return USBD_OK; +} + +/* + * Handle PCD interrupt request. + * handle: PCD handle. + * param: Pointer to information updated by the IT handling. + * return: Action to do after IT handling. + */ +static enum usb_action usb_dwc2_it_handler(void *handle, uint32_t *param) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t ep_intr; + uint32_t epint; + uint32_t epnum; + uint32_t temp; + enum usb_status ret; + + if (usb_dwc2_get_mode(handle) != USB_OTG_MODE_DEVICE) { + return USB_NOTHING; + } + + /* Avoid spurious interrupt */ + if (usb_dwc2_read_int(handle) == 0U) { + return USB_NOTHING; + } + + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_MMIS) != 0U) { + /* Incorrect mode, acknowledge the interrupt */ + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_MMIS); + } + + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OEPINT) != 0U) { + uint32_t reg_offset; + + /* Read in the device interrupt bits */ + ep_intr = usb_dwc2_all_out_ep_int(handle); + epnum = 0U; + while ((ep_intr & BIT(0)) != BIT(0)) { + epnum++; + ep_intr >>= 1; + } + + reg_offset = usb_base_addr + OTG_DOEP_BASE + (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT; + + epint = usb_dwc2_out_ep_int(handle, epnum); + + if ((epint & OTG_DOEPINT_XFRC) == OTG_DOEPINT_XFRC) { + mmio_write_32(reg_offset, OTG_DOEPINT_XFRC); + *param = epnum; + + return USB_DATA_OUT; + } + + if ((epint & OTG_DOEPINT_STUP) == OTG_DOEPINT_STUP) { + /* Inform that a setup packet is available */ + mmio_write_32(reg_offset, OTG_DOEPINT_STUP); + + return USB_SETUP; + } + + if ((epint & OTG_DOEPINT_OTEPDIS) == OTG_DOEPINT_OTEPDIS) { + mmio_write_32(reg_offset, OTG_DOEPINT_OTEPDIS); + } + } + + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IEPINT) != 0U) { + uint32_t reg_offset; + + /* Read in the device interrupt bits */ + ep_intr = usb_dwc2_all_in_ep_int(handle); + epnum = 0U; + while ((ep_intr & BIT(0)) != BIT(0)) { + epnum++; + ep_intr >>= 1; + } + + reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT; + + epint = usb_dwc2_in_ep_int(handle, epnum); + + if ((epint & OTG_DIEPINT_XFRC) == OTG_DIEPINT_XFRC) { + mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum)); + mmio_write_32(reg_offset, OTG_DIEPINT_XFRC); + *param = epnum; + + return USB_DATA_IN; + } + + if ((epint & OTG_DIEPINT_TOC) == OTG_DIEPINT_TOC) { + mmio_write_32(reg_offset, OTG_DIEPINT_TOC); + } + + if ((epint & OTG_DIEPINT_ITTXFE) == OTG_DIEPINT_ITTXFE) { + mmio_write_32(reg_offset, OTG_DIEPINT_ITTXFE); + } + + if ((epint & OTG_DIEPINT_INEPNE) == OTG_DIEPINT_INEPNE) { + mmio_write_32(reg_offset, OTG_DIEPINT_INEPNE); + } + + if ((epint & OTG_DIEPINT_EPDISD) == OTG_DIEPINT_EPDISD) { + mmio_write_32(reg_offset, OTG_DIEPINT_EPDISD); + } + + if ((epint & OTG_DIEPINT_TXFE) == OTG_DIEPINT_TXFE) { + *param = epnum; + + return USB_WRITE_EMPTY; + } + } + + /* Handle resume interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_WKUPINT) != 0U) { + INFO("handle USB : Resume\n"); + + /* Clear the remote wake-up signaling */ + mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG); + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_WKUPINT); + + return USB_RESUME; + } + + /* Handle suspend interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBSUSP) != 0U) { + INFO("handle USB : Suspend int\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBSUSP); + + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & + OTG_DSTS_SUSPSTS) == OTG_DSTS_SUSPSTS) { + return USB_SUSPEND; + } + } + + /* Handle LPM interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_LPMINT) != 0U) { + INFO("handle USB : LPM int enter in suspend\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_LPMINT); + *param = (mmio_read_32(usb_base_addr + OTG_GLPMCFG) & + OTG_GLPMCFG_BESL) >> 2; + + return USB_LPM; + } + + /* Handle reset interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBRST) != 0U) { + INFO("handle USB : Reset\n"); + + mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG); + + usb_dwc2_flush_tx_fifo(handle, 0U); + + mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK); + mmio_setbits_32(usb_base_addr + OTG_DAINTMSK, OTG_DAINT_EP0_IN | OTG_DAINT_EP0_OUT); + + mmio_setbits_32(usb_base_addr + OTG_DOEPMSK, OTG_DOEPMSK_STUPM | + OTG_DOEPMSK_XFRCM | + OTG_DOEPMSK_EPDM); + mmio_setbits_32(usb_base_addr + OTG_DIEPMSK, OTG_DIEPMSK_TOM | + OTG_DIEPMSK_XFRCM | + OTG_DIEPMSK_EPDM); + + /* Set default address to 0 */ + mmio_clrbits_32(usb_base_addr + OTG_DCFG, OTG_DCFG_DAD); + + /* Setup EP0 to receive SETUP packets */ + ret = usb_dwc2_ep0_out_start(handle); + if (ret != USBD_OK) { + return ret; + } + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBRST); + + return USB_RESET; + } + + /* Handle enumeration done interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_ENUMDNE) != 0U) { + ret = usb_dwc2_activate_setup(handle); + if (ret != USBD_OK) { + return ret; + } + + mmio_clrbits_32(usb_base_addr + OTG_GUSBCFG, OTG_GUSBCFG_TRDT); + + mmio_setbits_32(usb_base_addr + OTG_GUSBCFG, + (USBD_HS_TRDT_VALUE << OTG_GUSBCFG_TRDT_SHIFT) & OTG_GUSBCFG_TRDT); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_ENUMDNE); + + return USB_ENUM_DONE; + } + + /* Handle RXQLevel interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_RXFLVL) != 0U) { + mmio_clrbits_32(usb_base_addr + OTG_GINTMSK, + OTG_GINTSTS_RXFLVL); + + temp = mmio_read_32(usb_base_addr + OTG_GRXSTSP); + + *param = temp & OTG_GRXSTSP_EPNUM; + *param |= (temp & OTG_GRXSTSP_BCNT) << (USBD_OUT_COUNT_SHIFT - + OTG_GRXSTSP_BCNT_SHIFT); + + if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) == STS_DATA_UPDT) { + if ((temp & OTG_GRXSTSP_BCNT) != 0U) { + mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); + + return USB_READ_DATA_PACKET; + } + } else if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) == + STS_SETUP_UPDT) { + mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); + + return USB_READ_SETUP_PACKET; + } + + mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); + } + + /* Handle SOF interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SOF) != 0U) { + INFO("handle USB : SOF\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SOF); + + return USB_SOF; + } + + /* Handle incomplete ISO IN interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IISOIXFR) != 0U) { + INFO("handle USB : ISO IN\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, + OTG_GINTSTS_IISOIXFR); + } + + /* Handle incomplete ISO OUT interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IPXFR_INCOMPISOOUT) != + 0U) { + INFO("handle USB : ISO OUT\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, + OTG_GINTSTS_IPXFR_INCOMPISOOUT); + } + + /* Handle connection event interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SRQINT) != 0U) { + INFO("handle USB : Connect\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SRQINT); + } + + /* Handle disconnection event interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OTGINT) != 0U) { + INFO("handle USB : Disconnect\n"); + + temp = mmio_read_32(usb_base_addr + OTG_GOTGINT); + + if ((temp & OTG_GOTGINT_SEDET) == OTG_GOTGINT_SEDET) { + return USB_DISCONNECT; + } + } + + return USB_NOTHING; +} + +/* + * Start the usb device mode + * usb_core_handle: USB core driver handle. + * return USB status. + */ +static enum usb_status usb_dwc2_start_device(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_SDIS); + mmio_setbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT); + + return USBD_OK; +} + +static const struct usb_driver usb_dwc2driver = { + .ep0_out_start = usb_dwc2_ep0_out_start, + .ep_start_xfer = usb_dwc2_ep_start_xfer, + .ep0_start_xfer = usb_dwc2_ep0_start_xfer, + .write_packet = usb_dwc2_write_packet, + .read_packet = usb_dwc2_read_packet, + .ep_set_stall = usb_dwc2_ep_set_stall, + .start_device = usb_dwc2_start_device, + .stop_device = usb_dwc2_stop_device, + .set_address = usb_dwc2_set_address, + .write_empty_tx_fifo = usb_dwc2_write_empty_tx_fifo, + .it_handler = usb_dwc2_it_handler +}; + +/* + * Initialize USB DWC2 driver. + * usb_core_handle: USB core driver handle. + * pcd_handle: PCD handle. + * base_register: USB global register base address. + */ +void stm32mp1_usb_init_driver(struct usb_handle *usb_core_handle, + struct pcd_handle *pcd_handle, + void *base_register) +{ + register_usb_driver(usb_core_handle, pcd_handle, &usb_dwc2driver, + base_register); +} diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 6dbf37236..ae42e326f 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -34,6 +34,9 @@ int ufshc_send_uic_cmd(uintptr_t base, uic_cmd_t *cmd) { unsigned int data; + if (base == 0 || cmd == NULL) + return -EINVAL; + data = mmio_read_32(base + HCS); if ((data & HCS_UCRDY) == 0) return -EBUSY; @@ -54,9 +57,13 @@ int ufshc_dme_get(unsigned int attr, unsigned int idx, unsigned int *val) { uintptr_t base; unsigned int data; - int retries; + int result, retries; + uic_cmd_t cmd; + + assert(ufs_params.reg_base != 0); - assert((ufs_params.reg_base != 0) && (val != NULL)); + if (val == NULL) + return -EINVAL; base = ufs_params.reg_base; for (retries = 0; retries < 100; retries++) { @@ -68,19 +75,20 @@ int ufshc_dme_get(unsigned int attr, unsigned int idx, unsigned int *val) if (retries >= 100) return -EBUSY; - mmio_write_32(base + IS, ~0); - mmio_write_32(base + UCMDARG1, (attr << 16) | GEN_SELECTOR_IDX(idx)); - mmio_write_32(base + UCMDARG2, 0); - mmio_write_32(base + UCMDARG3, 0); - mmio_write_32(base + UICCMD, DME_GET); - do { + cmd.arg1 = (attr << 16) | GEN_SELECTOR_IDX(idx); + cmd.arg2 = 0; + cmd.arg3 = 0; + cmd.op = DME_GET; + for (retries = 0; retries < UFS_UIC_COMMAND_RETRIES; ++retries) { + result = ufshc_send_uic_cmd(base, &cmd); + if (result == 0) + break; data = mmio_read_32(base + IS); if (data & UFS_INT_UE) return -EINVAL; - } while ((data & UFS_INT_UCCS) == 0); - mmio_write_32(base + IS, UFS_INT_UCCS); - data = mmio_read_32(base + UCMDARG2) & CONFIG_RESULT_CODE_MASK; - assert(data == 0); + } + if (retries >= UFS_UIC_COMMAND_RETRIES) + return -EIO; *val = mmio_read_32(base + UCMDARG3); return 0; @@ -90,58 +98,101 @@ int ufshc_dme_set(unsigned int attr, unsigned int idx, unsigned int val) { uintptr_t base; unsigned int data; + int result, retries; + uic_cmd_t cmd; assert((ufs_params.reg_base != 0)); base = ufs_params.reg_base; - data = mmio_read_32(base + HCS); - if ((data & HCS_UCRDY) == 0) - return -EBUSY; - mmio_write_32(base + IS, ~0); - mmio_write_32(base + UCMDARG1, (attr << 16) | GEN_SELECTOR_IDX(idx)); - mmio_write_32(base + UCMDARG2, 0); - mmio_write_32(base + UCMDARG3, val); - mmio_write_32(base + UICCMD, DME_SET); - do { + cmd.arg1 = (attr << 16) | GEN_SELECTOR_IDX(idx); + cmd.arg2 = 0; + cmd.arg3 = val; + cmd.op = DME_SET; + + for (retries = 0; retries < UFS_UIC_COMMAND_RETRIES; ++retries) { + result = ufshc_send_uic_cmd(base, &cmd); + if (result == 0) + break; data = mmio_read_32(base + IS); if (data & UFS_INT_UE) return -EINVAL; - } while ((data & UFS_INT_UCCS) == 0); - mmio_write_32(base + IS, UFS_INT_UCCS); - data = mmio_read_32(base + UCMDARG2) & CONFIG_RESULT_CODE_MASK; - assert(data == 0); + } + if (retries >= UFS_UIC_COMMAND_RETRIES) + return -EIO; + return 0; } -static void ufshc_reset(uintptr_t base) +static int ufshc_hce_enable(uintptr_t base) { unsigned int data; + int retries; /* Enable Host Controller */ mmio_write_32(base + HCE, HCE_ENABLE); + /* Wait until basic initialization sequence completed */ - do { + for (retries = 0; retries < HCE_ENABLE_INNER_RETRIES; ++retries) { data = mmio_read_32(base + HCE); - } while ((data & HCE_ENABLE) == 0); + if (data & HCE_ENABLE) { + break; + } + udelay(HCE_ENABLE_TIMEOUT_US); + } + if (retries >= HCE_ENABLE_INNER_RETRIES) { + return -ETIMEDOUT; + } + + return 0; +} + +static int ufshc_reset(uintptr_t base) +{ + unsigned int data; + int retries, result; + + for (retries = 0; retries < HCE_ENABLE_OUTER_RETRIES; ++retries) { + result = ufshc_hce_enable(base); + if (result == 0) { + break; + } + } + if (retries >= HCE_ENABLE_OUTER_RETRIES) { + return -EIO; + } /* Enable Interrupts */ data = UFS_INT_UCCS | UFS_INT_ULSS | UFS_INT_UE | UFS_INT_UTPES | UFS_INT_DFES | UFS_INT_HCFES | UFS_INT_SBFES; mmio_write_32(base + IE, data); + + return 0; } -static int ufshc_link_startup(uintptr_t base) +static int ufshc_dme_link_startup(uintptr_t base) { uic_cmd_t cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.op = DME_LINKSTARTUP; + return ufshc_send_uic_cmd(base, &cmd); +} + +static int ufshc_link_startup(uintptr_t base) +{ int data, result; int retries; - for (retries = 10; retries > 0; retries--) { - memset(&cmd, 0, sizeof(cmd)); - cmd.op = DME_LINKSTARTUP; - result = ufshc_send_uic_cmd(base, &cmd); - if (result != 0) + for (retries = DME_LINKSTARTUP_RETRIES; retries > 0; retries--) { + result = ufshc_dme_link_startup(base); + if (result != 0) { + /* Reset controller before trying again */ + result = ufshc_reset(base); + if (result != 0) { + return result; + } continue; + } while ((mmio_read_32(base + HCS) & HCS_DP) == 0) ; data = mmio_read_32(base + IS); @@ -772,7 +823,8 @@ int ufs_init(const ufs_ops_t *ops, ufs_params_t *params) assert((ops != NULL) && (ops->phy_init != NULL) && (ops->phy_set_pwr_mode != NULL)); - ufshc_reset(ufs_params.reg_base); + result = ufshc_reset(ufs_params.reg_base); + assert(result == 0); ops->phy_init(&ufs_params); result = ufshc_link_startup(ufs_params.reg_base); assert(result == 0); diff --git a/drivers/usb/usb_device.c b/drivers/usb/usb_device.c new file mode 100644 index 000000000..031e67846 --- /dev/null +++ b/drivers/usb/usb_device.c @@ -0,0 +1,845 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdint.h> + +#include <common/debug.h> +#include <drivers/usb_device.h> + +/* Define for EP address */ +#define EP_DIR_MASK BIT(7) +#define EP_DIR_IN BIT(7) +#define EP_NUM_MASK GENMASK(3, 0) + +#define EP0_IN (0U | EP_DIR_IN) +#define EP0_OUT 0U + +/* USB address between 1 through 127 = 0x7F mask */ +#define ADDRESS_MASK GENMASK(6, 0) + +/* + * Set a STALL condition over an endpoint + * pdev: USB handle + * ep_addr: endpoint address + * return : status + */ +static enum usb_status usb_core_set_stall(struct usb_handle *pdev, uint8_t ep_addr) +{ + struct usbd_ep *ep; + struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data; + uint8_t num; + + num = ep_addr & EP_NUM_MASK; + if (num >= USBD_EP_NB) { + return USBD_FAIL; + } + if ((EP_DIR_MASK & ep_addr) == EP_DIR_IN) { + ep = &hpcd->in_ep[num]; + ep->is_in = true; + } else { + ep = &hpcd->out_ep[num]; + ep->is_in = false; + } + ep->num = num; + + pdev->driver->ep_set_stall(hpcd->instance, ep); + if (num == 0U) { + pdev->driver->ep0_out_start(hpcd->instance); + } + + return USBD_OK; +} + +/* + * usb_core_get_desc + * Handle Get Descriptor requests + * pdev : device instance + * req : usb request + */ +static void usb_core_get_desc(struct usb_handle *pdev, struct usb_setup_req *req) +{ + uint16_t len; + uint8_t *pbuf; + uint8_t desc_type = HIBYTE(req->value); + uint8_t desc_idx = LOBYTE(req->value); + + switch (desc_type) { + case USB_DESC_TYPE_DEVICE: + pbuf = pdev->desc->get_device_desc(&len); + break; + + case USB_DESC_TYPE_CONFIGURATION: + pbuf = pdev->desc->get_config_desc(&len); + break; + + case USB_DESC_TYPE_STRING: + switch (desc_idx) { + case USBD_IDX_LANGID_STR: + pbuf = pdev->desc->get_lang_id_desc(&len); + break; + + case USBD_IDX_MFC_STR: + pbuf = pdev->desc->get_manufacturer_desc(&len); + break; + + case USBD_IDX_PRODUCT_STR: + pbuf = pdev->desc->get_product_desc(&len); + break; + + case USBD_IDX_SERIAL_STR: + pbuf = pdev->desc->get_serial_desc(&len); + break; + + case USBD_IDX_CONFIG_STR: + pbuf = pdev->desc->get_configuration_desc(&len); + break; + + case USBD_IDX_INTERFACE_STR: + pbuf = pdev->desc->get_interface_desc(&len); + break; + + /* For all USER string */ + case USBD_IDX_USER0_STR: + default: + pbuf = pdev->desc->get_usr_desc(desc_idx - USBD_IDX_USER0_STR, &len); + break; + } + break; + + case USB_DESC_TYPE_DEVICE_QUALIFIER: + pbuf = pdev->desc->get_device_qualifier_desc(&len); + break; + + case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: + if (pdev->desc->get_other_speed_config_desc == NULL) { + usb_core_ctl_error(pdev); + return; + } + pbuf = pdev->desc->get_other_speed_config_desc(&len); + break; + + default: + ERROR("Unknown request %i\n", desc_type); + usb_core_ctl_error(pdev); + return; + } + + if ((len != 0U) && (req->length != 0U)) { + len = MIN(len, req->length); + + /* Start the transfer */ + usb_core_transmit_ep0(pdev, pbuf, len); + } +} + +/* + * usb_core_set_config + * Handle Set device configuration request + * pdev : device instance + * req : usb request + */ +static void usb_core_set_config(struct usb_handle *pdev, struct usb_setup_req *req) +{ + static uint8_t cfgidx; + + cfgidx = LOBYTE(req->value); + + if (cfgidx > USBD_MAX_NUM_CONFIGURATION) { + usb_core_ctl_error(pdev); + return; + } + + switch (pdev->dev_state) { + case USBD_STATE_ADDRESSED: + if (cfgidx != 0U) { + pdev->dev_config = cfgidx; + pdev->dev_state = USBD_STATE_CONFIGURED; + if (!pdev->class) { + usb_core_ctl_error(pdev); + return; + } + /* Set configuration and Start the Class */ + if (pdev->class->init(pdev, cfgidx) != 0U) { + usb_core_ctl_error(pdev); + return; + } + } + break; + + case USBD_STATE_CONFIGURED: + if (cfgidx == 0U) { + pdev->dev_state = USBD_STATE_ADDRESSED; + pdev->dev_config = cfgidx; + pdev->class->de_init(pdev, cfgidx); + } else if (cfgidx != pdev->dev_config) { + if (pdev->class == NULL) { + usb_core_ctl_error(pdev); + return; + } + /* Clear old configuration */ + pdev->class->de_init(pdev, pdev->dev_config); + /* Set new configuration */ + pdev->dev_config = cfgidx; + /* Set configuration and start the USB class */ + if (pdev->class->init(pdev, cfgidx) != 0U) { + usb_core_ctl_error(pdev); + return; + } + } + break; + + default: + usb_core_ctl_error(pdev); + return; + } + + /* Send status */ + usb_core_transmit_ep0(pdev, NULL, 0U); +} + +/* + * usb_core_get_status + * Handle Get Status request + * pdev : device instance + * req : usb request + */ +static void usb_core_get_status(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + if ((pdev->dev_state != USBD_STATE_ADDRESSED) && + (pdev->dev_state != USBD_STATE_CONFIGURED)) { + usb_core_ctl_error(pdev); + return; + } + + pdev->dev_config_status = USB_CONFIG_SELF_POWERED; + + if (pdev->dev_remote_wakeup != 0U) { + pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP; + } + + /* Start the transfer */ + usb_core_transmit_ep0(pdev, (uint8_t *)&pdev->dev_config_status, 2U); +} + +/* + * usb_core_set_address + * Set device address + * pdev : device instance + * req : usb request + */ +static void usb_core_set_address(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + uint8_t dev_addr; + + if ((req->index != 0U) || (req->length != 0U)) { + usb_core_ctl_error(pdev); + return; + } + + dev_addr = req->value & ADDRESS_MASK; + if (pdev->dev_state != USBD_STATE_DEFAULT) { + usb_core_ctl_error(pdev); + return; + } + + pdev->dev_address = dev_addr; + pdev->driver->set_address(((struct pcd_handle *)(pdev->data))->instance, dev_addr); + + /* Send status */ + usb_core_transmit_ep0(pdev, NULL, 0U); + + if (dev_addr != 0U) { + pdev->dev_state = USBD_STATE_ADDRESSED; + } else { + pdev->dev_state = USBD_STATE_DEFAULT; + } +} + +/* + * usb_core_dev_req + * Handle standard usb device requests + * pdev : device instance + * req : usb request + * return : status + */ +static enum usb_status usb_core_dev_req(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + VERBOSE("receive request %i\n", req->b_request); + switch (req->b_request) { + case USB_REQ_GET_DESCRIPTOR: + usb_core_get_desc(pdev, req); + break; + + case USB_REQ_SET_CONFIGURATION: + usb_core_set_config(pdev, req); + break; + + case USB_REQ_GET_STATUS: + usb_core_get_status(pdev, req); + break; + + case USB_REQ_SET_ADDRESS: + usb_core_set_address(pdev, req); + break; + + case USB_REQ_GET_CONFIGURATION: + case USB_REQ_SET_FEATURE: + case USB_REQ_CLEAR_FEATURE: + default: + ERROR("NOT SUPPORTED %i\n", req->b_request); + usb_core_ctl_error(pdev); + break; + } + + return USBD_OK; +} + +/* + * usb_core_itf_req + * Handle standard usb interface requests + * pdev : device instance + * req : usb request + * return : status + */ +static enum usb_status usb_core_itf_req(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + if (pdev->dev_state != USBD_STATE_CONFIGURED) { + usb_core_ctl_error(pdev); + return USBD_OK; + } + + if (LOBYTE(req->index) <= USBD_MAX_NUM_INTERFACES) { + pdev->class->setup(pdev, req); + + if (req->length == 0U) { + usb_core_transmit_ep0(pdev, NULL, 0U); + } + } else { + usb_core_ctl_error(pdev); + } + + return USBD_OK; +} + +/* + * usb_core_setup_stage + * Handle the setup stage + * pdev: device instance + * psetup : setup buffer + * return : status + */ +static enum usb_status usb_core_setup_stage(struct usb_handle *pdev, + uint8_t *psetup) +{ + struct usb_setup_req *req = &pdev->request; + + /* Copy setup buffer into req structure */ + req->bm_request = psetup[0]; + req->b_request = psetup[1]; + req->value = psetup[2] + (psetup[3] << 8); + req->index = psetup[4] + (psetup[5] << 8); + req->length = psetup[6] + (psetup[7] << 8); + + pdev->ep0_state = USBD_EP0_SETUP; + pdev->ep0_data_len = pdev->request.length; + + switch (pdev->request.bm_request & USB_REQ_RECIPIENT_MASK) { + case USB_REQ_RECIPIENT_DEVICE: + usb_core_dev_req(pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_INTERFACE: + usb_core_itf_req(pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_ENDPOINT: + default: + ERROR("receive unsupported request %i", + pdev->request.bm_request & USB_REQ_RECIPIENT_MASK); + usb_core_set_stall(pdev, pdev->request.bm_request & USB_REQ_DIRECTION); + return USBD_FAIL; + } + + return USBD_OK; +} + +/* + * usb_core_data_out + * Handle data OUT stage + * pdev: device instance + * epnum: endpoint index + * pdata: buffer to sent + * return : status + */ +static enum usb_status usb_core_data_out(struct usb_handle *pdev, uint8_t epnum, + uint8_t *pdata) +{ + struct usb_endpoint *pep; + + if (epnum == 0U) { + pep = &pdev->ep_out[0]; + if (pdev->ep0_state == USBD_EP0_DATA_OUT) { + if (pep->rem_length > pep->maxpacket) { + pep->rem_length -= pep->maxpacket; + + usb_core_receive(pdev, 0U, pdata, + MIN(pep->rem_length, + pep->maxpacket)); + } else { + if (pdev->class->ep0_rx_ready && + (pdev->dev_state == USBD_STATE_CONFIGURED)) { + pdev->class->ep0_rx_ready(pdev); + } + + usb_core_transmit_ep0(pdev, NULL, 0U); + } + } + } else if (pdev->class->data_out != NULL && + (pdev->dev_state == USBD_STATE_CONFIGURED)) { + pdev->class->data_out(pdev, epnum); + } + + return USBD_OK; +} + +/* + * usb_core_data_in + * Handle data in stage + * pdev: device instance + * epnum: endpoint index + * pdata: buffer to fill + * return : status + */ +static enum usb_status usb_core_data_in(struct usb_handle *pdev, uint8_t epnum, + uint8_t *pdata) +{ + if (epnum == 0U) { + struct usb_endpoint *pep = &pdev->ep_in[0]; + + if (pdev->ep0_state == USBD_EP0_DATA_IN) { + if (pep->rem_length > pep->maxpacket) { + pep->rem_length -= pep->maxpacket; + + usb_core_transmit(pdev, 0U, pdata, + pep->rem_length); + + /* Prepare EP for premature end of transfer */ + usb_core_receive(pdev, 0U, NULL, 0U); + } else { + /* Last packet is MPS multiple, send ZLP packet */ + if ((pep->total_length % pep->maxpacket == 0U) && + (pep->total_length >= pep->maxpacket) && + (pep->total_length < pdev->ep0_data_len)) { + usb_core_transmit(pdev, 0U, NULL, 0U); + + pdev->ep0_data_len = 0U; + + /* Prepare endpoint for premature end of transfer */ + usb_core_receive(pdev, 0U, NULL, 0U); + } else { + if (pdev->class->ep0_tx_sent != NULL && + (pdev->dev_state == + USBD_STATE_CONFIGURED)) { + pdev->class->ep0_tx_sent(pdev); + } + /* Start the transfer */ + usb_core_receive_ep0(pdev, NULL, 0U); + } + } + } + } else if ((pdev->class->data_in != NULL) && + (pdev->dev_state == USBD_STATE_CONFIGURED)) { + pdev->class->data_in(pdev, epnum); + } + + return USBD_OK; +} + +/* + * usb_core_suspend + * Handle suspend event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_suspend(struct usb_handle *pdev) +{ + INFO("USB Suspend mode\n"); + pdev->dev_old_state = pdev->dev_state; + pdev->dev_state = USBD_STATE_SUSPENDED; + + return USBD_OK; +} + +/* + * usb_core_resume + * Handle resume event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_resume(struct usb_handle *pdev) +{ + INFO("USB Resume\n"); + pdev->dev_state = pdev->dev_old_state; + + return USBD_OK; +} + +/* + * usb_core_sof + * Handle SOF event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_sof(struct usb_handle *pdev) +{ + if (pdev->dev_state == USBD_STATE_CONFIGURED) { + if (pdev->class->sof != NULL) { + pdev->class->sof(pdev); + } + } + + return USBD_OK; +} + +/* + * usb_core_disconnect + * Handle device disconnection event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_disconnect(struct usb_handle *pdev) +{ + /* Free class resources */ + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->class->de_init(pdev, pdev->dev_config); + + return USBD_OK; +} + +enum usb_status usb_core_handle_it(struct usb_handle *pdev) +{ + uint32_t param = 0U; + uint32_t len = 0U; + struct usbd_ep *ep; + + switch (pdev->driver->it_handler(pdev->data->instance, ¶m)) { + case USB_DATA_OUT: + usb_core_data_out(pdev, param, + pdev->data->out_ep[param].xfer_buff); + break; + + case USB_DATA_IN: + usb_core_data_in(pdev, param, + pdev->data->in_ep[param].xfer_buff); + break; + + case USB_SETUP: + usb_core_setup_stage(pdev, (uint8_t *)pdev->data->setup); + break; + + case USB_ENUM_DONE: + break; + + case USB_READ_DATA_PACKET: + ep = &pdev->data->out_ep[param & USBD_OUT_EPNUM_MASK]; + len = (param & USBD_OUT_COUNT_MASK) >> USBD_OUT_COUNT_SHIFT; + pdev->driver->read_packet(pdev->data->instance, + ep->xfer_buff, len); + ep->xfer_buff += len; + ep->xfer_count += len; + break; + + case USB_READ_SETUP_PACKET: + ep = &pdev->data->out_ep[param & USBD_OUT_EPNUM_MASK]; + len = (param & USBD_OUT_COUNT_MASK) >> 0x10; + pdev->driver->read_packet(pdev->data->instance, + (uint8_t *)pdev->data->setup, 8); + ep->xfer_count += len; + break; + + case USB_RESET: + pdev->dev_state = USBD_STATE_DEFAULT; + break; + + case USB_RESUME: + if (pdev->data->lpm_state == LPM_L1) { + pdev->data->lpm_state = LPM_L0; + } else { + usb_core_resume(pdev); + } + break; + + case USB_SUSPEND: + usb_core_suspend(pdev); + break; + + case USB_LPM: + if (pdev->data->lpm_state == LPM_L0) { + pdev->data->lpm_state = LPM_L1; + } else { + usb_core_suspend(pdev); + } + break; + + case USB_SOF: + usb_core_sof(pdev); + break; + + case USB_DISCONNECT: + usb_core_disconnect(pdev); + break; + + case USB_WRITE_EMPTY: + pdev->driver->write_empty_tx_fifo(pdev->data->instance, param, + pdev->data->in_ep[param].xfer_len, + (uint32_t *)&pdev->data->in_ep[param].xfer_count, + pdev->data->in_ep[param].maxpacket, + &pdev->data->in_ep[param].xfer_buff); + break; + + case USB_NOTHING: + default: + break; + } + + return USBD_OK; +} + +static void usb_core_start_xfer(struct usb_handle *pdev, + void *handle, + struct usbd_ep *ep) +{ + if (ep->num == 0U) { + pdev->driver->ep0_start_xfer(handle, ep); + } else { + pdev->driver->ep_start_xfer(handle, ep); + } +} + +/* + * usb_core_receive + * Receive an amount of data + * pdev: USB handle + * ep_addr: endpoint address + * buf: pointer to the reception buffer + * len: amount of data to be received + * return : status + */ +enum usb_status usb_core_receive(struct usb_handle *pdev, uint8_t ep_addr, + uint8_t *buf, uint32_t len) +{ + struct usbd_ep *ep; + struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data; + uint8_t num; + + num = ep_addr & EP_NUM_MASK; + if (num >= USBD_EP_NB) { + return USBD_FAIL; + } + ep = &hpcd->out_ep[num]; + + /* Setup and start the Xfer */ + ep->xfer_buff = buf; + ep->xfer_len = len; + ep->xfer_count = 0U; + ep->is_in = false; + ep->num = num; + + usb_core_start_xfer(pdev, hpcd->instance, ep); + + return USBD_OK; +} + +/* + * usb_core_transmit + * Send an amount of data + * pdev: USB handle + * ep_addr: endpoint address + * buf: pointer to the transmission buffer + * len: amount of data to be sent + * return : status + */ +enum usb_status usb_core_transmit(struct usb_handle *pdev, uint8_t ep_addr, + uint8_t *buf, uint32_t len) +{ + struct usbd_ep *ep; + struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data; + uint8_t num; + + num = ep_addr & EP_NUM_MASK; + if (num >= USBD_EP_NB) { + return USBD_FAIL; + } + ep = &hpcd->in_ep[num]; + + /* Setup and start the Xfer */ + ep->xfer_buff = buf; + ep->xfer_len = len; + ep->xfer_count = 0U; + ep->is_in = true; + ep->num = num; + + usb_core_start_xfer(pdev, hpcd->instance, ep); + + return USBD_OK; +} + +/* + * usb_core_receive_ep0 + * Receive an amount of data on ep0 + * pdev: USB handle + * buf: pointer to the reception buffer + * len: amount of data to be received + * return : status + */ +enum usb_status usb_core_receive_ep0(struct usb_handle *pdev, uint8_t *buf, + uint32_t len) +{ + /* Prepare the reception of the buffer over EP0 */ + if (len != 0U) { + pdev->ep0_state = USBD_EP0_DATA_OUT; + } else { + pdev->ep0_state = USBD_EP0_STATUS_OUT; + } + + pdev->ep_out[0].total_length = len; + pdev->ep_out[0].rem_length = len; + + /* Start the transfer */ + return usb_core_receive(pdev, 0U, buf, len); +} + +/* + * usb_core_transmit_ep0 + * Send an amount of data on ep0 + * pdev: USB handle + * buf: pointer to the transmission buffer + * len: amount of data to be sent + * return : status + */ +enum usb_status usb_core_transmit_ep0(struct usb_handle *pdev, uint8_t *buf, + uint32_t len) +{ + /* Set EP0 State */ + if (len != 0U) { + pdev->ep0_state = USBD_EP0_DATA_IN; + } else { + pdev->ep0_state = USBD_EP0_STATUS_IN; + } + + pdev->ep_in[0].total_length = len; + pdev->ep_in[0].rem_length = len; + + /* Start the transfer */ + return usb_core_transmit(pdev, 0U, buf, len); +} + +/* + * usb_core_ctl_error + * Handle USB low level error + * pdev: device instance + * req: usb request + * return : None + */ + +void usb_core_ctl_error(struct usb_handle *pdev) +{ + ERROR("%s : Send an ERROR\n", __func__); + usb_core_set_stall(pdev, EP0_IN); + usb_core_set_stall(pdev, EP0_OUT); +} + +/* + * usb_core_start + * Start the USB device core. + * pdev: Device Handle + * return : USBD Status + */ +enum usb_status usb_core_start(struct usb_handle *pdev) +{ + /* Start the low level driver */ + pdev->driver->start_device(pdev->data->instance); + + return USBD_OK; +} + +/* + * usb_core_stop + * Stop the USB device core. + * pdev: Device Handle + * return : USBD Status + */ +enum usb_status usb_core_stop(struct usb_handle *pdev) +{ + /* Free class resources */ + pdev->class->de_init(pdev, pdev->dev_config); + + /* Stop the low level driver */ + pdev->driver->stop_device(pdev->data->instance); + + return USBD_OK; +} + +/* + * register_usb_driver + * Stop the USB device core. + * pdev: Device Handle + * pcd_handle: PCD handle + * driver: USB driver + * driver_handle: USB driver handle + * return : USBD Status + */ +enum usb_status register_usb_driver(struct usb_handle *pdev, + struct pcd_handle *pcd_handle, + const struct usb_driver *driver, + void *driver_handle) +{ + uint8_t i; + + assert(pdev != NULL); + assert(pcd_handle != NULL); + assert(driver != NULL); + assert(driver_handle != NULL); + + /* Free class resources */ + pdev->driver = driver; + pdev->data = pcd_handle; + pdev->data->instance = driver_handle; + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->ep0_state = USBD_EP0_IDLE; + + /* Copy endpoint information */ + for (i = 0U; i < USBD_EP_NB; i++) { + pdev->ep_in[i].maxpacket = pdev->data->in_ep[i].maxpacket; + pdev->ep_out[i].maxpacket = pdev->data->out_ep[i].maxpacket; + } + + return USBD_OK; +} + +/* + * register_platform + * Register the USB device core. + * pdev: Device Handle + * plat_call_back: callback + * return : USBD Status + */ +enum usb_status register_platform(struct usb_handle *pdev, + const struct usb_desc *plat_call_back) +{ + assert(pdev != NULL); + assert(plat_call_back != NULL); + + /* Save platform info in class resources */ + pdev->desc = plat_call_back; + + return USBD_OK; +} |