From a718a5d0f43b9094c9abb04ed0d9999a32d69091 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 14 May 2020 15:00:23 +0200 Subject: net: dwc_eth_qos: update the compatible supported for STM32 Update the compatible associated with the STM32 MPU glue in the DWC ethernet driver. The supported compatible is the specific "st,stm32mp1-dwmac" as indicated in Linux binding Documentation/devicetree/bindings/net/stm32-dwmac.txt and not the "snps,dwmac-4.20a" only used to the select IP version. This glue is implemented in Linux kernel in: drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c For information in stm32mp151.dtsi, the 2 compatibles are supported: ethernet0: ethernet@5800a000 { compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a"; ... }; Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/net/dwc_eth_qos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 3f4437069ba..62941bb1753 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -2170,7 +2170,7 @@ static const struct udevice_id eqos_ids[] = { .data = (ulong)&eqos_tegra186_config }, { - .compatible = "snps,dwmac-4.20a", + .compatible = "st,stm32mp1-dwmac", .data = (ulong)&eqos_stm32_config }, { -- cgit v1.3.1 From 95bd49a5aa8bd7b1018e7de1ff547efa54552e62 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 25 May 2020 12:19:41 +0200 Subject: arm: stm32mp: spl: add bsec driver in SPL Add the bsec driver in SPL, as it is needed by SOC part number detection to found the supported OPP. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard Reviewed-by: Patrice Chotard --- arch/arm/dts/stm32mp15-u-boot.dtsi | 2 +- arch/arm/mach-stm32mp/Makefile | 2 +- arch/arm/mach-stm32mp/bsec.c | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/arm/dts/stm32mp15-u-boot.dtsi b/arch/arm/dts/stm32mp15-u-boot.dtsi index 1279589a563..a0d971ad88a 100644 --- a/arch/arm/dts/stm32mp15-u-boot.dtsi +++ b/arch/arm/dts/stm32mp15-u-boot.dtsi @@ -65,7 +65,7 @@ }; &bsec { - u-boot,dm-pre-proper; + u-boot,dm-pre-reloc; }; &clk_csi { diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile index 66bb8cf92fa..c8aa24d489e 100644 --- a/arch/arm/mach-stm32mp/Makefile +++ b/arch/arm/mach-stm32mp/Makefile @@ -6,12 +6,12 @@ obj-y += cpu.o obj-y += dram_init.o obj-y += syscon.o +obj-y += bsec.o ifdef CONFIG_SPL_BUILD obj-y += spl.o else obj-$(CONFIG_CMD_STM32PROG) += cmd_stm32prog/ -obj-y += bsec.o obj-$(CONFIG_CMD_STM32KEY) += cmd_stm32key.o obj-$(CONFIG_ARMV7_PSCI) += psci.o obj-$(CONFIG_TFABOOT) += boot_params.o diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c index fc39230113c..059ef0b1f58 100644 --- a/arch/arm/mach-stm32mp/bsec.c +++ b/arch/arm/mach-stm32mp/bsec.c @@ -474,20 +474,23 @@ static int stm32mp_bsec_ofdata_to_platdata(struct udevice *dev) return 0; } -#ifndef CONFIG_TFABOOT static int stm32mp_bsec_probe(struct udevice *dev) { +#if !defined(CONFIG_TFABOOT) && !defined(CONFIG_SPL_BUILD) int otp; struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); - /* update unlocked shadow for OTP cleared by the rom code */ + /* + * update unlocked shadow for OTP cleared by the rom code + * only executed in U-Boot proper when TF-A is not used + */ for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++) if (!bsec_read_SR_lock(plat->base, otp)) bsec_shadow_register(plat->base, otp); +#endif return 0; } -#endif static const struct udevice_id stm32mp_bsec_ids[] = { { .compatible = "st,stm32mp15-bsec" }, @@ -501,7 +504,5 @@ U_BOOT_DRIVER(stm32mp_bsec) = { .ofdata_to_platdata = stm32mp_bsec_ofdata_to_platdata, .platdata_auto_alloc_size = sizeof(struct stm32mp_bsec_platdata), .ops = &stm32mp_bsec_ops, -#ifndef CONFIG_TFABOOT .probe = stm32mp_bsec_probe, -#endif }; -- cgit v1.3.1 From 6f2e0ad1945a188d39e759f7b87a66cc9274ecc1 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 25 May 2020 12:19:42 +0200 Subject: ARM: dts: stm32: add cpufreq support on stm32mp15x This commit adds cpufreq support on stm32mp15x SOC. STM32 cpufreq uses operating points V2 bindings (no legacy). Nvmem cells have to be used to know the chip version and then which OPPs are available. Note that STM32 cpufreq driver is mainly based on "cpufreq-dt" driver. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- arch/arm/dts/stm32mp151.dtsi | 21 +++++++++++++++++++++ arch/arm/dts/stm32mp157c-ed1.dts | 8 ++++++++ arch/arm/dts/stm32mp15xx-dkx.dtsi | 8 ++++++++ 3 files changed, 37 insertions(+) diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi index 75d2c0d296e..d5216a18313 100644 --- a/arch/arm/dts/stm32mp151.dtsi +++ b/arch/arm/dts/stm32mp151.dtsi @@ -20,6 +20,24 @@ clock-frequency = <650000000>; device_type = "cpu"; reg = <0>; + operating-points-v2 = <&cpu0_opp_table>; + nvmem-cells = <&part_number_otp>; + nvmem-cell-names = "part_number"; + }; + }; + + cpu0_opp_table: cpu0-opp-table { + compatible = "operating-points-v2"; + opp-shared; + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + opp-microvolt = <1200000>; + opp-supported-hw = <0x1>; + }; + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1350000>; + opp-supported-hw = <0x2>; }; }; @@ -1522,6 +1540,9 @@ reg = <0x5c005000 0x400>; #address-cells = <1>; #size-cells = <1>; + part_number_otp: part_number_otp@4 { + reg = <0x4 0x1>; + }; ts_cal1: calib@5c { reg = <0x5c 0x2>; }; diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts index 186dc467544..c4c1202789d 100644 --- a/arch/arm/dts/stm32mp157c-ed1.dts +++ b/arch/arm/dts/stm32mp157c-ed1.dts @@ -107,6 +107,14 @@ }; }; +&cpu0{ + cpu-supply = <&vddcore>; +}; + +&cpu1{ + cpu-supply = <&vddcore>; +}; + &dac { pinctrl-names = "default"; pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>; diff --git a/arch/arm/dts/stm32mp15xx-dkx.dtsi b/arch/arm/dts/stm32mp15xx-dkx.dtsi index 7589c6f9dc5..e7a46e7b5fb 100644 --- a/arch/arm/dts/stm32mp15xx-dkx.dtsi +++ b/arch/arm/dts/stm32mp15xx-dkx.dtsi @@ -116,6 +116,14 @@ status = "okay"; }; +&cpu0{ + cpu-supply = <&vddcore>; +}; + +&cpu1{ + cpu-supply = <&vddcore>; +}; + ðernet0 { status = "okay"; pinctrl-0 = <ðernet0_rgmii_pins_a>; -- cgit v1.3.1 From 918e9c3d638722e5169091594846462e7af69f47 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 25 May 2020 12:19:43 +0200 Subject: board: st: create common file stpmic1.c Move function board_ddr_power_init() in a new file stpmic1 in board/st/common to avoid duplicated code in each board using stpmic1 Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- board/dhelectronics/dh_stm32mp1/Makefile | 2 +- board/st/common/Makefile | 1 + board/st/common/stpmic1.c | 164 +++++++++++++++++++++++++++++++ board/st/stm32mp1/board.c | 158 ----------------------------- 4 files changed, 166 insertions(+), 159 deletions(-) create mode 100644 board/st/common/stpmic1.c diff --git a/board/dhelectronics/dh_stm32mp1/Makefile b/board/dhelectronics/dh_stm32mp1/Makefile index e8f218da085..5758d9816bb 100644 --- a/board/dhelectronics/dh_stm32mp1/Makefile +++ b/board/dhelectronics/dh_stm32mp1/Makefile @@ -7,7 +7,7 @@ ifdef CONFIG_SPL_BUILD obj-y += ../../st/stm32mp1/spl.o endif -obj-y += ../../st/stm32mp1/board.o board.o +obj-y += ../../st/common/stpmic1.o board.o obj-$(CONFIG_SYS_MTDPARTS_RUNTIME) += ../../st/common/stm32mp_mtdparts.o obj-$(CONFIG_SET_DFU_ALT_INFO) += ../../st/common/stm32mp_dfu.o diff --git a/board/st/common/Makefile b/board/st/common/Makefile index aa030bacd81..012bfbbe8ee 100644 --- a/board/st/common/Makefile +++ b/board/st/common/Makefile @@ -4,6 +4,7 @@ # obj-$(CONFIG_CMD_STBOARD) += cmd_stboard.o +obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o ifeq ($(CONFIG_ARCH_STM32MP),y) obj-$(CONFIG_SYS_MTDPARTS_RUNTIME) += stm32mp_mtdparts.o diff --git a/board/st/common/stpmic1.c b/board/st/common/stpmic1.c new file mode 100644 index 00000000000..41111c5923b --- /dev/null +++ b/board/st/common/stpmic1.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include + +int board_ddr_power_init(enum ddr_type ddr_type) +{ + struct udevice *dev; + bool buck3_at_1800000v = false; + int ret; + u32 buck2; + + ret = uclass_get_device_by_driver(UCLASS_PMIC, + DM_GET_DRIVER(pmic_stpmic1), &dev); + if (ret) + /* No PMIC on board */ + return 0; + + switch (ddr_type) { + case STM32MP_DDR3: + /* VTT = Set LDO3 to sync mode */ + ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3)); + if (ret < 0) + return ret; + + ret &= ~STPMIC1_LDO3_MODE; + ret &= ~STPMIC1_LDO12356_VOUT_MASK; + ret |= STPMIC1_LDO_VOUT(STPMIC1_LDO3_DDR_SEL); + + ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3), + ret); + if (ret < 0) + return ret; + + /* VDD_DDR = Set BUCK2 to 1.35V */ + ret = pmic_clrsetbits(dev, + STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2), + STPMIC1_BUCK_VOUT_MASK, + STPMIC1_BUCK2_1350000V); + if (ret < 0) + return ret; + + /* Enable VDD_DDR = BUCK2 */ + ret = pmic_clrsetbits(dev, + STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2), + STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA); + if (ret < 0) + return ret; + + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); + + /* Enable VREF */ + ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR, + STPMIC1_VREF_ENA, STPMIC1_VREF_ENA); + if (ret < 0) + return ret; + + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); + + /* Enable VTT = LDO3 */ + ret = pmic_clrsetbits(dev, + STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3), + STPMIC1_LDO_ENA, STPMIC1_LDO_ENA); + if (ret < 0) + return ret; + + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); + + break; + + case STM32MP_LPDDR2_16: + case STM32MP_LPDDR2_32: + case STM32MP_LPDDR3_16: + case STM32MP_LPDDR3_32: + /* + * configure VDD_DDR1 = LDO3 + * Set LDO3 to 1.8V + * + bypass mode if BUCK3 = 1.8V + * + normal mode if BUCK3 != 1.8V + */ + ret = pmic_reg_read(dev, + STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK3)); + if (ret < 0) + return ret; + + if ((ret & STPMIC1_BUCK3_1800000V) == STPMIC1_BUCK3_1800000V) + buck3_at_1800000v = true; + + ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3)); + if (ret < 0) + return ret; + + ret &= ~STPMIC1_LDO3_MODE; + ret &= ~STPMIC1_LDO12356_VOUT_MASK; + ret |= STPMIC1_LDO3_1800000; + if (buck3_at_1800000v) + ret |= STPMIC1_LDO3_MODE; + + ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3), + ret); + if (ret < 0) + return ret; + + /* VDD_DDR2 : Set BUCK2 to 1.2V (16bits) or 1.25V (32 bits)*/ + switch (ddr_type) { + case STM32MP_LPDDR2_32: + case STM32MP_LPDDR3_32: + buck2 = STPMIC1_BUCK2_1250000V; + break; + default: + case STM32MP_LPDDR2_16: + case STM32MP_LPDDR3_16: + buck2 = STPMIC1_BUCK2_1200000V; + break; + } + + ret = pmic_clrsetbits(dev, + STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2), + STPMIC1_BUCK_VOUT_MASK, + buck2); + if (ret < 0) + return ret; + + /* Enable VDD_DDR1 = LDO3 */ + ret = pmic_clrsetbits(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3), + STPMIC1_LDO_ENA, STPMIC1_LDO_ENA); + if (ret < 0) + return ret; + + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); + + /* Enable VDD_DDR2 =BUCK2 */ + ret = pmic_clrsetbits(dev, + STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2), + STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA); + if (ret < 0) + return ret; + + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); + + /* Enable VREF */ + ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR, + STPMIC1_VREF_ENA, STPMIC1_VREF_ENA); + if (ret < 0) + return ret; + + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); + + break; + + default: + break; + }; + + return 0; +} diff --git a/board/st/stm32mp1/board.c b/board/st/stm32mp1/board.c index c218d37ecce..00c61c28864 100644 --- a/board/st/stm32mp1/board.c +++ b/board/st/stm32mp1/board.c @@ -4,13 +4,9 @@ */ #include -#include #include -#include #include #include -#include -#include #ifdef CONFIG_DEBUG_UART_BOARD_INIT void board_debug_uart_init(void) @@ -38,157 +34,3 @@ void board_debug_uart_init(void) #endif } #endif - -#ifdef CONFIG_PMIC_STPMIC1 -int board_ddr_power_init(enum ddr_type ddr_type) -{ - struct udevice *dev; - bool buck3_at_1800000v = false; - int ret; - u32 buck2; - - ret = uclass_get_device_by_driver(UCLASS_PMIC, - DM_GET_DRIVER(pmic_stpmic1), &dev); - if (ret) - /* No PMIC on board */ - return 0; - - switch (ddr_type) { - case STM32MP_DDR3: - /* VTT = Set LDO3 to sync mode */ - ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3)); - if (ret < 0) - return ret; - - ret &= ~STPMIC1_LDO3_MODE; - ret &= ~STPMIC1_LDO12356_VOUT_MASK; - ret |= STPMIC1_LDO_VOUT(STPMIC1_LDO3_DDR_SEL); - - ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3), - ret); - if (ret < 0) - return ret; - - /* VDD_DDR = Set BUCK2 to 1.35V */ - ret = pmic_clrsetbits(dev, - STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2), - STPMIC1_BUCK_VOUT_MASK, - STPMIC1_BUCK2_1350000V); - if (ret < 0) - return ret; - - /* Enable VDD_DDR = BUCK2 */ - ret = pmic_clrsetbits(dev, - STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2), - STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA); - if (ret < 0) - return ret; - - mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - - /* Enable VREF */ - ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR, - STPMIC1_VREF_ENA, STPMIC1_VREF_ENA); - if (ret < 0) - return ret; - - mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - - /* Enable VTT = LDO3 */ - ret = pmic_clrsetbits(dev, - STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3), - STPMIC1_LDO_ENA, STPMIC1_LDO_ENA); - if (ret < 0) - return ret; - - mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - - break; - - case STM32MP_LPDDR2_16: - case STM32MP_LPDDR2_32: - case STM32MP_LPDDR3_16: - case STM32MP_LPDDR3_32: - /* - * configure VDD_DDR1 = LDO3 - * Set LDO3 to 1.8V - * + bypass mode if BUCK3 = 1.8V - * + normal mode if BUCK3 != 1.8V - */ - ret = pmic_reg_read(dev, - STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK3)); - if (ret < 0) - return ret; - - if ((ret & STPMIC1_BUCK3_1800000V) == STPMIC1_BUCK3_1800000V) - buck3_at_1800000v = true; - - ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3)); - if (ret < 0) - return ret; - - ret &= ~STPMIC1_LDO3_MODE; - ret &= ~STPMIC1_LDO12356_VOUT_MASK; - ret |= STPMIC1_LDO3_1800000; - if (buck3_at_1800000v) - ret |= STPMIC1_LDO3_MODE; - - ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3), - ret); - if (ret < 0) - return ret; - - /* VDD_DDR2 : Set BUCK2 to 1.2V (16bits) or 1.25V (32 bits)*/ - switch (ddr_type) { - case STM32MP_LPDDR2_32: - case STM32MP_LPDDR3_32: - buck2 = STPMIC1_BUCK2_1250000V; - break; - default: - case STM32MP_LPDDR2_16: - case STM32MP_LPDDR3_16: - buck2 = STPMIC1_BUCK2_1200000V; - break; - } - - ret = pmic_clrsetbits(dev, - STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2), - STPMIC1_BUCK_VOUT_MASK, - buck2); - if (ret < 0) - return ret; - - /* Enable VDD_DDR1 = LDO3 */ - ret = pmic_clrsetbits(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3), - STPMIC1_LDO_ENA, STPMIC1_LDO_ENA); - if (ret < 0) - return ret; - - mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - - /* Enable VDD_DDR2 =BUCK2 */ - ret = pmic_clrsetbits(dev, - STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2), - STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA); - if (ret < 0) - return ret; - - mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - - /* Enable VREF */ - ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR, - STPMIC1_VREF_ENA, STPMIC1_VREF_ENA); - if (ret < 0) - return ret; - - mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - - break; - - default: - break; - }; - - return 0; -} -#endif -- cgit v1.3.1 From 37ad8377af00128adc47fb1192142ac9dfbf1f9d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 25 May 2020 12:19:44 +0200 Subject: stm32mp1: clk: configure pll1 with OPP The PLL1 node (st,pll1) is optional in device tree, the max supported frequency define in OPP node is used when the node is absent. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- doc/device-tree-bindings/clock/st,stm32mp1.txt | 4 + drivers/clk/clk_stm32mp1.c | 290 ++++++++++++++++++++++--- 2 files changed, 266 insertions(+), 28 deletions(-) diff --git a/doc/device-tree-bindings/clock/st,stm32mp1.txt b/doc/device-tree-bindings/clock/st,stm32mp1.txt index a3d427911d7..4d4136d2fce 100644 --- a/doc/device-tree-bindings/clock/st,stm32mp1.txt +++ b/doc/device-tree-bindings/clock/st,stm32mp1.txt @@ -87,6 +87,10 @@ Optional Properties: are listed with associated reg 0 to 3. PLLx is off when the associated node is absent or deactivated. + For PLL1, when the node is absent, the frequency of the OPP node is used + to compute the PLL setting (see compatible "operating-points-v2" in + opp/opp.txt for details). + Here are the available properties for each PLL node: - compatible: should be "st,stm32mp1-pll" diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index 6c5eddbd9a3..8acbad25f9a 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -644,8 +645,18 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { }; #ifdef STM32MP1_CLOCK_TREE_INIT + /* define characteristic of PLL according type */ +#define DIVM_MIN 0 +#define DIVM_MAX 63 #define DIVN_MIN 24 +#define DIVP_MIN 0 +#define DIVP_MAX 127 +#define FRAC_MAX 8192 + +#define PLL1600_VCO_MIN 800000000 +#define PLL1600_VCO_MAX 1600000000 + static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { [PLL_800] = { .refclk_min = 4, @@ -1190,6 +1201,208 @@ static ulong stm32mp1_clk_get_rate(struct clk *clk) } #ifdef STM32MP1_CLOCK_TREE_INIT + +bool stm32mp1_supports_opp(u32 opp_id, u32 cpu_type) +{ + unsigned int id; + + switch (opp_id) { + case 1: + case 2: + id = opp_id; + break; + default: + id = 1; /* default value */ + break; + } + + switch (cpu_type) { + case CPU_STM32MP157Fxx: + case CPU_STM32MP157Dxx: + case CPU_STM32MP153Fxx: + case CPU_STM32MP153Dxx: + case CPU_STM32MP151Fxx: + case CPU_STM32MP151Dxx: + return true; + default: + return id == 1; + } +} + +/* + * gets OPP parameters (frequency in KHz and voltage in mV) from + * an OPP table subnode. Platform HW support capabilities are also checked. + * Returns 0 on success and a negative FDT error code on failure. + */ +static int stm32mp1_get_opp(u32 cpu_type, ofnode subnode, + u32 *freq_khz, u32 *voltage_mv) +{ + u32 opp_hw; + u64 read_freq_64; + u32 read_voltage_32; + + *freq_khz = 0; + *voltage_mv = 0; + + opp_hw = ofnode_read_u32_default(subnode, "opp-supported-hw", 0); + if (opp_hw) + if (!stm32mp1_supports_opp(opp_hw, cpu_type)) + return -FDT_ERR_BADVALUE; + + read_freq_64 = ofnode_read_u64_default(subnode, "opp-hz", 0) / + 1000ULL; + read_voltage_32 = ofnode_read_u32_default(subnode, "opp-microvolt", 0) / + 1000U; + + if (!read_voltage_32 || !read_freq_64) + return -FDT_ERR_NOTFOUND; + + /* Frequency value expressed in KHz must fit on 32 bits */ + if (read_freq_64 > U32_MAX) + return -FDT_ERR_BADVALUE; + + /* Millivolt value must fit on 16 bits */ + if (read_voltage_32 > U16_MAX) + return -FDT_ERR_BADVALUE; + + *freq_khz = (u32)read_freq_64; + *voltage_mv = read_voltage_32; + + return 0; +} + +/* + * parses OPP table in DT and finds the parameters for the + * highest frequency supported by the HW platform. + * Returns 0 on success and a negative FDT error code on failure. + */ +int stm32mp1_get_max_opp_freq(struct stm32mp1_clk_priv *priv, u64 *freq_hz) +{ + ofnode node, subnode; + int ret; + u32 freq = 0U, voltage = 0U; + u32 cpu_type = get_cpu_type(); + + node = ofnode_by_compatible(ofnode_null(), "operating-points-v2"); + if (!ofnode_valid(node)) + return -FDT_ERR_NOTFOUND; + + ofnode_for_each_subnode(subnode, node) { + unsigned int read_freq; + unsigned int read_voltage; + + ret = stm32mp1_get_opp(cpu_type, subnode, + &read_freq, &read_voltage); + if (ret) + continue; + + if (read_freq > freq) { + freq = read_freq; + voltage = read_voltage; + } + } + + if (!freq || !voltage) + return -FDT_ERR_NOTFOUND; + + *freq_hz = (u64)1000U * freq; + + return 0; +} + +static int stm32mp1_pll1_opp(struct stm32mp1_clk_priv *priv, int clksrc, + u32 *pllcfg, u32 *fracv) +{ + u32 post_divm; + u32 input_freq; + u64 output_freq; + u64 freq; + u64 vco; + u32 divm, divn, divp, frac; + int i, ret; + u32 diff; + u32 best_diff = U32_MAX; + + /* PLL1 is 1600 */ + const u32 DIVN_MAX = stm32mp1_pll[PLL_1600].divn_max; + const u32 POST_DIVM_MIN = stm32mp1_pll[PLL_1600].refclk_min * 1000000U; + const u32 POST_DIVM_MAX = stm32mp1_pll[PLL_1600].refclk_max * 1000000U; + + ret = stm32mp1_get_max_opp_freq(priv, &output_freq); + if (ret) { + debug("PLL1 OPP configuration not found (%d).\n", ret); + return ret; + } + + switch (clksrc) { + case CLK_PLL12_HSI: + input_freq = stm32mp1_clk_get_fixed(priv, _HSI); + break; + case CLK_PLL12_HSE: + input_freq = stm32mp1_clk_get_fixed(priv, _HSE); + break; + default: + return -EINTR; + } + + /* Following parameters have always the same value */ + pllcfg[PLLCFG_Q] = 0; + pllcfg[PLLCFG_R] = 0; + pllcfg[PLLCFG_O] = PQR(1, 0, 0); + + for (divm = DIVM_MAX; divm >= DIVM_MIN; divm--) { + post_divm = (u32)(input_freq / (divm + 1)); + if (post_divm < POST_DIVM_MIN || post_divm > POST_DIVM_MAX) + continue; + + for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) { + freq = output_freq * (divm + 1) * (divp + 1); + divn = (u32)((freq / input_freq) - 1); + if (divn < DIVN_MIN || divn > DIVN_MAX) + continue; + + frac = (u32)(((freq * FRAC_MAX) / input_freq) - + ((divn + 1) * FRAC_MAX)); + /* 2 loops to refine the fractional part */ + for (i = 2; i != 0; i--) { + if (frac > FRAC_MAX) + break; + + vco = (post_divm * (divn + 1)) + + ((post_divm * (u64)frac) / + FRAC_MAX); + if (vco < (PLL1600_VCO_MIN / 2) || + vco > (PLL1600_VCO_MAX / 2)) { + frac++; + continue; + } + freq = vco / (divp + 1); + if (output_freq < freq) + diff = (u32)(freq - output_freq); + else + diff = (u32)(output_freq - freq); + if (diff < best_diff) { + pllcfg[PLLCFG_M] = divm; + pllcfg[PLLCFG_N] = divn; + pllcfg[PLLCFG_P] = divp; + *fracv = frac; + + if (diff == 0) + return 0; + + best_diff = diff; + } + frac++; + } + } + } + + if (best_diff == U32_MAX) + return -1; + + return 0; +} + static void stm32mp1_ls_osc_set(int enable, fdt_addr_t rcc, u32 offset, u32 mask_on) { @@ -1661,9 +1874,12 @@ static int stm32mp1_clktree(struct udevice *dev) unsigned int clksrc[CLKSRC_NB]; unsigned int clkdiv[CLKDIV_NB]; unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; - ofnode plloff[_PLL_NB]; - int ret, len; - uint i; + unsigned int pllfracv[_PLL_NB]; + unsigned int pllcsg[_PLL_NB][PLLCSG_NB]; + bool pllcfg_valid[_PLL_NB]; + bool pllcsg_set[_PLL_NB]; + int ret; + int i, len; int lse_css = 0; const u32 *pkcs_cell; @@ -1683,16 +1899,43 @@ static int stm32mp1_clktree(struct udevice *dev) /* check mandatory field in each pll */ for (i = 0; i < _PLL_NB; i++) { char name[12]; + ofnode node; sprintf(name, "st,pll@%d", i); - plloff[i] = dev_read_subnode(dev, name); - if (!ofnode_valid(plloff[i])) - continue; - ret = ofnode_read_u32_array(plloff[i], "cfg", - pllcfg[i], PLLCFG_NB); - if (ret < 0) { - debug("field cfg invalid: error %d\n", ret); - return -FDT_ERR_NOTFOUND; + node = dev_read_subnode(dev, name); + pllcfg_valid[i] = ofnode_valid(node); + pllcsg_set[i] = false; + if (pllcfg_valid[i]) { + debug("DT for PLL %d @ %s\n", i, name); + ret = ofnode_read_u32_array(node, "cfg", + pllcfg[i], PLLCFG_NB); + if (ret < 0) { + debug("field cfg invalid: error %d\n", ret); + return -FDT_ERR_NOTFOUND; + } + pllfracv[i] = ofnode_read_u32_default(node, "frac", 0); + + ret = ofnode_read_u32_array(node, "csg", pllcsg[i], + PLLCSG_NB); + if (!ret) { + pllcsg_set[i] = true; + } else if (ret != -FDT_ERR_NOTFOUND) { + debug("invalid csg node for pll@%d res=%d\n", + i, ret); + return ret; + } + } else if (i == _PLL1) { + /* use OPP for PLL1 for A7 CPU */ + debug("DT for PLL %d with OPP\n", i); + ret = stm32mp1_pll1_opp(priv, + clksrc[CLKSRC_PLL12], + pllcfg[i], + &pllfracv[i]); + if (ret) { + debug("PLL %d with OPP error = %d\n", i, ret); + return ret; + } + pllcfg_valid[i] = true; } } @@ -1778,29 +2021,18 @@ static int stm32mp1_clktree(struct udevice *dev) /* configure and start PLLs */ debug("configure PLLs\n"); for (i = 0; i < _PLL_NB; i++) { - u32 fracv; - u32 csg[PLLCSG_NB]; - - debug("configure PLL %d @ %d\n", i, - ofnode_to_offset(plloff[i])); - if (!ofnode_valid(plloff[i])) + if (!pllcfg_valid[i]) continue; - - fracv = ofnode_read_u32_default(plloff[i], "frac", 0); - pll_config(priv, i, pllcfg[i], fracv); - ret = ofnode_read_u32_array(plloff[i], "csg", csg, PLLCSG_NB); - if (!ret) { - pll_csg(priv, i, csg); - } else if (ret != -FDT_ERR_NOTFOUND) { - debug("invalid csg node for pll@%d res=%d\n", i, ret); - return ret; - } + debug("configure PLL %d\n", i); + pll_config(priv, i, pllcfg[i], pllfracv[i]); + if (pllcsg_set[i]) + pll_csg(priv, i, pllcsg[i]); pll_start(priv, i); } /* wait and start PLLs ouptut when ready */ for (i = 0; i < _PLL_NB; i++) { - if (!ofnode_valid(plloff[i])) + if (!pllcfg_valid[i]) continue; debug("output PLL %d\n", i); pll_output(priv, i, pllcfg[i][PLLCFG_O]); @@ -2050,6 +2282,8 @@ static int stm32mp1_clk_probe(struct udevice *dev) /* clock tree init is done only one time, before relocation */ if (!(gd->flags & GD_FLG_RELOC)) result = stm32mp1_clktree(dev); + if (result) + printf("clock tree initialization failed (%d)\n", result); #endif #ifndef CONFIG_SPL_BUILD -- cgit v1.3.1 From 4e62642aef59ef89e00fe05ef1c27f263d80bcf6 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 25 May 2020 12:19:45 +0200 Subject: arm: stm32mp: add weak function to save vddcore Add a weak functions to save the vddcore voltage value provided in the OPP node when the clock tree is initialized. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- arch/arm/mach-stm32mp/include/mach/sys_proto.h | 3 +++ drivers/clk/clk_stm32mp1.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h index 4b6c7b8bdd2..4149d3a1337 100644 --- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h +++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h @@ -48,3 +48,6 @@ void get_soc_name(char name[SOC_NAME_SIZE]); u32 get_bootmode(void); int setup_mac_address(void); + +/* board power management : configure vddcore according OPP */ +void board_vddcore_init(u32 voltage_mv); diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index 8acbad25f9a..c8840b9e5f1 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -1229,6 +1229,10 @@ bool stm32mp1_supports_opp(u32 opp_id, u32 cpu_type) } } +__weak void board_vddcore_init(u32 voltage_mv) +{ +} + /* * gets OPP parameters (frequency in KHz and voltage in mV) from * an OPP table subnode. Platform HW support capabilities are also checked. @@ -1306,6 +1310,7 @@ int stm32mp1_get_max_opp_freq(struct stm32mp1_clk_priv *priv, u64 *freq_hz) return -FDT_ERR_NOTFOUND; *freq_hz = (u64)1000U * freq; + board_vddcore_init(voltage); return 0; } -- cgit v1.3.1 From d1a4b09de6431fbc2f6a9dc53efe8d84cdd31134 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 25 May 2020 12:19:46 +0200 Subject: board: st: stpmic1: add function stpmic1_init Add a function stmpic_init to early initialize the PMIC STPMIC1 - keep vdd on during the reset cycle (to avoid issue when backup battery is absent) - Check if debug is enabled to program PMIC according to the bit This patch allows to remove the compilation of spl.c file from stm32mp1 board in dh_stm32mp1. CONFIG_SPL_BOARD_INIT is removed as the new function is called earlier in SPL, in the function board_early_init_f. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- arch/arm/mach-stm32mp/Kconfig | 1 - board/dhelectronics/dh_stm32mp1/Makefile | 4 ---- board/dhelectronics/dh_stm32mp1/board.c | 3 +++ board/st/common/stpmic1.c | 31 ++++++++++++++++++++++++ board/st/common/stpmic1.h | 6 +++++ board/st/stm32mp1/spl.c | 41 ++++++-------------------------- board/st/stm32mp1/stm32mp1.c | 6 +++++ configs/stm32mp15_basic_defconfig | 1 + 8 files changed, 54 insertions(+), 39 deletions(-) create mode 100644 board/st/common/stpmic1.h diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig index 6c995ed8d88..ea7d57477b5 100644 --- a/arch/arm/mach-stm32mp/Kconfig +++ b/arch/arm/mach-stm32mp/Kconfig @@ -1,7 +1,6 @@ if ARCH_STM32MP config SPL - select SPL_BOARD_INIT select SPL_CLK select SPL_DM select SPL_DM_SEQ_ALIAS diff --git a/board/dhelectronics/dh_stm32mp1/Makefile b/board/dhelectronics/dh_stm32mp1/Makefile index 5758d9816bb..b368b396a46 100644 --- a/board/dhelectronics/dh_stm32mp1/Makefile +++ b/board/dhelectronics/dh_stm32mp1/Makefile @@ -3,10 +3,6 @@ # Copyright (C) 2018, STMicroelectronics - All Rights Reserved # -ifdef CONFIG_SPL_BUILD -obj-y += ../../st/stm32mp1/spl.o -endif - obj-y += ../../st/common/stpmic1.o board.o obj-$(CONFIG_SYS_MTDPARTS_RUNTIME) += ../../st/common/stm32mp_mtdparts.o diff --git a/board/dhelectronics/dh_stm32mp1/board.c b/board/dhelectronics/dh_stm32mp1/board.c index 26e827bc384..0e745ec7336 100644 --- a/board/dhelectronics/dh_stm32mp1/board.c +++ b/board/dhelectronics/dh_stm32mp1/board.c @@ -41,6 +41,7 @@ #include #include #include +#include "../../st/common/stpmic1.h" /* SYSCFG registers */ #define SYSCFG_BOOTR 0x00 @@ -198,6 +199,8 @@ int board_stm32mp1_ddr_config_name_match(struct udevice *dev, int board_early_init_f(void) { + if (IS_ENABLED(CONFIG_SPL_BUILD)) + stpmic1_init(); board_get_coding_straps(); return 0; diff --git a/board/st/common/stpmic1.c b/board/st/common/stpmic1.c index 41111c5923b..85f950575f3 100644 --- a/board/st/common/stpmic1.c +++ b/board/st/common/stpmic1.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -162,3 +163,33 @@ int board_ddr_power_init(enum ddr_type ddr_type) return 0; } + +/* early init of PMIC */ +void stpmic1_init(void) +{ + struct udevice *dev; + + if (uclass_get_device_by_driver(UCLASS_PMIC, + DM_GET_DRIVER(pmic_stpmic1), &dev)) + return; + + /* Keep vdd on during the reset cycle */ + pmic_clrsetbits(dev, + STPMIC1_BUCKS_MRST_CR, + STPMIC1_MRST_BUCK(STPMIC1_BUCK3), + STPMIC1_MRST_BUCK(STPMIC1_BUCK3)); + + /* Check if debug is enabled to program PMIC according to the bit */ + if (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_DEBUG_ON) { + printf("Keep debug unit ON\n"); + + pmic_clrsetbits(dev, STPMIC1_BUCKS_MRST_CR, + STPMIC1_MRST_BUCK_DEBUG, + STPMIC1_MRST_BUCK_DEBUG); + + if (STPMIC1_MRST_LDO_DEBUG) + pmic_clrsetbits(dev, STPMIC1_LDOS_MRST_CR, + STPMIC1_MRST_LDO_DEBUG, + STPMIC1_MRST_LDO_DEBUG); + } +} diff --git a/board/st/common/stpmic1.h b/board/st/common/stpmic1.h new file mode 100644 index 00000000000..ecc32766970 --- /dev/null +++ b/board/st/common/stpmic1.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +void stpmic1_init(void); diff --git a/board/st/stm32mp1/spl.c b/board/st/stm32mp1/spl.c index e65ff288ea1..fa25cefd280 100644 --- a/board/st/stm32mp1/spl.c +++ b/board/st/stm32mp1/spl.c @@ -5,41 +5,14 @@ #include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include "../common/stpmic1.h" -void spl_board_init(void) +int board_early_init_f(void) { - /* Keep vdd on during the reset cycle */ -#if defined(CONFIG_PMIC_STPMIC1) && defined(CONFIG_SPL_POWER_SUPPORT) - struct udevice *dev; - int ret; + if (IS_ENABLED(CONFIG_PMIC_STPMIC1) && CONFIG_IS_ENABLED(POWER_SUPPORT)) + stpmic1_init(); - ret = uclass_get_device_by_driver(UCLASS_PMIC, - DM_GET_DRIVER(pmic_stpmic1), &dev); - if (!ret) - pmic_clrsetbits(dev, - STPMIC1_BUCKS_MRST_CR, - STPMIC1_MRST_BUCK(STPMIC1_BUCK3), - STPMIC1_MRST_BUCK(STPMIC1_BUCK3)); - - /* Check if debug is enabled to program PMIC according to the bit */ - if ((readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_DEBUG_ON) && !ret) { - printf("Keep debug unit ON\n"); - - pmic_clrsetbits(dev, STPMIC1_BUCKS_MRST_CR, - STPMIC1_MRST_BUCK_DEBUG, - STPMIC1_MRST_BUCK_DEBUG); - - if (STPMIC1_MRST_LDO_DEBUG) - pmic_clrsetbits(dev, STPMIC1_LDOS_MRST_CR, - STPMIC1_MRST_LDO_DEBUG, - STPMIC1_MRST_LDO_DEBUG); - } -#endif + return 0; } diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 4553329b250..4cea5bd0219 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -84,6 +84,12 @@ DECLARE_GLOBAL_DATA_PTR; #define USB_START_LOW_THRESHOLD_UV 1230000 #define USB_START_HIGH_THRESHOLD_UV 2150000 +int board_early_init_f(void) +{ + /* nothing to do, only used in SPL */ + return 0; +} + int checkboard(void) { int ret; diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index ecdbac65ffc..28363e900e2 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -18,6 +18,7 @@ CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1" CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y CONFIG_BOOTCOMMAND="run bootcmd_stm32mp" +CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=3 CONFIG_SPL_I2C_SUPPORT=y -- cgit v1.3.1 From 2f238327b7273656eb7670804fdb16de097b39b9 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 25 May 2020 12:19:47 +0200 Subject: board: stm32mp1: update vddcore in SPL For board using STPMIC1, the vddcore is provided by BUCK1 of STPMIC1 and need to be updated for 800MHz support and only after the clock tree initialization. The VDDCORE voltage value is provided by clock driver, saved in global variable opp_voltage_mv and udpated in SPL board_early_init_f(), just after clock tree initialization. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- board/dhelectronics/dh_stm32mp1/board.c | 9 ++++++++- board/st/common/stpmic1.c | 23 ++++++++++++++++++++++- board/st/common/stpmic1.h | 2 +- board/st/stm32mp1/spl.c | 11 ++++++++++- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/board/dhelectronics/dh_stm32mp1/board.c b/board/dhelectronics/dh_stm32mp1/board.c index 0e745ec7336..b2b4f3974d2 100644 --- a/board/dhelectronics/dh_stm32mp1/board.c +++ b/board/dhelectronics/dh_stm32mp1/board.c @@ -140,6 +140,7 @@ int checkboard(void) static u8 brdcode __section("data"); static u8 ddr3code __section("data"); static u8 somcode __section("data"); +static u32 opp_voltage_mv __section(".data"); static void board_get_coding_straps(void) { @@ -197,10 +198,16 @@ int board_stm32mp1_ddr_config_name_match(struct udevice *dev, return -EINVAL; } +void board_vddcore_init(u32 voltage_mv) +{ + if (IS_ENABLED(CONFIG_SPL_BUILD)) + opp_voltage_mv = voltage_mv; +} + int board_early_init_f(void) { if (IS_ENABLED(CONFIG_SPL_BUILD)) - stpmic1_init(); + stpmic1_init(opp_voltage_mv); board_get_coding_straps(); return 0; diff --git a/board/st/common/stpmic1.c b/board/st/common/stpmic1.c index 85f950575f3..3aa379e8a50 100644 --- a/board/st/common/stpmic1.c +++ b/board/st/common/stpmic1.c @@ -164,8 +164,25 @@ int board_ddr_power_init(enum ddr_type ddr_type) return 0; } +static int stmpic_buck1_set(struct udevice *dev, u32 voltage_mv) +{ + u32 value; + + /* VDDCORE= STMPCI1 BUCK1 ramp=+25mV, 5 => 725mV, 36 => 1500mV */ + value = ((voltage_mv - 725) / 25) + 5; + if (value < 5) + value = 5; + if (value > 36) + value = 36; + + return pmic_clrsetbits(dev, + STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK1), + STPMIC1_BUCK_VOUT_MASK, + STPMIC1_BUCK_VOUT(value)); +} + /* early init of PMIC */ -void stpmic1_init(void) +void stpmic1_init(u32 voltage_mv) { struct udevice *dev; @@ -173,6 +190,10 @@ void stpmic1_init(void) DM_GET_DRIVER(pmic_stpmic1), &dev)) return; + /* update VDDCORE = BUCK1 */ + if (voltage_mv) + stmpic_buck1_set(dev, voltage_mv); + /* Keep vdd on during the reset cycle */ pmic_clrsetbits(dev, STPMIC1_BUCKS_MRST_CR, diff --git a/board/st/common/stpmic1.h b/board/st/common/stpmic1.h index ecc32766970..b17d6f16338 100644 --- a/board/st/common/stpmic1.h +++ b/board/st/common/stpmic1.h @@ -3,4 +3,4 @@ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved */ -void stpmic1_init(void); +void stpmic1_init(u32 voltage_mv); diff --git a/board/st/stm32mp1/spl.c b/board/st/stm32mp1/spl.c index fa25cefd280..9a83da8fd30 100644 --- a/board/st/stm32mp1/spl.c +++ b/board/st/stm32mp1/spl.c @@ -9,10 +9,19 @@ #include #include "../common/stpmic1.h" +/* board early initialisation in board_f: need to use global variable */ +static u32 opp_voltage_mv __section(".data"); + +void board_vddcore_init(u32 voltage_mv) +{ + if (IS_ENABLED(CONFIG_PMIC_STPMIC1) && CONFIG_IS_ENABLED(POWER_SUPPORT)) + opp_voltage_mv = voltage_mv; +} + int board_early_init_f(void) { if (IS_ENABLED(CONFIG_PMIC_STPMIC1) && CONFIG_IS_ENABLED(POWER_SUPPORT)) - stpmic1_init(); + stpmic1_init(opp_voltage_mv); return 0; } -- cgit v1.3.1 From 4a87fea6de30b6e9c59a5abb6da1d0d84c984d15 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 25 May 2020 12:19:48 +0200 Subject: ARM: dts: stm32mp1: use OPP information for PLL1 settings in SPL This patch allows to switch the CPU frequency to 800MHz on the ST Microelectronics board (DK1/DK2 and EV1) or dh electronics SOM using the STM32MP15x SOC and when it is supported by the HW (for STM32MP15xD and STM32MP15xF). Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- arch/arm/dts/stm32mp15-u-boot.dtsi | 10 ++++++++++ arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi | 9 --------- arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi | 9 --------- arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi | 9 --------- arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi | 9 --------- 5 files changed, 10 insertions(+), 36 deletions(-) diff --git a/arch/arm/dts/stm32mp15-u-boot.dtsi b/arch/arm/dts/stm32mp15-u-boot.dtsi index a0d971ad88a..66be7df9ae7 100644 --- a/arch/arm/dts/stm32mp15-u-boot.dtsi +++ b/arch/arm/dts/stm32mp15-u-boot.dtsi @@ -88,6 +88,16 @@ u-boot,dm-pre-reloc; }; +&cpu0_opp_table { + u-boot,dm-spl; + opp-650000000 { + u-boot,dm-spl; + }; + opp-800000000 { + u-boot,dm-spl; + }; +}; + &gpioa { u-boot,dm-pre-reloc; }; diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index e13dade4633..7b8c1c1cc7f 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -133,15 +133,6 @@ CLK_LPTIM45_LSE >; - /* VCO = 1300.0 MHz => P = 650 (CPU) */ - pll1: st,pll@0 { - compatible = "st,stm32mp1-pll"; - reg = <0>; - cfg = < 2 80 0 0 0 PQR(1,0,0) >; - frac = < 0x800 >; - u-boot,dm-pre-reloc; - }; - /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ pll2: st,pll@1 { compatible = "st,stm32mp1-pll"; diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi index b16dc28d47a..ef3e7f45a36 100644 --- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi @@ -129,15 +129,6 @@ CLK_LPTIM45_LSE >; - /* VCO = 1300.0 MHz => P = 650 (CPU) */ - pll1: st,pll@0 { - compatible = "st,stm32mp1-pll"; - reg = <0>; - cfg = < 2 80 0 0 0 PQR(1,0,0) >; - frac = < 0x800 >; - u-boot,dm-pre-reloc; - }; - /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ pll2: st,pll@1 { compatible = "st,stm32mp1-pll"; diff --git a/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi b/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi index df63ad4a241..69c5af42415 100644 --- a/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi +++ b/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi @@ -235,15 +235,6 @@ CLK_LPTIM45_LSE >; - /* VCO = 1300.0 MHz => P = 650 (CPU) */ - pll1: st,pll@0 { - compatible = "st,stm32mp1-pll"; - reg = <0>; - cfg = < 2 80 0 0 0 PQR(1,0,0) >; - frac = < 0x800 >; - u-boot,dm-pre-reloc; - }; - /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ pll2: st,pll@1 { compatible = "st,stm32mp1-pll"; diff --git a/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi b/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi index bd4c2adc358..7529068c517 100644 --- a/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi +++ b/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi @@ -114,15 +114,6 @@ CLK_LPTIM45_LSE >; - /* VCO = 1300.0 MHz => P = 650 (CPU) */ - pll1: st,pll@0 { - compatible = "st,stm32mp1-pll"; - reg = <0>; - cfg = < 2 80 0 0 0 PQR(1,0,0) >; - frac = < 0x800 >; - u-boot,dm-pre-reloc; - }; - /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ pll2: st,pll@1 { compatible = "st,stm32mp1-pll"; -- cgit v1.3.1 From 4fb46816c7e2defe01213c09742e06322a9e5f62 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 25 May 2020 12:19:49 +0200 Subject: board: stm32mp1: move the function board_debug_uart_init in spl.c Move the debug function board_debug_uart_init in spl.c as the debug_uart_init() function is called in arch_cpu_init() only for SPL and remove the board.c file. For TFABOOT, the UART TX pin configuration is done in TF-A. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- board/st/stm32mp1/Makefile | 2 -- board/st/stm32mp1/spl.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/board/st/stm32mp1/Makefile b/board/st/stm32mp1/Makefile index 8188075b1a3..65560df2900 100644 --- a/board/st/stm32mp1/Makefile +++ b/board/st/stm32mp1/Makefile @@ -8,5 +8,3 @@ obj-y += spl.o else obj-y += stm32mp1.o endif - -obj-y += board.o diff --git a/board/st/stm32mp1/spl.c b/board/st/stm32mp1/spl.c index 9a83da8fd30..a6a41780c96 100644 --- a/board/st/stm32mp1/spl.c +++ b/board/st/stm32mp1/spl.c @@ -6,7 +6,10 @@ #include #include #include +#include #include +#include +#include #include "../common/stpmic1.h" /* board early initialisation in board_f: need to use global variable */ @@ -25,3 +28,28 @@ int board_early_init_f(void) return 0; } + +#ifdef CONFIG_DEBUG_UART_BOARD_INIT +void board_debug_uart_init(void) +{ +#if (CONFIG_DEBUG_UART_BASE == STM32_UART4_BASE) + +#define RCC_MP_APB1ENSETR (STM32_RCC_BASE + 0x0A00) +#define RCC_MP_AHB4ENSETR (STM32_RCC_BASE + 0x0A28) + + /* UART4 clock enable */ + setbits_le32(RCC_MP_APB1ENSETR, BIT(16)); + +#define GPIOG_BASE 0x50008000 + /* GPIOG clock enable */ + writel(BIT(6), RCC_MP_AHB4ENSETR); + /* GPIO configuration for ST boards: Uart4 TX = G11 */ + writel(0xffbfffff, GPIOG_BASE + 0x00); + writel(0x00006000, GPIOG_BASE + 0x24); +#else + +#error("CONFIG_DEBUG_UART_BASE: not supported value") + +#endif +} +#endif -- cgit v1.3.1 From 9ebc326c08d9acc0939977d26435b6f6755596b0 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 4 Jun 2020 14:30:23 +0200 Subject: configs: stm32mp1: activate CONFIG_GPIO_HOG This patch activates the new configuration CONFIG_GPIO_HOG. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- configs/stm32mp15_basic_defconfig | 1 + configs/stm32mp15_trusted_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index 28363e900e2..7347070c881 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -76,6 +76,7 @@ CONFIG_FASTBOOT_BUF_SIZE=0x02000000 CONFIG_FASTBOOT_USB_DEV=1 CONFIG_FASTBOOT_FLASH=y CONFIG_FASTBOOT_FLASH_MMC_DEV=1 +CONFIG_GPIO_HOG=y CONFIG_DM_HWSPINLOCK=y CONFIG_HWSPINLOCK_STM32=y CONFIG_DM_I2C=y diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index ca4a10813b7..97a27986a9f 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -59,6 +59,7 @@ CONFIG_FASTBOOT_BUF_SIZE=0x02000000 CONFIG_FASTBOOT_USB_DEV=1 CONFIG_FASTBOOT_FLASH=y CONFIG_FASTBOOT_FLASH_MMC_DEV=1 +CONFIG_GPIO_HOG=y CONFIG_DM_HWSPINLOCK=y CONFIG_HWSPINLOCK_STM32=y CONFIG_DM_I2C=y -- cgit v1.3.1 From 29e4ce3c970f7a183d1218a78d82891d07bf801d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 4 Jun 2020 14:30:24 +0200 Subject: board: stm32mp1: update the gpio hog support This patch updates the current gpio hog implementation and uses the new API gpio_hog_probe_all(), activated with CONFIG_GPIO_HOG. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- board/st/stm32mp1/stm32mp1.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 4cea5bd0219..c5c89d27e52 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -670,17 +670,11 @@ static void board_ev1_init(void) /* board dependent setup after realloc */ int board_init(void) { - struct udevice *dev; - /* address of boot parameters */ gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100; - /* probe all PINCTRL for hog */ - for (uclass_first_device(UCLASS_PINCTRL, &dev); - dev; - uclass_next_device(&dev)) { - pr_debug("probe pincontrol = %s\n", dev->name); - } + if (CONFIG_IS_ENABLED(DM_GPIO_HOG)) + gpio_hog_probe_all(); board_key_check(); -- cgit v1.3.1 From f13ff88b61c32ac8f0e9068c41328b265ef619eb Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 4 Jun 2020 14:30:25 +0200 Subject: gpio: stm32: add ops set_dir_flags Manage flags for GPIO configuration: - open_drain, open_source, push_pull - pull_up, pull_down Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/gpio/stm32_gpio.c | 90 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c index 4f710b6b6af..f120ee98086 100644 --- a/drivers/gpio/stm32_gpio.c +++ b/drivers/gpio/stm32_gpio.c @@ -18,9 +18,48 @@ #include #include -#define MODE_BITS(gpio_pin) (gpio_pin * 2) +#define MODE_BITS(gpio_pin) ((gpio_pin) * 2) #define MODE_BITS_MASK 3 -#define BSRR_BIT(gpio_pin, value) BIT(gpio_pin + (value ? 0 : 16)) +#define BSRR_BIT(gpio_pin, value) BIT((gpio_pin) + (value ? 0 : 16)) + +#define PUPD_BITS(gpio_pin) ((gpio_pin) * 2) +#define PUPD_MASK 3 + +#define OTYPE_BITS(gpio_pin) (gpio_pin) +#define OTYPE_MSK 1 + +static void stm32_gpio_set_moder(struct stm32_gpio_regs *regs, + int idx, + int mode) +{ + int bits_index; + int mask; + + bits_index = MODE_BITS(idx); + mask = MODE_BITS_MASK << bits_index; + + clrsetbits_le32(®s->moder, mask, mode << bits_index); +} + +static void stm32_gpio_set_otype(struct stm32_gpio_regs *regs, + int idx, + enum stm32_gpio_otype otype) +{ + int bits; + + bits = OTYPE_BITS(idx); + clrsetbits_le32(®s->otyper, OTYPE_MSK << bits, otype << bits); +} + +static void stm32_gpio_set_pupd(struct stm32_gpio_regs *regs, + int idx, + enum stm32_gpio_pupd pupd) +{ + int bits; + + bits = PUPD_BITS(idx); + clrsetbits_le32(®s->pupdr, PUPD_MASK << bits, pupd << bits); +} /* * convert gpio offset to gpio index taking into account gpio holes @@ -47,18 +86,13 @@ static int stm32_gpio_direction_input(struct udevice *dev, unsigned offset) { struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; - int bits_index; - int mask; int idx; idx = stm32_offset_to_index(dev, offset); if (idx < 0) return idx; - bits_index = MODE_BITS(idx); - mask = MODE_BITS_MASK << bits_index; - - clrsetbits_le32(®s->moder, mask, STM32_GPIO_MODE_IN << bits_index); + stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_IN); return 0; } @@ -68,18 +102,13 @@ static int stm32_gpio_direction_output(struct udevice *dev, unsigned offset, { struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; - int bits_index; - int mask; int idx; idx = stm32_offset_to_index(dev, offset); if (idx < 0) return idx; - bits_index = MODE_BITS(idx); - mask = MODE_BITS_MASK << bits_index; - - clrsetbits_le32(®s->moder, mask, STM32_GPIO_MODE_OUT << bits_index); + stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT); writel(BSRR_BIT(idx, value), ®s->bsrr); @@ -141,12 +170,45 @@ static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset) return GPIOF_FUNC; } +static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, + ulong flags) +{ + struct stm32_gpio_priv *priv = dev_get_priv(dev); + struct stm32_gpio_regs *regs = priv->regs; + int idx; + + idx = stm32_offset_to_index(dev, offset); + if (idx < 0) + return idx; + + if (flags & GPIOD_IS_OUT) { + int value = GPIOD_FLAGS_OUTPUT(flags); + + if (flags & GPIOD_OPEN_DRAIN) + stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_OD); + else + stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_PP); + stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT); + writel(BSRR_BIT(idx, value), ®s->bsrr); + + } else if (flags & GPIOD_IS_IN) { + stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_IN); + if (flags & GPIOD_PULL_UP) + stm32_gpio_set_pupd(regs, idx, STM32_GPIO_PUPD_UP); + else if (flags & GPIOD_PULL_DOWN) + stm32_gpio_set_pupd(regs, idx, STM32_GPIO_PUPD_DOWN); + } + + return 0; +} + static const struct dm_gpio_ops gpio_stm32_ops = { .direction_input = stm32_gpio_direction_input, .direction_output = stm32_gpio_direction_output, .get_value = stm32_gpio_get_value, .set_value = stm32_gpio_set_value, .get_function = stm32_gpio_get_function, + .set_dir_flags = stm32_gpio_set_dir_flags, }; static int gpio_stm32_probe(struct udevice *dev) -- cgit v1.3.1 From 43efbb6a3ebf0223f9eab8d45916f602d876319f Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 4 Jun 2020 14:30:26 +0200 Subject: gpio: stm32: add ops get_dir_flags Add ops get_dir_flags() to read dir flags from GPIO registers. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/gpio/stm32_gpio.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c index f120ee98086..5bff27f75b5 100644 --- a/drivers/gpio/stm32_gpio.c +++ b/drivers/gpio/stm32_gpio.c @@ -41,6 +41,11 @@ static void stm32_gpio_set_moder(struct stm32_gpio_regs *regs, clrsetbits_le32(®s->moder, mask, mode << bits_index); } +static int stm32_gpio_get_moder(struct stm32_gpio_regs *regs, int idx) +{ + return (readl(®s->moder) >> MODE_BITS(idx)) & MODE_BITS_MASK; +} + static void stm32_gpio_set_otype(struct stm32_gpio_regs *regs, int idx, enum stm32_gpio_otype otype) @@ -51,6 +56,12 @@ static void stm32_gpio_set_otype(struct stm32_gpio_regs *regs, clrsetbits_le32(®s->otyper, OTYPE_MSK << bits, otype << bits); } +static enum stm32_gpio_otype stm32_gpio_get_otype(struct stm32_gpio_regs *regs, + int idx) +{ + return (readl(®s->otyper) >> OTYPE_BITS(idx)) & OTYPE_MSK; +} + static void stm32_gpio_set_pupd(struct stm32_gpio_regs *regs, int idx, enum stm32_gpio_pupd pupd) @@ -61,6 +72,12 @@ static void stm32_gpio_set_pupd(struct stm32_gpio_regs *regs, clrsetbits_le32(®s->pupdr, PUPD_MASK << bits, pupd << bits); } +static enum stm32_gpio_pupd stm32_gpio_get_pupd(struct stm32_gpio_regs *regs, + int idx) +{ + return (readl(®s->pupdr) >> PUPD_BITS(idx)) & PUPD_MASK; +} + /* * convert gpio offset to gpio index taking into account gpio holes * into gpio bank @@ -202,6 +219,47 @@ static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, return 0; } +static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset, + ulong *flags) +{ + struct stm32_gpio_priv *priv = dev_get_priv(dev); + struct stm32_gpio_regs *regs = priv->regs; + int idx; + ulong dir_flags = 0; + + idx = stm32_offset_to_index(dev, offset); + if (idx < 0) + return idx; + + switch (stm32_gpio_get_moder(regs, idx)) { + case STM32_GPIO_MODE_OUT: + dir_flags |= GPIOD_IS_OUT; + if (stm32_gpio_get_otype(regs, idx) == STM32_GPIO_OTYPE_OD) + dir_flags |= GPIOD_OPEN_DRAIN; + if (readl(®s->idr) & BIT(idx)) + dir_flags |= GPIOD_IS_OUT_ACTIVE; + break; + case STM32_GPIO_MODE_IN: + dir_flags |= GPIOD_IS_IN; + switch (stm32_gpio_get_pupd(regs, idx)) { + case STM32_GPIO_PUPD_UP: + dir_flags |= GPIOD_PULL_UP; + break; + case STM32_GPIO_PUPD_DOWN: + dir_flags |= GPIOD_PULL_DOWN; + break; + default: + break; + } + break; + default: + break; + } + *flags = dir_flags; + + return 0; +} + static const struct dm_gpio_ops gpio_stm32_ops = { .direction_input = stm32_gpio_direction_input, .direction_output = stm32_gpio_direction_output, @@ -209,6 +267,7 @@ static const struct dm_gpio_ops gpio_stm32_ops = { .set_value = stm32_gpio_set_value, .get_function = stm32_gpio_get_function, .set_dir_flags = stm32_gpio_set_dir_flags, + .get_dir_flags = stm32_gpio_get_dir_flags, }; static int gpio_stm32_probe(struct udevice *dev) -- cgit v1.3.1 From 84115cd06648f45e1496e3a55b08a654f8e3a258 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 4 Jun 2020 14:30:27 +0200 Subject: gpio: stmfx: move function to prepare new ops introduction Move the functions stmfx_pinctrl_set_pupd and stmfx_pinctrl_set_type; they can be used by the new ops get_dir_flags and set_dir_flags introduced by next patch. No functional change. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/pinctrl/pinctrl-stmfx.c | 60 ++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index a3240ccd5a0..d74121725c3 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -74,6 +74,36 @@ static int stmfx_write(struct udevice *dev, uint offset, unsigned int val) return dm_i2c_reg_write(dev_get_parent(dev), offset, val); } +static int stmfx_pinctrl_set_pupd(struct udevice *dev, + unsigned int pin, u32 pupd) +{ + u8 reg = STMFX_REG_GPIO_PUPD + get_reg(pin); + u32 mask = get_mask(pin); + int ret; + + ret = stmfx_read(dev, reg); + if (ret < 0) + return ret; + ret = (ret & ~mask) | (pupd ? mask : 0); + + return stmfx_write(dev, reg, ret); +} + +static int stmfx_pinctrl_set_type(struct udevice *dev, + unsigned int pin, u32 type) +{ + u8 reg = STMFX_REG_GPIO_TYPE + get_reg(pin); + u32 mask = get_mask(pin); + int ret; + + ret = stmfx_read(dev, reg); + if (ret < 0) + return ret; + ret = (ret & ~mask) | (type ? mask : 0); + + return stmfx_write(dev, reg, ret); +} + static int stmfx_gpio_get(struct udevice *dev, unsigned int offset) { u32 reg = STMFX_REG_GPIO_STATE + get_reg(offset); @@ -190,36 +220,6 @@ static const struct pinconf_param stmfx_pinctrl_conf_params[] = { { "output-low", PIN_CONFIG_OUTPUT, 0 }, }; -static int stmfx_pinctrl_set_pupd(struct udevice *dev, - unsigned int pin, u32 pupd) -{ - u8 reg = STMFX_REG_GPIO_PUPD + get_reg(pin); - u32 mask = get_mask(pin); - int ret; - - ret = stmfx_read(dev, reg); - if (ret < 0) - return ret; - ret = (ret & ~mask) | (pupd ? mask : 0); - - return stmfx_write(dev, reg, ret); -} - -static int stmfx_pinctrl_set_type(struct udevice *dev, - unsigned int pin, u32 type) -{ - u8 reg = STMFX_REG_GPIO_TYPE + get_reg(pin); - u32 mask = get_mask(pin); - int ret; - - ret = stmfx_read(dev, reg); - if (ret < 0) - return ret; - ret = (ret & ~mask) | (type ? mask : 0); - - return stmfx_write(dev, reg, ret); -} - static int stmfx_pinctrl_conf_set(struct udevice *dev, unsigned int pin, unsigned int param, unsigned int arg) { -- cgit v1.3.1 From 067c7398d5748d1b29df6aa1d5059a528310e4f7 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 4 Jun 2020 14:30:28 +0200 Subject: gpio: stmfx: rename function used to change pin configuration Rename the two function used to change the pin configuration from stmfx_pinctrl_.. stmfx_conf_... to clarify the function usage. No functional change. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/pinctrl/pinctrl-stmfx.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index d74121725c3..657ca2e2408 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -74,8 +74,7 @@ static int stmfx_write(struct udevice *dev, uint offset, unsigned int val) return dm_i2c_reg_write(dev_get_parent(dev), offset, val); } -static int stmfx_pinctrl_set_pupd(struct udevice *dev, - unsigned int pin, u32 pupd) +static int stmfx_conf_set_pupd(struct udevice *dev, unsigned int pin, u32 pupd) { u8 reg = STMFX_REG_GPIO_PUPD + get_reg(pin); u32 mask = get_mask(pin); @@ -89,8 +88,7 @@ static int stmfx_pinctrl_set_pupd(struct udevice *dev, return stmfx_write(dev, reg, ret); } -static int stmfx_pinctrl_set_type(struct udevice *dev, - unsigned int pin, u32 type) +static int stmfx_conf_set_type(struct udevice *dev, unsigned int pin, u32 type) { u8 reg = STMFX_REG_GPIO_TYPE + get_reg(pin); u32 mask = get_mask(pin); @@ -235,22 +233,22 @@ static int stmfx_pinctrl_conf_set(struct udevice *dev, unsigned int pin, case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: case PIN_CONFIG_BIAS_DISABLE: case PIN_CONFIG_DRIVE_PUSH_PULL: - ret = stmfx_pinctrl_set_type(dev, pin, 0); + ret = stmfx_conf_set_type(dev, pin, 0); break; case PIN_CONFIG_BIAS_PULL_DOWN: - ret = stmfx_pinctrl_set_type(dev, pin, 1); + ret = stmfx_conf_set_type(dev, pin, 1); if (ret) return ret; - ret = stmfx_pinctrl_set_pupd(dev, pin, 0); + ret = stmfx_conf_set_pupd(dev, pin, 0); break; case PIN_CONFIG_BIAS_PULL_UP: - ret = stmfx_pinctrl_set_type(dev, pin, 1); + ret = stmfx_conf_set_type(dev, pin, 1); if (ret) return ret; - ret = stmfx_pinctrl_set_pupd(dev, pin, 1); + ret = stmfx_conf_set_pupd(dev, pin, 1); break; case PIN_CONFIG_DRIVE_OPEN_DRAIN: - ret = stmfx_pinctrl_set_type(dev, pin, 1); + ret = stmfx_conf_set_type(dev, pin, 1); break; case PIN_CONFIG_OUTPUT: ret = stmfx_gpio_direction_output(plat->gpio, pin, arg); -- cgit v1.3.1 From fabb6e14c86d8d38beaaade8bc18a678cdc06c0a Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 4 Jun 2020 14:30:29 +0200 Subject: gpio: stmfx: add function stmfx_read_reg and stmfx_write_reg Add the helper functions stmfx_read_reg() and stmfx_write_reg() to avoid duplicated code for access to stmfx's register with mask. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/pinctrl/pinctrl-stmfx.c | 68 ++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index 657ca2e2408..5d15424b845 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -74,43 +74,49 @@ static int stmfx_write(struct udevice *dev, uint offset, unsigned int val) return dm_i2c_reg_write(dev_get_parent(dev), offset, val); } -static int stmfx_conf_set_pupd(struct udevice *dev, unsigned int pin, u32 pupd) +static int stmfx_read_reg(struct udevice *dev, u8 reg_base, uint offset) { - u8 reg = STMFX_REG_GPIO_PUPD + get_reg(pin); - u32 mask = get_mask(pin); + u8 reg = reg_base + get_reg(offset); + u32 mask = get_mask(offset); int ret; ret = stmfx_read(dev, reg); if (ret < 0) return ret; - ret = (ret & ~mask) | (pupd ? mask : 0); - return stmfx_write(dev, reg, ret); + return ret < 0 ? ret : !!(ret & mask); } -static int stmfx_conf_set_type(struct udevice *dev, unsigned int pin, u32 type) +static int stmfx_write_reg(struct udevice *dev, u8 reg_base, uint offset, + uint val) { - u8 reg = STMFX_REG_GPIO_TYPE + get_reg(pin); - u32 mask = get_mask(pin); + u8 reg = reg_base + get_reg(offset); + u32 mask = get_mask(offset); int ret; ret = stmfx_read(dev, reg); if (ret < 0) return ret; - ret = (ret & ~mask) | (type ? mask : 0); + ret = (ret & ~mask) | (val ? mask : 0); return stmfx_write(dev, reg, ret); } -static int stmfx_gpio_get(struct udevice *dev, unsigned int offset) +static int stmfx_conf_set_pupd(struct udevice *dev, unsigned int offset, + uint pupd) { - u32 reg = STMFX_REG_GPIO_STATE + get_reg(offset); - u32 mask = get_mask(offset); - int ret; + return stmfx_write_reg(dev, STMFX_REG_GPIO_PUPD, offset, pupd); +} - ret = stmfx_read(dev, reg); +static int stmfx_conf_set_type(struct udevice *dev, unsigned int offset, + uint type) +{ + return stmfx_write_reg(dev, STMFX_REG_GPIO_TYPE, offset, type); +} - return ret < 0 ? ret : !!(ret & mask); +static int stmfx_gpio_get(struct udevice *dev, unsigned int offset) +{ + return stmfx_read_reg(dev, STMFX_REG_GPIO_STATE, offset); } static int stmfx_gpio_set(struct udevice *dev, unsigned int offset, int value) @@ -123,50 +129,28 @@ static int stmfx_gpio_set(struct udevice *dev, unsigned int offset, int value) static int stmfx_gpio_get_function(struct udevice *dev, unsigned int offset) { - u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset); - u32 mask = get_mask(offset); - int ret; - - ret = stmfx_read(dev, reg); + int ret = stmfx_read_reg(dev, STMFX_REG_GPIO_DIR, offset); if (ret < 0) return ret; /* On stmfx, gpio pins direction is (0)input, (1)output. */ - return ret & mask ? GPIOF_OUTPUT : GPIOF_INPUT; + return ret ? GPIOF_OUTPUT : GPIOF_INPUT; } static int stmfx_gpio_direction_input(struct udevice *dev, unsigned int offset) { - u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset); - u32 mask = get_mask(offset); - int ret; - - ret = stmfx_read(dev, reg); - if (ret < 0) - return ret; - - ret &= ~mask; - - return stmfx_write(dev, reg, ret & ~mask); + return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 0); } static int stmfx_gpio_direction_output(struct udevice *dev, unsigned int offset, int value) { - u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset); - u32 mask = get_mask(offset); - int ret; - - ret = stmfx_gpio_set(dev, offset, value); - if (ret < 0) - return ret; - - ret = stmfx_read(dev, reg); + int ret = stmfx_gpio_set(dev, offset, value); if (ret < 0) return ret; - return stmfx_write(dev, reg, ret | mask); + return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 1); } static int stmfx_gpio_probe(struct udevice *dev) -- cgit v1.3.1 From 22b3fe4224a9929d025767ec600226de984d0246 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 4 Jun 2020 14:30:30 +0200 Subject: gpio: stmfx: add ops set_dir_flag Manage the flags for GPIO configuration: - open_drain, push_pull - pull_up, pull_down Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/pinctrl/pinctrl-stmfx.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index 5d15424b845..88df9e61a73 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -153,6 +153,42 @@ static int stmfx_gpio_direction_output(struct udevice *dev, return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 1); } +static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, + ulong flags) +{ + int ret = -ENOTSUPP; + + if (flags & GPIOD_IS_OUT) { + if (flags & GPIOD_OPEN_SOURCE) + return -ENOTSUPP; + if (flags & GPIOD_OPEN_DRAIN) + ret = stmfx_conf_set_type(dev, offset, 0); + else /* PUSH-PULL */ + ret = stmfx_conf_set_type(dev, offset, 1); + if (ret) + return ret; + ret = stmfx_gpio_direction_output(dev, offset, + GPIOD_FLAGS_OUTPUT(flags)); + } else if (flags & GPIOD_IS_IN) { + ret = stmfx_gpio_direction_input(dev, offset); + if (ret) + return ret; + if (flags & GPIOD_PULL_UP) { + ret = stmfx_conf_set_type(dev, offset, 1); + if (ret) + return ret; + ret = stmfx_conf_set_pupd(dev, offset, 1); + } else if (flags & GPIOD_PULL_DOWN) { + ret = stmfx_conf_set_type(dev, offset, 1); + if (ret) + return ret; + ret = stmfx_conf_set_pupd(dev, offset, 0); + } + } + + return ret; +} + static int stmfx_gpio_probe(struct udevice *dev) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); @@ -181,6 +217,7 @@ static const struct dm_gpio_ops stmfx_gpio_ops = { .get_function = stmfx_gpio_get_function, .direction_input = stmfx_gpio_direction_input, .direction_output = stmfx_gpio_direction_output, + .set_dir_flags = stmfx_gpio_set_dir_flags, }; U_BOOT_DRIVER(stmfx_gpio) = { -- cgit v1.3.1 From 8d895efffe2313acc419caee53414f2903b8a39c Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 4 Jun 2020 14:30:31 +0200 Subject: gpio: stmfx: add ops get_dir_flags Add support of ops get_dir_flags() to read dir flags from STMFX registers. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/pinctrl/pinctrl-stmfx.c | 50 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index 88df9e61a73..1d326ecf17a 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -108,12 +108,22 @@ static int stmfx_conf_set_pupd(struct udevice *dev, unsigned int offset, return stmfx_write_reg(dev, STMFX_REG_GPIO_PUPD, offset, pupd); } +static int stmfx_conf_get_pupd(struct udevice *dev, unsigned int offset) +{ + return stmfx_read_reg(dev, STMFX_REG_GPIO_PUPD, offset); +} + static int stmfx_conf_set_type(struct udevice *dev, unsigned int offset, uint type) { return stmfx_write_reg(dev, STMFX_REG_GPIO_TYPE, offset, type); } +static int stmfx_conf_get_type(struct udevice *dev, unsigned int offset) +{ + return stmfx_read_reg(dev, STMFX_REG_GPIO_TYPE, offset); +} + static int stmfx_gpio_get(struct udevice *dev, unsigned int offset) { return stmfx_read_reg(dev, STMFX_REG_GPIO_STATE, offset); @@ -189,6 +199,45 @@ static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, return ret; } +static int stmfx_gpio_get_dir_flags(struct udevice *dev, unsigned int offset, + ulong *flags) +{ + ulong dir_flags = 0; + int ret; + + if (stmfx_gpio_get_function(dev, offset) == GPIOF_OUTPUT) { + dir_flags |= GPIOD_IS_OUT; + ret = stmfx_conf_get_type(dev, offset); + if (ret < 0) + return ret; + if (ret == 0) + dir_flags |= GPIOD_OPEN_DRAIN; + /* 1 = push-pull (default), open source not supported */ + ret = stmfx_gpio_get(dev, offset); + if (ret < 0) + return ret; + if (ret) + dir_flags |= GPIOD_IS_OUT_ACTIVE; + } else { + dir_flags |= GPIOD_IS_IN; + ret = stmfx_conf_get_type(dev, offset); + if (ret < 0) + return ret; + if (ret == 1) { + ret = stmfx_conf_get_pupd(dev, offset); + if (ret < 0) + return ret; + if (ret == 1) + dir_flags |= GPIOD_PULL_UP; + else + dir_flags |= GPIOD_PULL_DOWN; + } + } + *flags = dir_flags; + + return 0; +} + static int stmfx_gpio_probe(struct udevice *dev) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); @@ -218,6 +267,7 @@ static const struct dm_gpio_ops stmfx_gpio_ops = { .direction_input = stmfx_gpio_direction_input, .direction_output = stmfx_gpio_direction_output, .set_dir_flags = stmfx_gpio_set_dir_flags, + .get_dir_flags = stmfx_gpio_get_dir_flags, }; U_BOOT_DRIVER(stmfx_gpio) = { -- cgit v1.3.1 From 5593333c2e4f674210a7415b6f61c16f7f3a4593 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 4 Jun 2020 14:30:32 +0200 Subject: pinctrl: stmfx: add information on pin configuration Add information on pin configuration used for pinmux command. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/pinctrl/pinctrl-stmfx.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index 1d326ecf17a..c2ea82770e6 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -358,6 +358,34 @@ static const char *stmfx_pinctrl_get_pin_name(struct udevice *dev, return pin_name; } +static const char *stmfx_pinctrl_get_pin_conf(struct udevice *dev, + unsigned int pin, int func) +{ + int pupd, type; + + type = stmfx_conf_get_type(dev, pin); + if (type < 0) + return ""; + + if (func == GPIOF_OUTPUT) { + if (type) + return "drive-open-drain"; + else + return ""; /* default: push-pull*/ + } + if (!type) + return ""; /* default: bias-disable*/ + + pupd = stmfx_conf_get_pupd(dev, pin); + if (pupd < 0) + return ""; + + if (pupd) + return "bias-pull-up"; + else + return "bias-pull-down"; +} + static int stmfx_pinctrl_get_pin_muxing(struct udevice *dev, unsigned int selector, char *buf, int size) @@ -369,7 +397,9 @@ static int stmfx_pinctrl_get_pin_muxing(struct udevice *dev, if (func < 0) return func; - snprintf(buf, size, "%s", func == GPIOF_INPUT ? "input" : "output"); + snprintf(buf, size, "%s ", func == GPIOF_INPUT ? "input" : "output"); + + strncat(buf, stmfx_pinctrl_get_pin_conf(dev, selector, func), size); return 0; } -- cgit v1.3.1 From da7a0bb1f279221a85706bee7f75974c83d5e87a Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 4 Jun 2020 14:30:33 +0200 Subject: pinctrl: stm32: add information on pin configuration Add information on pin configuration used for pinmux command: - bias configuration for output (disable, pull up, pull down) - otype for input (open drain or push pull) Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/pinctrl/pinctrl_stm32.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c index fc241fdcdef..71fa29a3891 100644 --- a/drivers/pinctrl/pinctrl_stm32.c +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -45,6 +45,17 @@ static const char * const pinmux_mode[PINMUX_MODE_COUNT] = { "alt function", }; +static const char * const pinmux_output[] = { + [STM32_GPIO_PUPD_NO] = "bias-disable", + [STM32_GPIO_PUPD_UP] = "bias-pull-up", + [STM32_GPIO_PUPD_DOWN] = "bias-pull-down", +}; + +static const char * const pinmux_input[] = { + [STM32_GPIO_OTYPE_PP] = "drive-push-pull", + [STM32_GPIO_OTYPE_OD] = "drive-open-drain", +}; + static int stm32_pinctrl_get_af(struct udevice *dev, unsigned int offset) { struct stm32_gpio_priv *priv = dev_get_priv(dev); @@ -182,10 +193,12 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev, int size) { struct udevice *gpio_dev; + struct stm32_gpio_priv *priv; const char *label; int mode; int af_num; unsigned int gpio_idx; + u32 pupd, otype; /* look up for the bank which owns the requested pin */ gpio_dev = stm32_pinctrl_get_gpio_dev(dev, selector, &gpio_idx); @@ -194,9 +207,9 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev, return -ENODEV; mode = gpio_get_raw_function(gpio_dev, gpio_idx, &label); - dev_dbg(dev, "selector = %d gpio_idx = %d mode = %d\n", selector, gpio_idx, mode); + priv = dev_get_priv(gpio_dev); switch (mode) { @@ -211,9 +224,17 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev, snprintf(buf, size, "%s %d", pinmux_mode[mode], af_num); break; case GPIOF_OUTPUT: + pupd = (readl(&priv->regs->pupdr) >> (gpio_idx * 2)) & + PUPD_MASK; + snprintf(buf, size, "%s %s %s", + pinmux_mode[mode], pinmux_output[pupd], + label ? label : ""); + break; case GPIOF_INPUT: - snprintf(buf, size, "%s %s", - pinmux_mode[mode], label ? label : ""); + otype = (readl(&priv->regs->otyper) >> gpio_idx) & OTYPE_MSK; + snprintf(buf, size, "%s %s %s", + pinmux_mode[mode], pinmux_input[otype], + label ? label : ""); break; } -- cgit v1.3.1 From 2ee5005dea1a12bba096abac1f8ebeaea91bf964 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 11 Jun 2020 16:51:17 +0200 Subject: configs: stm32mp1: activate WATCHDOG As kernel v5.6 have a solution since so we will be able to enable the watchdog at boot time. It is reloaded by the watchdog framework (if CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED is set) and until the userspace watchdog daemon takes over control. Need presence of kernel patch 85fdc63fe256 ("drivers: watchdog: stm32_iwdg: set WDOG_HW_RUNNING at probe") integrated in v5.6-rc1. This patch revert the previous commit ca351e705a5c ("stm32mp1: deactivate WATCHDOG in defconfig"). Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- configs/stm32mp15_basic_defconfig | 2 ++ configs/stm32mp15_trusted_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index 7347070c881..4c3bdb60632 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -144,5 +144,7 @@ CONFIG_VIDEO_STM32=y CONFIG_VIDEO_STM32_DSI=y CONFIG_VIDEO_STM32_MAX_XRES=1280 CONFIG_VIDEO_STM32_MAX_YRES=800 +CONFIG_WDT=y +CONFIG_WDT_STM32MP=y CONFIG_ERRNO_STR=y CONFIG_FDT_FIXUP_PARTITIONS=y diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index 97a27986a9f..4ca50d6874a 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -128,5 +128,7 @@ CONFIG_VIDEO_STM32=y CONFIG_VIDEO_STM32_DSI=y CONFIG_VIDEO_STM32_MAX_XRES=1280 CONFIG_VIDEO_STM32_MAX_YRES=800 +CONFIG_WDT=y +CONFIG_WDT_STM32MP=y CONFIG_ERRNO_STR=y CONFIG_FDT_FIXUP_PARTITIONS=y -- cgit v1.3.1 From 8b8c99bd3e1e9463e27ccd1bca18f4a7627901aa Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Fri, 12 Jun 2020 10:40:58 +0200 Subject: power: regulator: stm32: vrefbuf: fix a possible overshoot when re-enabling There maybe an overshoot: - when disabling, then re-enabling vrefbuf too quickly - or upon platform reset as external capacitor maybe slow discharging (VREFBUF is HiZ at reset by default). VREFBUF is used by ADC/DAC on some boards. An overshoot on the reference voltage make the conversions inaccurate for a short period of time. So: - Don't put the VREFBUF in HiZ when disabling, to force an active discharge. - Enforce a 1ms OFF/ON delay, also upon reset Penalty is a 1ms delay is applied (even for a cold boot), when enabling VREFBUF. Fixes: 93cf0ae7758d ("power: regulator: Add support for stm32-vrefbuf") Signed-off-by: Fabrice Gasnier Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard Reviewed-by: Jaehoon Chung --- drivers/power/regulator/stm32-vrefbuf.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/power/regulator/stm32-vrefbuf.c b/drivers/power/regulator/stm32-vrefbuf.c index 250773514f5..92136961c2e 100644 --- a/drivers/power/regulator/stm32-vrefbuf.c +++ b/drivers/power/regulator/stm32-vrefbuf.c @@ -43,8 +43,20 @@ static int stm32_vrefbuf_set_enable(struct udevice *dev, bool enable) u32 val; int ret; - clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_HIZ | STM32_ENVR, - enable ? STM32_ENVR : STM32_HIZ); + if (enable && !(readl(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR)) { + /* + * There maybe an overshoot: + * - when disabling, then re-enabling vrefbuf too quickly + * - or upon platform reset as external capacitor maybe slow + * discharging (VREFBUF is HiZ at reset by default). + * So force active discharge (HiZ=0) for 1ms before enabling. + */ + clrbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_HIZ); + udelay(1000); + } + + clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_ENVR, + enable ? STM32_ENVR : 0); if (!enable) return 0; -- cgit v1.3.1 From 6072c220bd3f9097f92b5e9aa48584e948f7cecf Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 15 Jun 2020 11:25:13 +0200 Subject: stm32mp1: configs: activate CMD_ERASEENV Activate the command env erase to reset the environment with the command: > env erase it is simpler than: > env default -a > env save Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- configs/stm32mp15_basic_defconfig | 1 + configs/stm32mp15_trusted_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index 4c3bdb60632..aa058096497 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -30,6 +30,7 @@ CONFIG_SYS_PROMPT="STM32MP> " # CONFIG_CMD_ELF is not set # CONFIG_CMD_EXPORTENV is not set # CONFIG_CMD_IMPORTENV is not set +CONFIG_CMD_ERASEENV=y CONFIG_CMD_MEMINFO=y CONFIG_CMD_MEMTEST=y CONFIG_SYS_MEMTEST_START=0xc0000000 diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index 4ca50d6874a..8db52cbc511 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -14,6 +14,7 @@ CONFIG_SYS_PROMPT="STM32MP> " # CONFIG_CMD_ELF is not set # CONFIG_CMD_EXPORTENV is not set # CONFIG_CMD_IMPORTENV is not set +CONFIG_CMD_ERASEENV=y CONFIG_CMD_MEMINFO=y CONFIG_CMD_MEMTEST=y CONFIG_SYS_MEMTEST_START=0xc0000000 -- cgit v1.3.1 From 42400228dce2c300cf1cde921f5f2750540ec8d9 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Tue, 16 Jun 2020 18:19:28 +0200 Subject: board: st: stm32mp1: increase teed partition With TEE 3.7.0, the partition teed (OP-TEE pageable code and data) need to increase up to 512KB in NOR device. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- board/st/common/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/st/common/Kconfig b/board/st/common/Kconfig index 015ba409396..750dbb64517 100644 --- a/board/st/common/Kconfig +++ b/board/st/common/Kconfig @@ -39,7 +39,7 @@ config MTDPARTS_NOR0_BOOT config MTDPARTS_NOR0_TEE string "mtd tee partitions for nor0" - default "256k(teeh),256k(teed),256k(teex)" + default "256k(teeh),512k(teed),256k(teex)" depends on SYS_MTDPARTS_RUNTIME && ARCH_STM32MP help This define the tee partitions added in mtparts dynamically -- cgit v1.3.1 From 03c4e6224a0650c6de07f7000db444cd1a30b1cc Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Tue, 16 Jun 2020 18:25:14 +0200 Subject: arm: stm32mp: stm32prog: add "Device Name" in iproduct during DFU USB enumeration Add "Device Name" in iproduct during DFU USB enumeration to have this information in STM32CubeProgrammer trace (this tools is compatible with @Name since v2.3) Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c index 969245e199c..30547f94c94 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c @@ -197,10 +197,12 @@ bool stm32prog_usb_loop(struct stm32prog_data *data, int dev) bool result; /* USB download gadget for STM32 Programmer */ char product[128]; + char name[SOC_NAME_SIZE]; + get_soc_name(name); snprintf(product, sizeof(product), - "USB download gadget@Device ID /0x%03X, @Revision ID /0x%04X", - get_cpu_dev(), get_cpu_rev()); + "USB download gadget@Device ID /0x%03X, @Revision ID /0x%04X, @Name /%s,", + get_cpu_dev(), get_cpu_rev(), name); g_dnl_set_product(product); if (stm32prog_data->phase == PHASE_FLASHLAYOUT) { -- cgit v1.3.1 From bd3f60d29c2494d156b353c33678be7366caafbd Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Tue, 16 Jun 2020 18:27:44 +0200 Subject: arm: stm32mp: protect DBGMCU_IDC access with BSEC As debugger must be totally closed on Sec closed chip, the DBGMCU_IDC register is no more accessible (self hosted debug is disabled with OTP). This patch adds a function bsec_dbgswenable() to check if the DBGMCU registers are available before to access them: BSEC_DENABLE.DBGSWENABLE = self hosted debug status. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- arch/arm/mach-stm32mp/bsec.c | 25 +++++++++++++++++++++++++ arch/arm/mach-stm32mp/cpu.c | 22 ++++++++++++++++++---- arch/arm/mach-stm32mp/include/mach/bsec.h | 7 +++++++ 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-stm32mp/include/mach/bsec.h diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c index 059ef0b1f58..0c56b440f56 100644 --- a/arch/arm/mach-stm32mp/bsec.c +++ b/arch/arm/mach-stm32mp/bsec.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #define BSEC_OTP_WRDATA_OFF 0x008 #define BSEC_OTP_STATUS_OFF 0x00C #define BSEC_OTP_LOCK_OFF 0x010 +#define BSEC_DENABLE_OFF 0x014 #define BSEC_DISTURBED_OFF 0x01C #define BSEC_ERROR_OFF 0x034 #define BSEC_WRLOCK_OFF 0x04C /* OTP write permananet lock */ @@ -46,6 +48,9 @@ #define BSEC_MODE_PROGFAIL_MASK 0x10 #define BSEC_MODE_PWR_MASK 0x20 +/* DENABLE Register */ +#define BSEC_DENABLE_DBGSWENABLE BIT(10) + /* * OTP Lock services definition * Value must corresponding to the bit number in the register @@ -506,3 +511,23 @@ U_BOOT_DRIVER(stm32mp_bsec) = { .ops = &stm32mp_bsec_ops, .probe = stm32mp_bsec_probe, }; + +bool bsec_dbgswenable(void) +{ + struct udevice *dev; + struct stm32mp_bsec_platdata *plat; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), &dev); + if (ret || !dev) { + pr_debug("bsec driver not available\n"); + return false; + } + + plat = dev_get_platdata(dev); + if (readl(plat->base + BSEC_DENABLE_OFF) & BSEC_DENABLE_DBGSWENABLE) + return true; + + return false; +} diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index 472b140321f..382067190ca 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -155,8 +156,13 @@ static void dbgmcu_init(void) { setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN); - /* Freeze IWDG2 if Cortex-A7 is in debug mode */ - setbits_le32(DBGMCU_APB4FZ1, DBGMCU_APB4FZ1_IWDG2); + /* + * Freeze IWDG2 if Cortex-A7 is in debug mode + * done in TF-A for TRUSTED boot and + * DBGMCU access is controlled by BSEC_DENABLE.DBGSWENABLE + */ + if (!IS_ENABLED(CONFIG_TFABOOT) && bsec_dbgswenable()) + setbits_le32(DBGMCU_APB4FZ1, DBGMCU_APB4FZ1_IWDG2); } #endif /* !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) */ @@ -276,9 +282,17 @@ void enable_caches(void) static u32 read_idc(void) { - setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN); + /* DBGMCU access is controlled by BSEC_DENABLE.DBGSWENABLE */ + if (bsec_dbgswenable()) { + setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN); - return readl(DBGMCU_IDC); + return readl(DBGMCU_IDC); + } + + if (CONFIG_IS_ENABLED(STM32MP15x)) + return CPU_DEV_STM32MP15; /* STM32MP15x and unknown revision */ + else + return 0x0; } u32 get_cpu_dev(void) diff --git a/arch/arm/mach-stm32mp/include/mach/bsec.h b/arch/arm/mach-stm32mp/include/mach/bsec.h new file mode 100644 index 00000000000..252eac3946a --- /dev/null +++ b/arch/arm/mach-stm32mp/include/mach/bsec.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +/* check self hosted debug status = BSEC_DENABLE.DBGSWENABLE */ +bool bsec_dbgswenable(void); -- cgit v1.3.1 From d5d726d3cc47691ace3c68fa31147ad104aaf579 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Tue, 16 Jun 2020 18:30:27 +0200 Subject: configs: stm32mp1: only support SD card after NOR in bootcmd_stm32mp In the boot command used in ST boards, bootcmd_stm32mp, only support the SD card as second stage, where is found the bootfs with DISTRO. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- include/configs/stm32mp1.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h index f271b84a59e..baaf2ff89c3 100644 --- a/include/configs/stm32mp1.h +++ b/include/configs/stm32mp1.h @@ -123,7 +123,7 @@ * for serial/usb: execute the stm32prog command * for mmc boot (eMMC, SD card), boot only on the same device * for nand or spi-nand boot, boot with on ubifs partition on UBI partition - * for nor boot, use the default order + * for nor boot, use SD card = mmc0 */ #define STM32MP_BOOTCMD "bootcmd_stm32mp=" \ "echo \"Boot over ${boot_device}${boot_instance}!\";" \ @@ -136,6 +136,8 @@ "if test ${boot_device} = nand ||" \ " test ${boot_device} = spi-nand ;" \ "then env set boot_targets ubifs0; fi;" \ + "if test ${boot_device} = nor;" \ + "then env set boot_targets mmc0; fi;" \ "run distro_bootcmd;" \ "fi;\0" -- cgit v1.3.1 From 03fb03842a1e16f89477d4a968712cc2422be217 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 29 Jun 2020 10:34:06 +0200 Subject: board: st: move type-c stusb1600 controller code in a driver Migrate the ST Microelectronics STUSB160X Type-C controller code in a generic I2C driver in st/common, based on Linux one in : drivers/usb/typec/stusb160x.c This patch simplifies the stm32mp1 board code and allows to reuse this STUSB160X driver in other boards. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- board/st/common/Kconfig | 7 +++++ board/st/common/Makefile | 2 ++ board/st/common/stusb160x.c | 46 +++++++++++++++++++++++++++++ board/st/common/stusb160x.h | 10 +++++++ board/st/stm32mp1/stm32mp1.c | 58 ++++--------------------------------- configs/stm32mp15_basic_defconfig | 1 + configs/stm32mp15_trusted_defconfig | 1 + 7 files changed, 73 insertions(+), 52 deletions(-) create mode 100644 board/st/common/stusb160x.c create mode 100644 board/st/common/stusb160x.h diff --git a/board/st/common/Kconfig b/board/st/common/Kconfig index 750dbb64517..ddcf33a1220 100644 --- a/board/st/common/Kconfig +++ b/board/st/common/Kconfig @@ -69,3 +69,10 @@ config DFU_ALT_RAM0 depends on ARCH_STM32MP && SET_DFU_ALT_INFO help This defines the partitions of ram used to build dfu dynamically. + +config TYPEC_STUSB160X + tristate "STMicroelectronics STUSB160X Type-C controller driver" + depends on DM_I2C + help + Say Y if your system has STMicroelectronics STUSB160X Type-C port + controller. diff --git a/board/st/common/Makefile b/board/st/common/Makefile index 012bfbbe8ee..65bbebd6abc 100644 --- a/board/st/common/Makefile +++ b/board/st/common/Makefile @@ -10,3 +10,5 @@ ifeq ($(CONFIG_ARCH_STM32MP),y) obj-$(CONFIG_SYS_MTDPARTS_RUNTIME) += stm32mp_mtdparts.o obj-$(CONFIG_SET_DFU_ALT_INFO) += stm32mp_dfu.o endif + +obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o diff --git a/board/st/common/stusb160x.c b/board/st/common/stusb160x.c new file mode 100644 index 00000000000..f1197f9faa4 --- /dev/null +++ b/board/st/common/stusb160x.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * STMicroelectronics STUSB Type-C controller driver + * based on Linux drivers/usb/typec/stusb160x.c + * + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include + +/* REGISTER */ +#define STUSB160X_CC_CONNECTION_STATUS 0x0E + +/* STUSB160X_CC_CONNECTION_STATUS bitfields */ +#define STUSB160X_CC_ATTACH BIT(0) + +int stusb160x_cable_connected(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_I2C_GENERIC, + DM_GET_DRIVER(stusb160x), + &dev); + if (ret < 0) + return ret; + + ret = dm_i2c_reg_read(dev, STUSB160X_CC_CONNECTION_STATUS); + if (ret < 0) + return 0; + + return ret & STUSB160X_CC_ATTACH; +} + +static const struct udevice_id stusb160x_ids[] = { + { .compatible = "st,stusb1600" }, + {} +}; + +U_BOOT_DRIVER(stusb160x) = { + .name = "stusb160x", + .id = UCLASS_I2C_GENERIC, + .of_match = stusb160x_ids, +}; diff --git a/board/st/common/stusb160x.h b/board/st/common/stusb160x.h new file mode 100644 index 00000000000..fe39840b41d --- /dev/null +++ b/board/st/common/stusb160x.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020, STMicroelectronics + */ + +#ifdef CONFIG_TYPEC_STUSB160X +int stusb160x_cable_connected(void); +#else +int stusb160x_cable_connected(void) { return -ENODEV; } +#endif diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index c5c89d27e52..71daf180347 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -41,6 +41,8 @@ #include #include +#include "../../st/common/stusb160x.h" + /* SYSCFG registers */ #define SYSCFG_BOOTR 0x00 #define SYSCFG_PMCSETR 0x04 @@ -181,64 +183,16 @@ static void board_key_check(void) } #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) - -/* STMicroelectronics STUSB1600 Type-C controller */ -#define STUSB1600_CC_CONNECTION_STATUS 0x0E - -/* STUSB1600_CC_CONNECTION_STATUS bitfields */ -#define STUSB1600_CC_ATTACH BIT(0) - -static int stusb1600_init(struct udevice **dev_stusb1600) -{ - ofnode node; - struct udevice *dev, *bus; - int ret; - u32 chip_addr; - - *dev_stusb1600 = NULL; - - /* if node stusb1600 is present, means DK1 or DK2 board */ - node = ofnode_by_compatible(ofnode_null(), "st,stusb1600"); - if (!ofnode_valid(node)) - return -ENODEV; - - ret = ofnode_read_u32(node, "reg", &chip_addr); - if (ret) - return -EINVAL; - - ret = uclass_get_device_by_ofnode(UCLASS_I2C, ofnode_get_parent(node), - &bus); - if (ret) { - printf("bus for stusb1600 not found\n"); - return -ENODEV; - } - - ret = dm_i2c_probe(bus, chip_addr, 0, &dev); - if (!ret) - *dev_stusb1600 = dev; - - return ret; -} - -static int stusb1600_cable_connected(struct udevice *dev) -{ - u8 status; - - if (dm_i2c_read(dev, STUSB1600_CC_CONNECTION_STATUS, &status, 1)) - return 0; - - return status & STUSB1600_CC_ATTACH; -} - #include int g_dnl_board_usb_cable_connected(void) { - struct udevice *stusb1600; struct udevice *dwc2_udc_otg; int ret; - if (!stusb1600_init(&stusb1600)) - return stusb1600_cable_connected(stusb1600); + /* if typec stusb160x is present, means DK1 or DK2 board */ + ret = stusb160x_cable_connected(); + if (ret >= 0) + return ret; ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC, DM_GET_DRIVER(dwc2_udc_otg), diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index aa058096497..e68b0b80821 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -10,6 +10,7 @@ CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL=y CONFIG_TARGET_ST_STM32MP15x=y CONFIG_CMD_STM32PROG=y +CONFIG_TYPEC_STUSB160X=y CONFIG_ENV_OFFSET_REDUND=0x2C0000 CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index 8db52cbc511..f4aa8432a5a 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -6,6 +6,7 @@ CONFIG_ENV_OFFSET=0x280000 CONFIG_ENV_SECT_SIZE=0x40000 CONFIG_TARGET_ST_STM32MP15x=y CONFIG_CMD_STM32PROG=y +CONFIG_TYPEC_STUSB160X=y CONFIG_ENV_OFFSET_REDUND=0x2C0000 CONFIG_DISTRO_DEFAULTS=y CONFIG_FIT=y -- cgit v1.3.1 From 6826d0d82ba6ca2b466117aafdaa3305b666e37b Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 2 Jul 2020 15:20:47 +0200 Subject: board: dh_stm32mp1: update the gpio hog support This patch update the current gpio hog implementation with the new API gpio_hog_probe_all() activated with CONFIG_GPIO_HOG. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- board/dhelectronics/dh_stm32mp1/board.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/board/dhelectronics/dh_stm32mp1/board.c b/board/dhelectronics/dh_stm32mp1/board.c index b2b4f3974d2..b8625f25d3e 100644 --- a/board/dhelectronics/dh_stm32mp1/board.c +++ b/board/dhelectronics/dh_stm32mp1/board.c @@ -523,17 +523,11 @@ static void board_init_fmc2(void) /* board dependent setup after realloc */ int board_init(void) { - struct udevice *dev; - /* address of boot parameters */ gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100; - /* probe all PINCTRL for hog */ - for (uclass_first_device(UCLASS_PINCTRL, &dev); - dev; - uclass_next_device(&dev)) { - pr_debug("probe pincontrol = %s\n", dev->name); - } + if (CONFIG_IS_ENABLED(DM_GPIO_HOG)) + gpio_hog_probe_all(); board_key_check(); -- cgit v1.3.1 From 8b5206d9e48576ff94f48e98803154e0e9f8fb1d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 2 Jul 2020 17:43:44 +0200 Subject: cmd: env: use ENV_IS_IN_DEVICE in env info Use the define ENV_IS_IN_DEVICE to test if one the CONFIG_ENV_IS_IN_... is defined and correct the detection of persistent storage support in the command "env info" if CONFIG_ENV_IS_NOWHERE is activated. Since commit 60d5ed2593c9 ("env: allow ENV_IS_NOWHERE with other storage target") test CONFIG_ENV_IS_NOWHERE is not enough; see also commit 953db29a1e9c6 ("env: enable saveenv command when one CONFIG_ENV_IS_IN is activated"). This patch avoids issue for this command in stm32mp1 platform. Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass Reviewed-by: Patrice Chotard --- cmd/nvedit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nvedit.c b/cmd/nvedit.c index 08d49df220a..49338b4d364 100644 --- a/cmd/nvedit.c +++ b/cmd/nvedit.c @@ -1265,7 +1265,7 @@ static int do_env_info(struct cmd_tbl *cmdtp, int flag, /* evaluate whether environment can be persisted */ if (eval_flags & ENV_INFO_IS_PERSISTED) { -#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) +#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE) printf("Environment can be persisted\n"); eval_results |= ENV_INFO_IS_PERSISTED; #else -- cgit v1.3.1 From c16cba88bd469353b0f6265e1f507200f20e3d6d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 2 Jul 2020 17:43:45 +0200 Subject: stm32mp1: use the command env info in env_check Activate CMD_NVEDIT_INFO and use the new command "env info -d -p -q" to automatically save the environment on first boot. This patch allows to remove the env_default variable. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- arch/arm/mach-stm32mp/Kconfig | 1 + include/configs/stm32mp1.h | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig index ea7d57477b5..4003c2e38bf 100644 --- a/arch/arm/mach-stm32mp/Kconfig +++ b/arch/arm/mach-stm32mp/Kconfig @@ -45,6 +45,7 @@ config STM32MP15x select STM32_RESET select STM32_SERIAL select SYS_ARCH_TIMER + imply CMD_NVEDIT_INFO imply SYSRESET_PSCI if TFABOOT imply SYSRESET_SYSCON if !TFABOOT help diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h index baaf2ff89c3..ed20b842ac9 100644 --- a/include/configs/stm32mp1.h +++ b/include/configs/stm32mp1.h @@ -157,9 +157,7 @@ "splashimage=0xc4300000\0" \ "ramdisk_addr_r=0xc4400000\0" \ "altbootcmd=run bootcmd\0" \ - "env_default=1\0" \ - "env_check=if test $env_default -eq 1;"\ - " then env set env_default 0;env save;fi\0" \ + "env_check=if env info -p -d; then env save; fi\0" \ STM32MP_BOOTCMD \ BOOTENV \ "boot_net_usb_start=true\0" -- cgit v1.3.1 From 1a5be5a416e21fe243141d079f30a5e50bf6e332 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 2 Jul 2020 19:56:34 +0200 Subject: ram: stm32mp1: protect minimum value in get_bufsize Add protection on minimum value for result of get_bufsize and check the alignment of buffer size: only multiple min_size is allowed; only 4 bytes alignment was checked previously (value & 0x3). For example the "Random" test raises an issue when size is not 8 bytes aligned because address for buffer = address + size / 2 is not word aligned. This patch avoid test error for unsupported size value. Reviewed-by: Patrice Chotard Signed-off-by: Patrick Delaunay --- drivers/ram/stm32mp1/stm32mp1_tests.c | 37 ++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/ram/stm32mp1/stm32mp1_tests.c b/drivers/ram/stm32mp1/stm32mp1_tests.c index bacdd74705d..90e82acda7a 100644 --- a/drivers/ram/stm32mp1/stm32mp1_tests.c +++ b/drivers/ram/stm32mp1/stm32mp1_tests.c @@ -17,7 +17,7 @@ DECLARE_GLOBAL_DATA_PTR; static int get_bufsize(char *string, int argc, char *argv[], int arg_nb, - size_t *bufsize, size_t default_size) + size_t *bufsize, size_t default_size, size_t min_size) { unsigned long value; @@ -27,13 +27,14 @@ static int get_bufsize(char *string, int argc, char *argv[], int arg_nb, arg_nb, argv[arg_nb]); return -1; } - if (value > STM32_DDR_SIZE || value == 0) { - sprintf(string, "invalid size %s", argv[arg_nb]); + if (value > STM32_DDR_SIZE || value < min_size) { + sprintf(string, "invalid size %s (min=%d)", + argv[arg_nb], min_size); return -1; } - if (value & 0x3) { - sprintf(string, "unaligned size %s", - argv[arg_nb]); + if (value & (min_size - 1)) { + sprintf(string, "unaligned size %s (min=%d)", + argv[arg_nb], min_size); return -1; } *bufsize = value; @@ -441,7 +442,7 @@ static enum test_result test_addressbus(struct stm32mp1_ddrctl *ctl, u32 bufsize; u32 error; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4)) return TEST_ERROR; if (!is_power_of_2(bufsize)) { sprintf(string, "size 0x%x is not a power of 2", @@ -470,7 +471,7 @@ static enum test_result test_memdevice(struct stm32mp1_ddrctl *ctl, size_t bufsize; u32 error; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4)) return TEST_ERROR; if (get_addr(string, argc, argv, 1, &addr)) return TEST_ERROR; @@ -512,7 +513,7 @@ static enum test_result test_sso(struct stm32mp1_ddrctl *ctl, u32 error = 0; u32 data; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4)) return TEST_ERROR; if (get_addr(string, argc, argv, 1, &addr)) return TEST_ERROR; @@ -584,7 +585,7 @@ static enum test_result test_random(struct stm32mp1_ddrctl *ctl, u32 error = 0; unsigned int seed; - if (get_bufsize(string, argc, argv, 0, &bufsize, 8 * 1024)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 8)) return TEST_ERROR; if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1)) return TEST_ERROR; @@ -744,7 +745,7 @@ static enum test_result test_noise_burst(struct stm32mp1_ddrctl *ctl, int i; enum test_result res = TEST_PASSED; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 128)) return TEST_ERROR; if (get_pattern(string, argc, argv, 1, &pattern, 0xFFFFFFFF)) return TEST_ERROR; @@ -920,7 +921,7 @@ static enum test_result test_freq_pattern(struct stm32mp1_ddrctl *ctl, const u32 **patterns; u32 bufsize; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 128)) return TEST_ERROR; switch (readl(&ctl->mstr) & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK) { @@ -1007,7 +1008,7 @@ static enum test_result test_checkboard(struct stm32mp1_ddrctl *ctl, u32 checkboard[2] = {0x55555555, 0xAAAAAAAA}; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 8)) return TEST_ERROR; if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1)) return TEST_ERROR; @@ -1042,7 +1043,7 @@ static enum test_result test_blockseq(struct stm32mp1_ddrctl *ctl, u32 bufsize, nb_loop, loop = 0, addr, value; int i; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4)) return TEST_ERROR; if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1)) return TEST_ERROR; @@ -1076,7 +1077,7 @@ static enum test_result test_walkbit0(struct stm32mp1_ddrctl *ctl, u32 bufsize, nb_loop, loop = 0, addr, value; int i; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4)) return TEST_ERROR; if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1)) return TEST_ERROR; @@ -1114,7 +1115,7 @@ static enum test_result test_walkbit1(struct stm32mp1_ddrctl *ctl, u32 bufsize, nb_loop, loop = 0, addr, value; int i; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4)) return TEST_ERROR; if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1)) return TEST_ERROR; @@ -1156,7 +1157,7 @@ static enum test_result test_bitspread(struct stm32mp1_ddrctl *ctl, u32 bufsize, nb_loop, loop = 0, addr, bitspread[4]; int i, j; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 32)) return TEST_ERROR; if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1)) return TEST_ERROR; @@ -1203,7 +1204,7 @@ static enum test_result test_bitflip(struct stm32mp1_ddrctl *ctl, u32 bitflip[4]; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024)) + if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 32)) return TEST_ERROR; if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1)) return TEST_ERROR; -- cgit v1.3.1 From fcd4890829dc432f6ae6057fc3736fbc463ca5c2 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 2 Jul 2020 19:56:35 +0200 Subject: ram: stm32mp1: add parameter addr in test FrequencySelectivePattern Add a parameter addr in test FrequencySelectivePattern to select the base address used to execute the tests. Default value (when the parameter is absent) is STM32_DDR_BASE, selected in get_addr() function. Reviewed-by: Patrice Chotard Signed-off-by: Patrick Delaunay --- drivers/ram/stm32mp1/stm32mp1_tests.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/ram/stm32mp1/stm32mp1_tests.c b/drivers/ram/stm32mp1/stm32mp1_tests.c index 90e82acda7a..fec9fd010e9 100644 --- a/drivers/ram/stm32mp1/stm32mp1_tests.c +++ b/drivers/ram/stm32mp1/stm32mp1_tests.c @@ -919,10 +919,12 @@ static enum test_result test_freq_pattern(struct stm32mp1_ddrctl *ctl, enum test_result res = TEST_PASSED, pattern_res; int i, bus_width; const u32 **patterns; - u32 bufsize; + u32 bufsize, addr; if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 128)) return TEST_ERROR; + if (get_addr(string, argc, argv, 1, &addr)) + return TEST_ERROR; switch (readl(&ctl->mstr) & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK) { case DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF: @@ -935,15 +937,14 @@ static enum test_result test_freq_pattern(struct stm32mp1_ddrctl *ctl, } printf("running test pattern at 0x%08x length 0x%x width = %d\n", - STM32_DDR_BASE, bufsize, bus_width); + addr, bufsize, bus_width); patterns = (const u32 **)(bus_width == 16 ? patterns_x16 : patterns_x32); for (i = 0; i < NB_PATTERN; i++) { printf("test data pattern %s:", patterns_comments[i]); - pattern_res = test_loop(patterns[i], (u32 *)STM32_DDR_BASE, - bufsize); + pattern_res = test_loop(patterns[i], (u32 *)addr, bufsize); if (pattern_res != TEST_PASSED) { printf("Failed\n"); return pattern_res; @@ -1419,9 +1420,9 @@ const struct test_desc test[] = { "Verifies r/w and memcopy(burst for pseudo random value.", 3 }, - {test_freq_pattern, "FrequencySelectivePattern", "[size]", + {test_freq_pattern, "FrequencySelectivePattern", "[size] [addr]", "write & test patterns: Mostly Zero, Mostly One and F/n", - 1 + 2 }, {test_blockseq, "BlockSequential", "[size] [loop] [addr]", "test incremental pattern", -- cgit v1.3.1 From 81b66b903311cba53e8a0d4ded112076b6fb4498 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 2 Jul 2020 19:56:36 +0200 Subject: ram: stm32mp1: use the DDR size by default in the test addressBus The test 4 = "AddressBus [size] [addr]" without parameter detects alias for any address bit only when: - size = real size of DDR - addr = start of DDR = 0xC0000000 These value must be the default value when parameters are absent. This patch sets bufsize to STM32_DDR_SIZE and get_bufsize() selects the correct value for bufsize when this parameter is absent = full size of the DDDR On EV1 board : DDR> test 4 running at 0xC0000000 length 0x40000000 On DK2 board DDR> test 4 running at 0xC0000000 length 0x20000000 Reviewed-by: Patrice Chotard Signed-off-by: Patrick Delaunay --- drivers/ram/stm32mp1/stm32mp1_tests.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ram/stm32mp1/stm32mp1_tests.c b/drivers/ram/stm32mp1/stm32mp1_tests.c index fec9fd010e9..a2a69da9a37 100644 --- a/drivers/ram/stm32mp1/stm32mp1_tests.c +++ b/drivers/ram/stm32mp1/stm32mp1_tests.c @@ -442,7 +442,7 @@ static enum test_result test_addressbus(struct stm32mp1_ddrctl *ctl, u32 bufsize; u32 error; - if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4)) + if (get_bufsize(string, argc, argv, 0, &bufsize, STM32_DDR_SIZE, 4)) return TEST_ERROR; if (!is_power_of_2(bufsize)) { sprintf(string, "size 0x%x is not a power of 2", @@ -452,6 +452,7 @@ static enum test_result test_addressbus(struct stm32mp1_ddrctl *ctl, if (get_addr(string, argc, argv, 1, &addr)) return TEST_ERROR; + printf("running at 0x%08x length 0x%x\n", addr, bufsize); error = (u32)addressbus((u32 *)addr, bufsize); if (error) { sprintf(string, "0x%x: error for address 0x%x", -- cgit v1.3.1 From 6c393e8c0fae98a3a6e2909fc79697075552a152 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 2 Jul 2020 19:56:37 +0200 Subject: ram: stm32mp1: add size and addr parameter to test all Add size and addr parameter to test "All" to override the default value (4kB and STM32_DDR_BASE) used in tests with these optional parameters: [size] or [addr]. When other optional parameters are present before [addr], they are replaced by default value: - [loop] = "1" - [pattern] = "-" (new: force default pattern) Example to use: DDR>test 0 1 0x20000 DDR>test 0 1 0x1000000 0xD0000000 Reviewed-by: Patrice Chotard Signed-off-by: Patrick Delaunay --- drivers/ram/stm32mp1/stm32mp1_tests.c | 47 ++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/drivers/ram/stm32mp1/stm32mp1_tests.c b/drivers/ram/stm32mp1/stm32mp1_tests.c index a2a69da9a37..952006aa149 100644 --- a/drivers/ram/stm32mp1/stm32mp1_tests.c +++ b/drivers/ram/stm32mp1/stm32mp1_tests.c @@ -14,6 +14,8 @@ #define ADDR_INVALID 0xFFFFFFFF +#define PATTERN_DEFAULT "-" + DECLARE_GLOBAL_DATA_PTR; static int get_bufsize(char *string, int argc, char *argv[], int arg_nb, @@ -103,6 +105,10 @@ static int get_pattern(char *string, int argc, char *argv[], int arg_nb, unsigned long value; if (argc > arg_nb) { + if (!strcmp(argv[arg_nb], PATTERN_DEFAULT)) { + *pattern = default_pattern; + return 0; + } if (strict_strtoul(argv[arg_nb], 16, &value) < 0) { sprintf(string, "invalid %d parameter %s", arg_nb, argv[arg_nb]); @@ -1343,17 +1349,52 @@ static enum test_result test_all(struct stm32mp1_ddrctl *ctl, char *string, int argc, char *argv[]) { enum test_result res = TEST_PASSED, result; - int i, nb_error = 0; + int i, j, nb_error = 0, len; u32 loop = 0, nb_loop; + int argc_test; + char *argv_test[4]; + char loop_string[] = "1"; + char pattern_string[] = PATTERN_DEFAULT; + u32 *addr; if (get_nb_loop(string, argc, argv, 0, &nb_loop, 1)) return TEST_ERROR; + if (get_addr(string, argc, argv, 2, (u32 *)&addr)) + return TEST_ERROR; + while (!nb_error) { /* execute all the test except the lasts which are infinite */ for (i = 1; i < test_nb - NB_TEST_INFINITE; i++) { + argc_test = 0; + j = 0; + len = strlen(test[i].usage); + if (argc > 1 && j < len && + !strncmp("[size]", &test[i].usage[j], 6)) { + argv_test[argc_test++] = argv[1]; + j += 7; + } + if (argc > 2) { + if (j < len && + !strncmp("[loop]", &test[i].usage[j], 6)) { + argv_test[argc_test++] = loop_string; + j += 7; + } + if (j < len && + !strncmp("[pattern]", &test[i].usage[j], + 9)) { + argv_test[argc_test++] = pattern_string; + j += 10; + } + if (j < len && + !strncmp("[addr]", &test[i].usage[j], 6)) { + argv_test[argc_test++] = argv[2]; + j += 7; + } + } printf("execute %d:%s\n", (int)i, test[i].name); - result = test[i].fct(ctl, phy, string, 0, NULL); + result = test[i].fct(ctl, phy, string, + argc_test, argv_test); printf("result %d:%s = ", (int)i, test[i].name); if (result != TEST_PASSED) { nb_error++; @@ -1384,7 +1425,7 @@ static enum test_result test_all(struct stm32mp1_ddrctl *ctl, ****************************************************************/ const struct test_desc test[] = { - {test_all, "All", "[loop]", "Execute all tests", 1 }, + {test_all, "All", "[loop] [size] [addr]", "Execute all tests", 3 }, {test_databus, "Simple DataBus", "[addr]", "Verifies each data line by walking 1 on fixed address", 1 -- cgit v1.3.1