diff options
author | John Tsichritzis <john.tsichritzis@arm.com> | 2019-06-19 15:06:00 +0000 |
---|---|---|
committer | TrustedFirmware Code Review <review@review.trustedfirmware.org> | 2019-06-19 15:06:00 +0000 |
commit | fc3c382f2ccb910554d0608a7db67c3fbefca4f7 (patch) | |
tree | 78ef472e449b85595f5c1ca61771b4d86bd8c77b /plat | |
parent | de3ad4f0963cdf5206a9736185d23514cfb45111 (diff) | |
parent | f237822f0b003dc5bec54d8c4ee961597a11116c (diff) | |
download | platform_external_arm-trusted-firmware-fc3c382f2ccb910554d0608a7db67c3fbefca4f7.tar.gz platform_external_arm-trusted-firmware-fc3c382f2ccb910554d0608a7db67c3fbefca4f7.tar.bz2 platform_external_arm-trusted-firmware-fc3c382f2ccb910554d0608a7db67c3fbefca4f7.zip |
Merge changes from topic "yg/clk_syscfg_dt" into integration
* changes:
fdts: stm32mp1: realign device tree files with internal devs
stm32mp1: increase device tree size to 20kB
stm32mp1: make dt_get_stdout_node_offset() static
stm32mp1: use unsigned values for SDMMC defines
stm32mp1: remove useless LIBFDT_SRCS from PLAT_BL_COMMON_SOURCES
stm32mp1: update doc for U-Boot compilation
stm32mp1: add general SYSCFG management
stm32mp1: move stm32_get_gpio_bank_clock() to private file
clk: stm32mp1: correctly handle Clock Spreading Generator
clk: stm32mp1: use defines for mask values in stm32mp1_clk_sel array
clk: stm32mp1: move oscillator functions to generic file
arch: add some defines for generic timer registers
Diffstat (limited to 'plat')
-rw-r--r-- | plat/st/common/include/stm32mp_dt.h | 3 | ||||
-rw-r--r-- | plat/st/common/stm32mp_common.c | 11 | ||||
-rw-r--r-- | plat/st/common/stm32mp_dt.c | 151 | ||||
-rw-r--r-- | plat/st/stm32mp1/bl2_plat_setup.c | 7 | ||||
-rw-r--r-- | plat/st/stm32mp1/include/stm32mp1_private.h | 4 | ||||
-rw-r--r-- | plat/st/stm32mp1/platform.mk | 7 | ||||
-rw-r--r-- | plat/st/stm32mp1/stm32mp1_def.h | 17 | ||||
-rw-r--r-- | plat/st/stm32mp1/stm32mp1_private.c | 13 | ||||
-rw-r--r-- | plat/st/stm32mp1/stm32mp1_syscfg.c | 180 |
9 files changed, 328 insertions, 65 deletions
diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h index 3415b051d..74b01b3aa 100644 --- a/plat/st/common/include/stm32mp_dt.h +++ b/plat/st/common/include/stm32mp_dt.h @@ -36,11 +36,12 @@ int dt_set_stdout_pinctrl(void); void dt_fill_device_info(struct dt_node_info *info, int node); int dt_get_node(struct dt_node_info *info, int offset, const char *compat); int dt_get_stdout_uart_info(struct dt_node_info *info); -int dt_get_stdout_node_offset(void); uint32_t dt_get_ddr_size(void); uintptr_t dt_get_ddrctrl_base(void); uintptr_t dt_get_ddrphyc_base(void); uintptr_t dt_get_pwr_base(void); +uint32_t dt_get_pwr_vdd_voltage(void); +uintptr_t dt_get_syscfg_base(void); const char *dt_get_board_model(void); #endif /* STM32MP_DT_H */ diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c index 2aba41e54..f95c7885d 100644 --- a/plat/st/common/stm32mp_common.c +++ b/plat/st/common/stm32mp_common.c @@ -98,17 +98,6 @@ uintptr_t stm32_get_gpio_bank_base(unsigned int bank) return GPIOA_BASE + (bank * GPIO_BANK_OFFSET); } -unsigned long stm32_get_gpio_bank_clock(unsigned int bank) -{ - if (bank == GPIO_BANK_Z) { - return GPIOZ; - } - - assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K); - - return GPIOA + (bank - GPIO_BANK_A); -} - uint32_t stm32_get_gpio_bank_offset(unsigned int bank) { if (bank == GPIO_BANK_Z) { diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c index e64433bc8..17da4904a 100644 --- a/plat/st/common/stm32mp_dt.c +++ b/plat/st/common/stm32mp_dt.c @@ -146,6 +146,52 @@ int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, } /******************************************************************************* + * This function gets the stdout path node. + * It reads the value indicated inside the device tree. + * Returns node offset on success and a negative FDT error code on failure. + ******************************************************************************/ +static int dt_get_stdout_node_offset(void) +{ + int node; + const char *cchar; + + node = fdt_path_offset(fdt, "/secure-chosen"); + if (node < 0) { + node = fdt_path_offset(fdt, "/chosen"); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + } + + cchar = fdt_getprop(fdt, node, "stdout-path", NULL); + if (cchar == NULL) { + return -FDT_ERR_NOTFOUND; + } + + node = -FDT_ERR_NOTFOUND; + if (strchr(cchar, (int)':') != NULL) { + const char *name; + char *str = (char *)cchar; + int len = 0; + + while (strncmp(":", str, 1)) { + len++; + str++; + } + + name = fdt_get_alias_namelen(fdt, cchar, len); + + if (name != NULL) { + node = fdt_path_offset(fdt, name); + } + } else { + node = fdt_path_offset(fdt, cchar); + } + + return node; +} + +/******************************************************************************* * This function gets the stdout pin configuration information from the DT. * And then calls the sub-function to treat it and set GPIO registers. * Returns 0 on success and a negative FDT error code on failure. @@ -232,49 +278,6 @@ int dt_get_stdout_uart_info(struct dt_node_info *info) } /******************************************************************************* - * This function gets the stdout path node. - * It reads the value indicated inside the device tree. - * Returns node if success, and a negative value else. - ******************************************************************************/ -int dt_get_stdout_node_offset(void) -{ - int node; - const char *cchar; - - node = fdt_path_offset(fdt, "/chosen"); - if (node < 0) { - return -FDT_ERR_NOTFOUND; - } - - cchar = fdt_getprop(fdt, node, "stdout-path", NULL); - if (cchar == NULL) { - return -FDT_ERR_NOTFOUND; - } - - node = -FDT_ERR_NOTFOUND; - if (strchr(cchar, (int)':') != NULL) { - const char *name; - char *str = (char *)cchar; - int len = 0; - - while (strncmp(":", str, 1)) { - len++; - str++; - } - - name = fdt_get_alias_namelen(fdt, cchar, len); - - if (name != NULL) { - node = fdt_path_offset(fdt, name); - } - } else { - node = fdt_path_offset(fdt, cchar); - } - - return node; -} - -/******************************************************************************* * This function gets DDR size information from the DT. * Returns value in bytes on success, and 0 on failure. ******************************************************************************/ @@ -359,6 +362,68 @@ uintptr_t dt_get_pwr_base(void) } /******************************************************************************* + * This function gets PWR VDD regulator voltage information from the DT. + * Returns value in microvolts on success, and 0 on failure. + ******************************************************************************/ +uint32_t dt_get_pwr_vdd_voltage(void) +{ + int node, pwr_regulators_node; + const fdt32_t *cuint; + + node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); + if (node < 0) { + INFO("%s: Cannot read PWR node in DT\n", __func__); + return 0; + } + + pwr_regulators_node = fdt_subnode_offset(fdt, node, "pwr-regulators"); + if (node < 0) { + INFO("%s: Cannot read pwr-regulators node in DT\n", __func__); + return 0; + } + + cuint = fdt_getprop(fdt, pwr_regulators_node, "vdd-supply", NULL); + if (cuint == NULL) { + return 0; + } + + node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (node < 0) { + return 0; + } + + cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); + if (cuint == NULL) { + return 0; + } + + return fdt32_to_cpu(*cuint); +} + +/******************************************************************************* + * This function gets SYSCFG base address information from the DT. + * Returns value on success, and 0 on failure. + ******************************************************************************/ +uintptr_t dt_get_syscfg_base(void) +{ + int node; + const fdt32_t *cuint; + + node = fdt_node_offset_by_compatible(fdt, -1, DT_SYSCFG_COMPAT); + if (node < 0) { + INFO("%s: Cannot read SYSCFG node in DT\n", __func__); + return 0; + } + + cuint = fdt_getprop(fdt, node, "reg", NULL); + if (cuint == NULL) { + return 0; + } + + return fdt32_to_cpu(*cuint); +} + +/******************************************************************************* * This function retrieves board model from DT * Returns string taken from model node, NULL otherwise ******************************************************************************/ diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c index b54486e84..27d298e8d 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -15,6 +15,7 @@ #include <common/desc_image_load.h> #include <drivers/delay_timer.h> #include <drivers/generic_delay_timer.h> +#include <drivers/st/bsec.h> #include <drivers/st/stm32_console.h> #include <drivers/st/stm32mp_pmic.h> #include <drivers/st/stm32mp_reset.h> @@ -211,6 +212,10 @@ void bl2_el3_plat_arch_setup(void) ; } + if (bsec_probe() != 0) { + panic(); + } + /* Reset backup domain on cold boot cases */ if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) { mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST); @@ -236,6 +241,8 @@ void bl2_el3_plat_arch_setup(void) panic(); } + stm32mp1_syscfg_init(); + result = dt_get_stdout_uart_info(&dt_uart_info); if ((result <= 0) || diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h index 49a2bdf41..e38fca012 100644 --- a/plat/st/stm32mp1/include/stm32mp1_private.h +++ b/plat/st/stm32mp1/include/stm32mp1_private.h @@ -17,4 +17,8 @@ void stm32mp1_security_setup(void); void stm32mp1_gic_pcpu_init(void); void stm32mp1_gic_init(void); +void stm32mp1_syscfg_init(void); +void stm32mp1_syscfg_enable_io_compensation(void); +void stm32mp1_syscfg_disable_io_compensation(void); + #endif /* STM32MP1_PRIVATE_H */ diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk index 4796e91f0..f6bf9f3f4 100644 --- a/plat/st/stm32mp1/platform.mk +++ b/plat/st/stm32mp1/platform.mk @@ -49,14 +49,12 @@ PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} PLAT_BL_COMMON_SOURCES += lib/cpus/aarch32/cortex_a7.S -PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \ - drivers/arm/tzc/tzc400.c \ +PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \ drivers/delay_timer/delay_timer.c \ drivers/delay_timer/generic_delay_timer.c \ drivers/st/bsec/bsec.c \ drivers/st/clk/stm32mp_clkfunc.c \ drivers/st/clk/stm32mp1_clk.c \ - drivers/st/clk/stm32mp1_clkfunc.c \ drivers/st/ddr/stm32mp1_ddr_helpers.c \ drivers/st/gpio/stm32_gpio.c \ drivers/st/i2c/stm32_i2c.c \ @@ -66,7 +64,8 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \ plat/st/common/stm32mp_dt.c \ plat/st/stm32mp1/stm32mp1_context.c \ plat/st/stm32mp1/stm32mp1_helper.S \ - plat/st/stm32mp1/stm32mp1_security.c + plat/st/stm32mp1/stm32mp1_security.c \ + plat/st/stm32mp1/stm32mp1_syscfg.c BL2_SOURCES += drivers/io/io_block.c \ drivers/io/io_dummy.c \ diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index cff7ddbd6..94c4c5b38 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -111,7 +111,7 @@ enum ddr_type { #endif /* DTB initialization value */ -#define STM32MP_DTB_SIZE U(0x00004000) /* 16Ko for DTB */ +#define STM32MP_DTB_SIZE U(0x00005000) /* 20Ko for DTB */ #define STM32MP_DTB_BASE (STM32MP_BL2_BASE - \ STM32MP_DTB_SIZE) @@ -223,11 +223,11 @@ enum ddr_type { #define STM32MP_SDMMC2_BASE U(0x58007000) #define STM32MP_SDMMC3_BASE U(0x48004000) -#define STM32MP_MMC_INIT_FREQ 400000 /*400 KHz*/ -#define STM32MP_SD_NORMAL_SPEED_MAX_FREQ 25000000 /*25 MHz*/ -#define STM32MP_SD_HIGH_SPEED_MAX_FREQ 50000000 /*50 MHz*/ -#define STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ 26000000 /*26 MHz*/ -#define STM32MP_EMMC_HIGH_SPEED_MAX_FREQ 52000000 /*52 MHz*/ +#define STM32MP_MMC_INIT_FREQ U(400000) /*400 KHz*/ +#define STM32MP_SD_NORMAL_SPEED_MAX_FREQ U(25000000) /*25 MHz*/ +#define STM32MP_SD_HIGH_SPEED_MAX_FREQ U(50000000) /*50 MHz*/ +#define STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ U(26000000) /*26 MHz*/ +#define STM32MP_EMMC_HIGH_SPEED_MAX_FREQ U(52000000) /*52 MHz*/ /******************************************************************************* * STM32MP1 BSEC / OTP @@ -239,11 +239,15 @@ enum ddr_type { /* OTP offsets */ #define DATA0_OTP U(0) +#define HW2_OTP U(18) /* OTP mask */ /* DATA0 */ #define DATA0_OTP_SECURED BIT(6) +/* HW2 OTP */ +#define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13) + /******************************************************************************* * STM32MP1 TAMP ******************************************************************************/ @@ -277,5 +281,6 @@ static inline uint32_t tamp_bkpr(uint32_t idx) ******************************************************************************/ #define DT_PWR_COMPAT "st,stm32mp1-pwr" #define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" +#define DT_SYSCFG_COMPAT "st,stm32mp157-syscfg" #endif /* STM32MP1_DEF_H */ diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c index 20eb88e72..340c7fba3 100644 --- a/plat/st/stm32mp1/stm32mp1_private.c +++ b/plat/st/stm32mp1/stm32mp1_private.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <assert.h> + #include <platform_def.h> #include <lib/xlat_tables/xlat_tables_v2.h> @@ -53,3 +55,14 @@ void configure_mmu(void) enable_mmu_svc_mon(0); } + +unsigned long stm32_get_gpio_bank_clock(unsigned int bank) +{ + if (bank == GPIO_BANK_Z) { + return GPIOZ; + } + + assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K); + + return GPIOA + (bank - GPIO_BANK_A); +} diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c new file mode 100644 index 000000000..2fd06f38a --- /dev/null +++ b/plat/st/stm32mp1/stm32mp1_syscfg.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <common/debug.h> +#include <drivers/st/bsec.h> +#include <drivers/st/stpmic1.h> +#include <lib/mmio.h> + +#include <stm32mp_dt.h> +#include <stm32mp1_private.h> + +/* + * SYSCFG REGISTER OFFSET (base relative) + */ +#define SYSCFG_BOOTR 0x00U +#define SYSCFG_IOCTRLSETR 0x18U +#define SYSCFG_ICNR 0x1CU +#define SYSCFG_CMPCR 0x20U +#define SYSCFG_CMPENSETR 0x24U + +/* + * SYSCFG_BOOTR Register + */ +#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0) +#define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4) +#define SYSCFG_BOOTR_BOOTPD_SHIFT 4 +/* + * SYSCFG_IOCTRLSETR Register + */ +#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0) +#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1) +#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2) +#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3) +#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4) + +/* + * SYSCFG_ICNR Register + */ +#define SYSCFG_ICNR_AXI_M9 BIT(9) + +/* + * SYSCFG_CMPCR Register + */ +#define SYSCFG_CMPCR_SW_CTRL BIT(1) +#define SYSCFG_CMPCR_READY BIT(8) +#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16) +#define SYSCFG_CMPCR_RANSRC_SHIFT 16 +#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20) +#define SYSCFG_CMPCR_ANSRC_SHIFT 24 + +/* + * SYSCFG_CMPENSETR Register + */ +#define SYSCFG_CMPENSETR_MPU_EN BIT(0) + +void stm32mp1_syscfg_init(void) +{ + uint32_t bootr; + uint32_t otp = 0; + uint32_t vdd_voltage; + uintptr_t syscfg_base = dt_get_syscfg_base(); + + /* + * Interconnect update : select master using the port 1. + * LTDC = AXI_M9. + */ + mmio_write_32(syscfg_base + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9); + + /* Disable Pull-Down for boot pin connected to VDD */ + bootr = mmio_read_32(syscfg_base + SYSCFG_BOOTR) & + SYSCFG_BOOTR_BOOT_MASK; + mmio_clrsetbits_32(syscfg_base + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK, + bootr << SYSCFG_BOOTR_BOOTPD_SHIFT); + + /* + * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI + * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. + * It could be disabled for low frequencies or if AFMUX is selected + * but the function is not used, typically for TRACE. + * If high speed low voltage pad mode is node enable, platform will + * over consume. + * + * WARNING: + * Enabling High Speed mode while VDD > 2.7V + * with the OTP product_below_2v5 (OTP 18, BIT 13) + * erroneously set to 1 can damage the SoC! + * => TF-A enables the low power mode only if VDD < 2.7V (in DT) + * but this value needs to be consistent with board design. + */ + if (bsec_read_otp(&otp, HW2_OTP) != BSEC_OK) { + panic(); + } + + otp = otp & HW2_OTP_PRODUCT_BELOW_2V5; + + /* Get VDD supply */ + vdd_voltage = dt_get_pwr_vdd_voltage(); + + /* Check if VDD is Low Voltage */ + if (vdd_voltage == 0U) { + WARN("VDD unknown"); + } else if (vdd_voltage < 2700000U) { + mmio_write_32(syscfg_base + SYSCFG_IOCTRLSETR, + SYSCFG_IOCTRLSETR_HSLVEN_TRACE | + SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI | + SYSCFG_IOCTRLSETR_HSLVEN_ETH | + SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | + SYSCFG_IOCTRLSETR_HSLVEN_SPI); + + if (otp == 0U) { + INFO("Product_below_2v5=0: HSLVEN protected by HW\n"); + } + } else { + if (otp != 0U) { + ERROR("Product_below_2v5=1:\n"); + ERROR("\tHSLVEN update is destructive,\n"); + ERROR("\tno update as VDD > 2.7V\n"); + panic(); + } + } + + stm32mp1_syscfg_enable_io_compensation(); +} + +void stm32mp1_syscfg_enable_io_compensation(void) +{ + uintptr_t syscfg_base = dt_get_syscfg_base(); + + /* + * Activate automatic I/O compensation. + * Warning: need to ensure CSI enabled and ready in clock driver. + * Enable non-secure clock, we assume non-secure is suspended. + */ + stm32mp1_clk_enable_non_secure(SYSCFG); + + mmio_setbits_32(syscfg_base + SYSCFG_CMPENSETR, + SYSCFG_CMPENSETR_MPU_EN); + + while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) & + SYSCFG_CMPCR_READY) == 0U) { + ; + } + + mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); +} + +void stm32mp1_syscfg_disable_io_compensation(void) +{ + uintptr_t syscfg_base = dt_get_syscfg_base(); + uint32_t value; + + /* + * Deactivate automatic I/O compensation. + * Warning: CSI is disabled automatically in STOP if not + * requested for other usages and always OFF in STANDBY. + * Disable non-secure SYSCFG clock, we assume non-secure is suspended. + */ + value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) >> + SYSCFG_CMPCR_ANSRC_SHIFT; + + mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, + SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); + + value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) | + (value << SYSCFG_CMPCR_RANSRC_SHIFT); + + mmio_write_32(syscfg_base + SYSCFG_CMPCR, value); + + mmio_setbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); + + mmio_clrbits_32(syscfg_base + SYSCFG_CMPENSETR, + SYSCFG_CMPENSETR_MPU_EN); + + stm32mp1_clk_disable_non_secure(SYSCFG); +} |