diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst index 7adc3c8..88251d6 100644 --- a/docs/plat/stm32mp1.rst +++ b/docs/plat/stm32mp1.rst @@ -83,9 +83,8 @@ make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min DTB_FILE_NAME=stm32mp157c-ev1.dtb cd - make stm32mp15_basic_defconfig + make stm32mp15_trusted_defconfig make DEVICE_TREE=stm32mp157c-ev1 all - ./tools/mkimage -T stm32image -a 0xC0100000 -e 0xC0100000 -d u-boot.bin u-boot.stm32 To build TF-A with with Op-TEE support: diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index 11fd666..76e6e6f 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -40,6 +39,15 @@ #define HSIDIV_TIMEOUT TIMEOUT_US_200MS #define OSCRDY_TIMEOUT TIMEOUT_US_1S +const char *stm32mp_osc_node_label[NB_OSC] = { + [_LSI] = "clk-lsi", + [_LSE] = "clk-lse", + [_HSI] = "clk-hsi", + [_HSE] = "clk-hse", + [_CSI] = "clk-csi", + [_I2S_CKIN] = "i2s_ckin", +}; + enum stm32mp1_parent_id { /* Oscillators are defined in enum stm32mp_osc_id */ @@ -83,7 +91,7 @@ _STGEN_SEL, _I2C46_SEL, _SPI6_SEL, - _USART1_SEL, + _UART1_SEL, _RNG1_SEL, _UART6_SEL, _UART24_SEL, @@ -93,8 +101,8 @@ _SDMMC3_SEL, _QSPI_SEL, _FMC_SEL, - _ASS_SEL, - _MSS_SEL, + _AXIS_SEL, + _MCUS_SEL, _USBPHY_SEL, _USBO_SEL, _PARENT_SEL_NB, @@ -246,13 +254,13 @@ .fixed = (f), \ } -#define _CLK_PARENT(idx, off, s, m, p) \ - [(idx)] = { \ - .offset = (off), \ - .src = (s), \ - .msk = (m), \ - .parent = (p), \ - .nb_parent = ARRAY_SIZE(p) \ +#define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \ + [_ ## _label ## _SEL] = { \ + .offset = _rcc_selr, \ + .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \ + .msk = _rcc_selr ## _ ## _label ## SRC_MASK, \ + .parent = (_parents), \ + .nb_parent = ARRAY_SIZE(_parents) \ } #define _CLK_PLL(idx, type, off1, off2, off3, \ @@ -315,6 +323,8 @@ _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), + _CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), + _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), @@ -322,7 +332,7 @@ _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), - _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _USART1_SEL), + _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), @@ -430,25 +440,25 @@ }; static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { - _CLK_PARENT(_I2C12_SEL, RCC_I2C12CKSELR, 0, 0x7, i2c12_parents), - _CLK_PARENT(_I2C35_SEL, RCC_I2C35CKSELR, 0, 0x7, i2c35_parents), - _CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents), - _CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents), - _CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents), - _CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents), - _CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents), - _CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents), - _CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, uart234578_parents), - _CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents), - _CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents), - _CLK_PARENT(_SDMMC12_SEL, RCC_SDMMC12CKSELR, 0, 0x7, sdmmc12_parents), - _CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7, sdmmc3_parents), - _CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0xf, qspi_parents), - _CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0xf, fmc_parents), - _CLK_PARENT(_ASS_SEL, RCC_ASSCKSELR, 0, 0x3, ass_parents), - _CLK_PARENT(_MSS_SEL, RCC_MSSCKSELR, 0, 0x3, mss_parents), - _CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents), - _CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents), + _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents), + _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents), + _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents), + _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents), + _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents), + _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents), + _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents), + _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents), + _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents), + _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents), + _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents), + _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents), + _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(USBPHY, RCC_USBCKSELR, usbphy_parents), + _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents), }; /* Define characteristic of PLL according type */ @@ -648,7 +658,7 @@ } sel = clk_sel_ref(s); - p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & sel->msk; + p_sel = (mmio_read_32(rcc_base + sel->offset) & sel->msk) >> sel->src; if (p_sel < sel->nb_parent) { return (int)sel->parent[p_sel]; } @@ -1305,7 +1315,11 @@ const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; - mmio_write_32(pllxcr, RCC_PLLNCR_PLLON); + /* Preserve RCC_PLLNCR_SSCG_CTRL value */ + mmio_clrsetbits_32(pllxcr, + RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN, + RCC_PLLNCR_PLLON); } static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) @@ -1434,6 +1448,9 @@ RCC_PLLNCSGR_SSCG_MODE_MASK; mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg); + + mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr, + RCC_PLLNCR_SSCG_CTRL); } static int stm32mp1_set_clksrc(unsigned int clksrc) @@ -1516,9 +1533,6 @@ } } -#define CNTCVL_OFF 0x008 -#define CNTCVU_OFF 0x00C - static void stm32mp1_stgen_config(void) { uintptr_t stgen; diff --git a/drivers/st/clk/stm32mp1_clkfunc.c b/drivers/st/clk/stm32mp1_clkfunc.c deleted file mode 100644 index 1aa05bf..0000000 --- a/drivers/st/clk/stm32mp1_clkfunc.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include - -#include - -#include - -#include -#include -#include -#include -#include - -const char *stm32mp_osc_node_label[NB_OSC] = { - [_LSI] = "clk-lsi", - [_LSE] = "clk-lse", - [_HSI] = "clk-hsi", - [_HSE] = "clk-hse", - [_CSI] = "clk-csi", - [_I2S_CKIN] = "i2s_ckin", -}; - -/* - * Get the frequency of an oscillator from its name in device tree. - * @param name: oscillator name - * @param freq: stores the frequency of the oscillator - * @return: 0 on success, and a negative FDT/ERRNO error code on failure. - */ -int fdt_osc_read_freq(const char *name, uint32_t *freq) -{ - int node, subnode; - void *fdt; - - if (fdt_get_address(&fdt) == 0) { - return -ENOENT; - } - - node = fdt_path_offset(fdt, "/clocks"); - if (node < 0) { - return -FDT_ERR_NOTFOUND; - } - - fdt_for_each_subnode(subnode, fdt, node) { - const char *cchar; - int ret; - - cchar = fdt_get_name(fdt, subnode, &ret); - if (cchar == NULL) { - return ret; - } - - if (strncmp(cchar, name, (size_t)ret) == 0) { - const fdt32_t *cuint; - - cuint = fdt_getprop(fdt, subnode, "clock-frequency", - &ret); - if (cuint == NULL) { - return ret; - } - - *freq = fdt32_to_cpu(*cuint); - - return 0; - } - } - - /* Oscillator not found, freq=0 */ - *freq = 0; - return 0; -} - -/* - * Check the presence of an oscillator property from its id. - * @param osc_id: oscillator ID - * @param prop_name: property name - * @return: true/false regarding search result. - */ -bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) -{ - int node, subnode; - void *fdt; - - if (fdt_get_address(&fdt) == 0) { - return false; - } - - if (osc_id >= NB_OSC) { - return false; - } - - node = fdt_path_offset(fdt, "/clocks"); - if (node < 0) { - return false; - } - - fdt_for_each_subnode(subnode, fdt, node) { - const char *cchar; - int ret; - - cchar = fdt_get_name(fdt, subnode, &ret); - if (cchar == NULL) { - return false; - } - - if (strncmp(cchar, stm32mp_osc_node_label[osc_id], - (size_t)ret) != 0) { - continue; - } - - if (fdt_getprop(fdt, subnode, prop_name, NULL) != NULL) { - return true; - } - } - - return false; -} - -/* - * Get the value of a oscillator property from its ID. - * @param osc_id: oscillator ID - * @param prop_name: property name - * @param dflt_value: default value - * @return oscillator value on success, default value if property not found. - */ -uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, - const char *prop_name, uint32_t dflt_value) -{ - int node, subnode; - void *fdt; - - if (fdt_get_address(&fdt) == 0) { - return dflt_value; - } - - if (osc_id >= NB_OSC) { - return dflt_value; - } - - node = fdt_path_offset(fdt, "/clocks"); - if (node < 0) { - return dflt_value; - } - - fdt_for_each_subnode(subnode, fdt, node) { - const char *cchar; - int ret; - - cchar = fdt_get_name(fdt, subnode, &ret); - if (cchar == NULL) { - return dflt_value; - } - - if (strncmp(cchar, stm32mp_osc_node_label[osc_id], - (size_t)ret) != 0) { - continue; - } - - return fdt_read_uint32_default(subnode, prop_name, dflt_value); - } - - return dflt_value; -} diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c index 16acef0..87c8e2b 100644 --- a/drivers/st/clk/stm32mp_clkfunc.c +++ b/drivers/st/clk/stm32mp_clkfunc.c @@ -16,6 +16,147 @@ #define DT_STGEN_COMPAT "st,stm32-stgen" /* + * Get the frequency of an oscillator from its name in device tree. + * @param name: oscillator name + * @param freq: stores the frequency of the oscillator + * @return: 0 on success, and a negative FDT/ERRNO error code on failure. + */ +int fdt_osc_read_freq(const char *name, uint32_t *freq) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar; + int ret; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + return ret; + } + + if (strncmp(cchar, name, (size_t)ret) == 0) { + const fdt32_t *cuint; + + cuint = fdt_getprop(fdt, subnode, "clock-frequency", + &ret); + if (cuint == NULL) { + return ret; + } + + *freq = fdt32_to_cpu(*cuint); + + return 0; + } + } + + /* Oscillator not found, freq=0 */ + *freq = 0; + return 0; +} + +/* + * Check the presence of an oscillator property from its id. + * @param osc_id: oscillator ID + * @param prop_name: property name + * @return: true/false regarding search result. + */ +bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return false; + } + + if (osc_id >= NB_OSC) { + return false; + } + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return false; + } + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar; + int ret; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + return false; + } + + if (strncmp(cchar, stm32mp_osc_node_label[osc_id], + (size_t)ret) != 0) { + continue; + } + + if (fdt_getprop(fdt, subnode, prop_name, NULL) != NULL) { + return true; + } + } + + return false; +} + +/* + * Get the value of a oscillator property from its ID. + * @param osc_id: oscillator ID + * @param prop_name: property name + * @param dflt_value: default value + * @return oscillator value on success, default value if property not found. + */ +uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, + const char *prop_name, uint32_t dflt_value) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return dflt_value; + } + + if (osc_id >= NB_OSC) { + return dflt_value; + } + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return dflt_value; + } + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar; + int ret; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + return dflt_value; + } + + if (strncmp(cchar, stm32mp_osc_node_label[osc_id], + (size_t)ret) != 0) { + continue; + } + + return fdt_read_uint32_default(subnode, prop_name, dflt_value); + } + + return dflt_value; +} + +/* * Get the RCC node offset from the device tree * @param fdt: Device tree reference * @return: Node offset or a negative value on error diff --git a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi index 16b8cf6..11e8f2b 100644 --- a/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi +++ b/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause /* * Copyright (C) 2018, STMicroelectronics - All Rights Reserved - */ -/* STM32MP157C DK1/DK2 BOARD configuration + * + * STM32MP157C DK1/DK2 BOARD configuration * 1x DDR3L 4Gb, 16-bit, 533MHz. * Reference used NT5CC256M16DP-DI from NANYA * @@ -16,8 +16,7 @@ * address mapping : RBC * Tc > + 85C : N */ - -#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.41" +#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.45" #define DDR_MEM_SPEED 533000 #define DDR_MEM_SIZE 0x20000000 @@ -90,7 +89,7 @@ #define DDR_PTR2 0x042DA068 #define DDR_ACIOCR 0x10400812 #define DDR_DXCCR 0x00000C40 -#define DDR_DSGCR 0xF200001F +#define DDR_DSGCR 0xF200011F #define DDR_DCR 0x0000000B #define DDR_DTPR0 0x38D488D0 #define DDR_DTPR1 0x098B00D8 @@ -109,11 +108,11 @@ #define DDR_DX1DLLCR 0x40000000 #define DDR_DX1DQTR 0xFFFFFFFF #define DDR_DX1DQSTR 0x3DB02000 -#define DDR_DX2GCR 0x0000CE81 +#define DDR_DX2GCR 0x0000CE80 #define DDR_DX2DLLCR 0x40000000 #define DDR_DX2DQTR 0xFFFFFFFF #define DDR_DX2DQSTR 0x3DB02000 -#define DDR_DX3GCR 0x0000CE81 +#define DDR_DX3GCR 0x0000CE80 #define DDR_DX3DLLCR 0x40000000 #define DDR_DX3DQTR 0xFFFFFFFF #define DDR_DX3DQSTR 0x3DB02000 diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi index 82e7104..4b70b60 100644 --- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi +++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi @@ -1,9 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause /* * Copyright (C) 2018, STMicroelectronics - All Rights Reserved - */ - -/* STM32MP157C ED1 BOARD configuration + * + * STM32MP157C ED1 BOARD configuration * 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology. * Reference used NT5CC256M16DP-DI from NANYA * @@ -17,8 +16,7 @@ * address mapping : RBC * Tc > + 85C : N */ - -#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.41" +#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.45" #define DDR_MEM_SPEED 533000 #define DDR_MEM_SIZE 0x40000000 @@ -91,7 +89,7 @@ #define DDR_PTR2 0x042DA068 #define DDR_ACIOCR 0x10400812 #define DDR_DXCCR 0x00000C40 -#define DDR_DSGCR 0xF200001F +#define DDR_DSGCR 0xF200011F #define DDR_DCR 0x0000000B #define DDR_DTPR0 0x38D488D0 #define DDR_DTPR1 0x098B00D8 diff --git a/fdts/stm32mp157-pinctrl.dtsi b/fdts/stm32mp157-pinctrl.dtsi index c7553ca..8e480b2 100644 --- a/fdts/stm32mp157-pinctrl.dtsi +++ b/fdts/stm32mp157-pinctrl.dtsi @@ -214,21 +214,6 @@ }; }; - sdmmc1_dir_pins_b: sdmmc1-dir-1 { - pins1 { - pinmux = , /* SDMMC1_D0DIR */ - , /* SDMMC1_D123DIR */ - ; /* SDMMC1_CDIR */ - slew-rate = <3>; - drive-push-pull; - bias-pull-up; - }; - pins2 { - pinmux = ; /* SDMMC1_CKIN */ - bias-pull-up; - }; - }; - sdmmc2_b4_pins_a: sdmmc2-b4-0 { pins1 { pinmux = , /* SDMMC2_D0 */ @@ -286,6 +271,19 @@ }; }; + uart7_pins_a: uart7-0 { + pins1 { + pinmux = ; /* USART7_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* USART7_RX */ + bias-disable; + }; + }; + usart3_pins_a: usart3-0 { pins1 { pinmux = , /* USART3_TX */ @@ -300,6 +298,21 @@ bias-disable; }; }; + + usart3_pins_b: usart3-1 { + pins1 { + pinmux = , /* USART3_TX */ + ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART3_RX */ + ; /* USART3_CTS_NSS */ + bias-disable; + }; + }; }; pinctrl_z: pin-controller-z@54004000 { diff --git a/fdts/stm32mp157a-dk1.dts b/fdts/stm32mp157a-dk1.dts index 68188be..b17d501 100644 --- a/fdts/stm32mp157a-dk1.dts +++ b/fdts/stm32mp157a-dk1.dts @@ -15,6 +15,8 @@ aliases { serial0 = &uart4; + serial1 = &usart3; + serial2 = &uart7; }; chosen { @@ -146,6 +148,12 @@ status = "okay"; }; +&pwr { + pwr-regulators { + vdd-supply = <&vdd>; + }; +}; + &rng1 { status = "okay"; }; @@ -170,6 +178,18 @@ status = "okay"; }; +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_a>; + status = "disabled"; +}; + +&usart3 { + pinctrl-names = "default"; + pinctrl-0 = <&usart3_pins_b>; + status = "disabled"; +}; + /* ATF Specific */ #include #include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" @@ -281,3 +301,11 @@ cfg = < 3 98 5 7 7 PQR(1,1,1) >; }; }; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + status = "okay"; + secure-status = "okay"; + }; +}; diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts index 820e413..ed55725 100644 --- a/fdts/stm32mp157c-ed1.dts +++ b/fdts/stm32mp157c-ed1.dts @@ -42,7 +42,7 @@ st,main-control-register = <0x04>; st,vin-control-register = <0xc0>; - st,usb-control-register = <0x30>; + st,usb-control-register = <0x20>; regulators { compatible = "st,stpmic1-regulators"; @@ -143,6 +143,12 @@ status = "okay"; }; +&pwr { + pwr-regulators { + vdd-supply = <&vdd>; + }; +}; + &rng1 { status = "okay"; }; @@ -302,4 +308,10 @@ }; }; -/delete-node/ &clk_csi; +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + status = "okay"; + secure-status = "okay"; + }; +}; diff --git a/fdts/stm32mp157c-security.dtsi b/fdts/stm32mp157c-security.dtsi index 59119c5..f7e55b3 100644 --- a/fdts/stm32mp157c-security.dtsi +++ b/fdts/stm32mp157c-security.dtsi @@ -26,9 +26,12 @@ status = "okay"; secure-status = "okay"; }; - board_id: board_id@ec { - reg = <0xec 0x4>; - status = "okay"; - secure-status = "okay"; - }; +}; + +&sdmmc1 { + compatible = "st,stm32-sdmmc2"; +}; + +&sdmmc2 { + compatible = "st,stm32-sdmmc2"; }; diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi index 0ec7ecb..0942a91 100644 --- a/fdts/stm32mp157c.dtsi +++ b/fdts/stm32mp157c.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* - * Copyright (C) STMicroelectronics 2017 - All Rights Reserved + * Copyright (C) STMicroelectronics 2017-2019 - All Rights Reserved * Author: Ludovic Barre for STMicroelectronics. */ #include @@ -70,6 +70,16 @@ interrupt-parent = <&intc>; ranges; + timers12: timer@40006000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40006000 0x400>; + clocks = <&rcc TIM12_K>; + clock-names = "int"; + status = "disabled"; + }; + usart2: serial@4000e000 { compatible = "st,stm32h7-uart"; reg = <0x4000e000 0x400>; @@ -127,8 +137,19 @@ status = "disabled"; }; + timers15: timer@44006000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x44006000 0x400>; + clocks = <&rcc TIM15_K>; + clock-names = "int"; + status = "disabled"; + }; + sdmmc3: sdmmc@48004000 { - compatible = "st,stm32-sdmmc2"; + compatible = "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00253180>; reg = <0x48004000 0x400>, <0x48005000 0x400>; clocks = <&rcc SDMMC3_K>; clock-names = "apb_pclk"; @@ -139,6 +160,16 @@ status = "disabled"; }; + usbotg_hs: usb-otg@49000000 { + compatible = "st,stm32mp1-hsotg", "snps,dwc2"; + reg = <0x49000000 0x10000>; + clocks = <&rcc USBO_K>; + clock-names = "otg"; + resets = <&rcc USBO_R>; + reset-names = "dwc2"; + status = "disabled"; + }; + rcc: rcc@50000000 { compatible = "st,stm32mp1-rcc", "syscon"; reg = <0x50000000 0x1000>; @@ -170,6 +201,30 @@ }; }; + syscfg: syscon@50020000 { + compatible = "st,stm32mp157-syscfg", "syscon"; + reg = <0x50020000 0x400>; + clocks = <&rcc SYSCFG>; + }; + + cryp1: cryp@54001000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54001000 0x400>; + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; + status = "disabled"; + }; + + hash1: hash@54002000 { + compatible = "st,stm32f756-hash"; + reg = <0x54002000 0x400>; + interrupts = ; + clocks = <&rcc HASH1>; + resets = <&rcc HASH1_R>; + status = "disabled"; + }; + rng1: rng@54003000 { compatible = "st,stm32-rng"; reg = <0x54003000 0x400>; @@ -202,7 +257,8 @@ }; sdmmc1: sdmmc@58005000 { - compatible = "st,stm32-sdmmc2"; + compatible = "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00253180>; reg = <0x58005000 0x1000>, <0x58006000 0x1000>; clocks = <&rcc SDMMC1_K>; clock-names = "apb_pclk"; @@ -214,7 +270,8 @@ }; sdmmc2: sdmmc@58007000 { - compatible = "st,stm32-sdmmc2"; + compatible = "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00253180>; reg = <0x58007000 0x1000>, <0x58008000 0x1000>; clocks = <&rcc SDMMC2_K>; clock-names = "apb_pclk"; diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h index 44044d4..0db4145 100644 --- a/include/arch/aarch32/arch.h +++ b/include/arch/aarch32/arch.h @@ -81,6 +81,10 @@ * Generic timer memory mapped registers & offsets ******************************************************************************/ #define CNTCR_OFF U(0x000) +/* Counter Count Value Lower register */ +#define CNTCVL_OFF U(0x008) +/* Counter Count Value Upper register */ +#define CNTCVU_OFF U(0x00C) #define CNTFID_OFF U(0x020) #define CNTCR_EN (U(1) << 0) diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index d23d89e..502b868 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -99,6 +99,7 @@ * Generic timer memory mapped registers & offsets ******************************************************************************/ #define CNTCR_OFF U(0x000) +#define CNTCV_OFF U(0x008) #define CNTFID_OFF U(0x020) #define CNTCR_EN (U(1) << 0) diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h index 7afa5ad..1ebd39f 100644 --- a/include/drivers/st/stm32mp1_clk.h +++ b/include/drivers/st/stm32mp1_clk.h @@ -9,6 +9,19 @@ #include +enum stm32mp_osc_id { + _HSI, + _HSE, + _CSI, + _LSI, + _LSE, + _I2S_CKIN, + NB_OSC, + _UNKNOWN_OSC_ID = 0xFF +}; + +extern const char *stm32mp_osc_node_label[NB_OSC]; + int stm32mp1_clk_probe(void); int stm32mp1_clk_init(void); diff --git a/include/drivers/st/stm32mp1_clkfunc.h b/include/drivers/st/stm32mp1_clkfunc.h deleted file mode 100644 index f303937..0000000 --- a/include/drivers/st/stm32mp1_clkfunc.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef STM32MP1_CLKFUNC_H -#define STM32MP1_CLKFUNC_H - -#include - -#include - -enum stm32mp_osc_id { - _HSI, - _HSE, - _CSI, - _LSI, - _LSE, - _I2S_CKIN, - NB_OSC, - _UNKNOWN_OSC_ID = 0xFF -}; - -extern const char *stm32mp_osc_node_label[NB_OSC]; - -int fdt_osc_read_freq(const char *name, uint32_t *freq); -bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name); -uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, - const char *prop_name, - uint32_t dflt_value); - -#endif /* STM32MP1_CLKFUNC_H */ diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h index eaa853d..4b4aac8 100644 --- a/include/drivers/st/stm32mp1_rcc.h +++ b/include/drivers/st/stm32mp1_rcc.h @@ -480,4 +480,82 @@ /* Values of RCC_PWRLPDLYCR register */ #define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) +/* RCC_ASSCKSELR register fields */ +#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) +#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 + +/* RCC_MSSCKSELR register fields */ +#define RCC_MSSCKSELR_MCUSSRC_MASK GENMASK(1, 0) +#define RCC_MSSCKSELR_MCUSSRC_SHIFT 0 + +/* RCC_I2C46CKSELR register fields */ +#define RCC_I2C46CKSELR_I2C46SRC_MASK GENMASK(2, 0) +#define RCC_I2C46CKSELR_I2C46SRC_SHIFT 0 + +/* RCC_SPI6CKSELR register fields */ +#define RCC_SPI6CKSELR_SPI6SRC_MASK GENMASK(2, 0) +#define RCC_SPI6CKSELR_SPI6SRC_SHIFT 0 + +/* RCC_UART1CKSELR register fields */ +#define RCC_UART1CKSELR_UART1SRC_MASK GENMASK(2, 0) +#define RCC_UART1CKSELR_UART1SRC_SHIFT 0 + +/* RCC_RNG1CKSELR register fields */ +#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK(1, 0) +#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0 + +/* RCC_STGENCKSELR register fields */ +#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0) +#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 + +/* RCC_I2C12CKSELR register fields */ +#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0) +#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 + +/* RCC_I2C35CKSELR register fields */ +#define RCC_I2C35CKSELR_I2C35SRC_MASK GENMASK(2, 0) +#define RCC_I2C35CKSELR_I2C35SRC_SHIFT 0 + +/* RCC_UART6CKSELR register fields */ +#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0) +#define RCC_UART6CKSELR_UART6SRC_SHIFT 0 + +/* RCC_UART24CKSELR register fields */ +#define RCC_UART24CKSELR_UART24SRC_MASK GENMASK(2, 0) +#define RCC_UART24CKSELR_UART24SRC_SHIFT 0 + +/* RCC_UART35CKSELR register fields */ +#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0) +#define RCC_UART35CKSELR_UART35SRC_SHIFT 0 + +/* RCC_UART78CKSELR register fields */ +#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0) +#define RCC_UART78CKSELR_UART78SRC_SHIFT 0 + +/* RCC_SDMMC12CKSELR register fields */ +#define RCC_SDMMC12CKSELR_SDMMC12SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC12CKSELR_SDMMC12SRC_SHIFT 0 + +/* RCC_SDMMC3CKSELR register fields */ +#define RCC_SDMMC3CKSELR_SDMMC3SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC3CKSELR_SDMMC3SRC_SHIFT 0 + +/* RCC_ETHCKSELR register fields */ +#define RCC_ETHCKSELR_ETHSRC_MASK GENMASK(1, 0) +#define RCC_ETHCKSELR_ETHSRC_SHIFT 0 + +/* RCC_QSPICKSELR register fields */ +#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK(1, 0) +#define RCC_QSPICKSELR_QSPISRC_SHIFT 0 + +/* RCC_FMCCKSELR register fields */ +#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0) +#define RCC_FMCCKSELR_FMCSRC_SHIFT 0 + +/* RCC_USBCKSELR register fields */ +#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) +#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 +#define RCC_USBCKSELR_USBOSRC_MASK BIT(4) +#define RCC_USBCKSELR_USBOSRC_SHIFT 4 + #endif /* STM32MP1_RCC_H */ diff --git a/include/drivers/st/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h index 5beb06b..0769167 100644 --- a/include/drivers/st/stm32mp_clkfunc.h +++ b/include/drivers/st/stm32mp_clkfunc.h @@ -11,6 +11,14 @@ #include +#include + +int fdt_osc_read_freq(const char *name, uint32_t *freq); +bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name); +uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, + const char *prop_name, + uint32_t dflt_value); + int fdt_get_rcc_node(void *fdt); uint32_t fdt_rcc_read_addr(void); int fdt_rcc_read_uint32_array(const char *prop_name, diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h index 3415b05..74b01b3 100644 --- a/plat/st/common/include/stm32mp_dt.h +++ b/plat/st/common/include/stm32mp_dt.h @@ -36,11 +36,12 @@ 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 2aba41e..f95c788 100644 --- a/plat/st/common/stm32mp_common.c +++ b/plat/st/common/stm32mp_common.c @@ -98,17 +98,6 @@ 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 e64433b..17da490 100644 --- a/plat/st/common/stm32mp_dt.c +++ b/plat/st/common/stm32mp_dt.c @@ -146,6 +146,52 @@ } /******************************************************************************* + * 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 @@ } /******************************************************************************* - * 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 @@ } /******************************************************************************* + * 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 b54486e..27d298e 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -211,6 +212,10 @@ ; } + 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 @@ 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 49a2bdf..e38fca0 100644 --- a/plat/st/stm32mp1/include/stm32mp1_private.h +++ b/plat/st/stm32mp1/include/stm32mp1_private.h @@ -17,4 +17,8 @@ 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 4796e91..f6bf9f3 100644 --- a/plat/st/stm32mp1/platform.mk +++ b/plat/st/stm32mp1/platform.mk @@ -49,14 +49,12 @@ 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/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 cff7ddb..94c4c5b 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -111,7 +111,7 @@ #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 @@ #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 @@ /* 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 @@ ******************************************************************************/ #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 20eb88e..340c7fb 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 + #include #include @@ -53,3 +55,14 @@ 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 0000000..2fd06f3 --- /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 + +#include +#include +#include +#include + +#include +#include + +/* + * 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); +}