[U-Boot] [PATCH 00/16] patches for stm32 support

Some patches to cleanup and to improve the support of stm32mp1 in U-Boot.
Nicolas Le Bayon (2): i2c: stm32f7: Fix SDADEL minimum formula i2c: stm32f7: improve loopback in timing algorithm
Patrick Delaunay (14): stm32mp1: Move config SYS_MALLOC_LEN to Kconfig stm32mp1: Move ENV_SIZE and ENV_OFFSET to Kconfig stm32mp1: migrate PREBOOT to Kconfig stm32mp1: cosmetic: bsec: reorder include files stm32mp1: psci: add synchronization with ROM code stm32mp1: update RCC binding after kernel realignment mkimage: change stm32image header to manage binary information stm32mp1: add bootcount support armv7: timer: init timer with bootstage stm32mp1: add bootstage support clk: stm32mp1: add set_rate for DDRPHYC clock env: solve compilation error in SPL serial: stm32: remove unnecessary trace serial: stm32: remove watchog reset in debug putc
Kconfig | 2 +- arch/arm/Kconfig | 1 + arch/arm/cpu/armv7/arch_timer.c | 3 + arch/arm/mach-stm32mp/Kconfig | 24 ++ arch/arm/mach-stm32mp/bsec.c | 2 +- arch/arm/mach-stm32mp/include/mach/stm32.h | 1 + arch/arm/mach-stm32mp/psci.c | 22 +- common/Kconfig | 1 + doc/device-tree-bindings/clock/st,stm32mp1.txt | 427 +++++++++++++++++-------- drivers/clk/clk_stm32mp1.c | 83 +++++ drivers/i2c/stm32f7_i2c.c | 6 +- drivers/serial/serial_stm32.c | 3 +- env/Kconfig | 2 +- env/common.c | 7 +- include/configs/stm32mp1.h | 12 - tools/stm32image.c | 8 +- 16 files changed, 440 insertions(+), 164 deletions(-)

This patch moves the the config SYS_MALLOC_LEN to Kconfig as it is already done for zynq arch in commit 01aa5b8f0503 ("Kconfig: Move config SYS_MALLOC_LEN to Kconfig for zynq")
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
Kconfig | 2 +- arch/arm/mach-stm32mp/Kconfig | 3 +++ include/configs/stm32mp1.h | 5 ----- 3 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/Kconfig b/Kconfig index 7a5491b..0926de7 100644 --- a/Kconfig +++ b/Kconfig @@ -147,7 +147,7 @@ config SYS_MALLOC_F_LEN
config SYS_MALLOC_LEN hex "Define memory for Dynamic allocation" - depends on ARCH_ZYNQ || ARCH_VERSAL + depends on ARCH_ZYNQ || ARCH_VERSAL || ARCH_STM32MP help This defines memory to be allocated for Dynamic allocation TODO: Use for other architectures diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig index 73aa382..39a2a32 100644 --- a/arch/arm/mach-stm32mp/Kconfig +++ b/arch/arm/mach-stm32mp/Kconfig @@ -23,6 +23,9 @@ config SPL config SYS_SOC default "stm32mp"
+config SYS_MALLOC_LEN + default 0x2000000 + config TARGET_STM32MP1 bool "Support stm32mp1xx" select ARCH_SUPPORT_PSCI if !STM32MP1_TRUSTED diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h index 737dfd6..18ff7cf 100644 --- a/include/configs/stm32mp1.h +++ b/include/configs/stm32mp1.h @@ -23,11 +23,6 @@ #endif
/* - * malloc() pool size - */ -#define CONFIG_SYS_MALLOC_LEN SZ_32M - -/* * Configuration of the external SRAM memory used by U-Boot */ #define CONFIG_SYS_SDRAM_BASE STM32_DDR_BASE

Add arch stm32mp for ENV migration step and drop more items from include/configs/xxx.h.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
arch/arm/mach-stm32mp/Kconfig | 3 +++ env/Kconfig | 2 +- include/configs/stm32mp1.h | 5 ----- 3 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig index 39a2a32..26dace10 100644 --- a/arch/arm/mach-stm32mp/Kconfig +++ b/arch/arm/mach-stm32mp/Kconfig @@ -26,6 +26,9 @@ config SYS_SOC config SYS_MALLOC_LEN default 0x2000000
+config ENV_SIZE + default 0x1000 + config TARGET_STM32MP1 bool "Support stm32mp1xx" select ARCH_SUPPORT_PSCI if !STM32MP1_TRUSTED diff --git a/env/Kconfig b/env/Kconfig index 7830066..0e1e02d 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -470,7 +470,7 @@ config ENV_EXT4_FILE It's a string of the EXT4 file name. This file use to store the environment (explicit path to the file)
-if ARCH_ROCKCHIP || ARCH_SUNXI || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL || ARC +if ARCH_ROCKCHIP || ARCH_SUNXI || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL || ARC || ARCH_STM32MP
config ENV_OFFSET hex "Environment Offset" diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h index 18ff7cf..eda8775 100644 --- a/include/configs/stm32mp1.h +++ b/include/configs/stm32mp1.h @@ -38,11 +38,6 @@ */ #define CONFIG_SYS_LOAD_ADDR STM32_DDR_BASE
-/* - * Env parameters - */ -#define CONFIG_ENV_SIZE SZ_4K - /* ATAGs */ #define CONFIG_CMDLINE_TAG #define CONFIG_SETUP_MEMORY_TAGS

Use Kconfig to activate CONFIG_PREBOOT (empty by default).
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
arch/arm/Kconfig | 1 + common/Kconfig | 1 + include/configs/stm32mp1.h | 2 -- 3 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4640f3b..6660d8b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1405,6 +1405,7 @@ config ARCH_STM32MP imply CMD_DM imply CMD_POWEROFF imply ENV_VARS_UBOOT_RUNTIME_CONFIG + imply USE_PREBOOT help Support for STM32MP SoC family developed by STMicroelectronics, MPUs based on ARM cortex A core diff --git a/common/Kconfig b/common/Kconfig index 1a1951f..c759952 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -247,6 +247,7 @@ config USE_PREBOOT config PREBOOT string "preboot default value" depends on USE_PREBOOT + default "" help This is the default of "preboot" environment variable.
diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h index eda8775..8e00158 100644 --- a/include/configs/stm32mp1.h +++ b/include/configs/stm32mp1.h @@ -87,8 +87,6 @@ * for nand boot, boot with on ubifs partition on nand * for nor boot, use the default order */ -#define CONFIG_PREBOOT - #define STM32MP_BOOTCMD "bootcmd_stm32mp=" \ "echo "Boot over ${boot_device}${boot_instance}!";" \ "if test ${boot_device} = serial || test ${boot_device} = usb;" \

Reorder the include files in alphabetic order.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
arch/arm/mach-stm32mp/bsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c index 9ed8d8c..0166649 100644 --- a/arch/arm/mach-stm32mp/bsec.c +++ b/arch/arm/mach-stm32mp/bsec.c @@ -7,9 +7,9 @@ #include <dm.h> #include <misc.h> #include <asm/io.h> -#include <linux/iopoll.h> #include <asm/arch/stm32mp1_smc.h> #include <linux/arm-smccc.h> +#include <linux/iopoll.h>
#define BSEC_OTP_MAX_VALUE 95

Use SGI0 interruption and TAMP_BACKUP_MAGIC_NUMBER to synchronize the core1 boot sequence requested by core0 in psci_cpu_on(): - a initial interruption is needed in ROM code after RCC_MP_GRSTCSETR_MPUP1RST (psci_cpu_off) - the ROM code set to 0 the 2 registers + TAMP_BACKUP_BRANCH_ADDRESS + TAMP_BACKUP_MAGIC_NUMBER when magic is not egual to BOOT_API_A7_CORE0_MAGIC_NUMBER
This patch solve issue for cpu1 restart in kernel. echo 0 > /sys/devices/system/cpu/cpu1/online echo 1 > /sys/devices/system/cpu/cpu1/online
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
arch/arm/mach-stm32mp/psci.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-stm32mp/psci.c b/arch/arm/mach-stm32mp/psci.c index c2dff38..139bb09 100644 --- a/arch/arm/mach-stm32mp/psci.c +++ b/arch/arm/mach-stm32mp/psci.c @@ -47,14 +47,14 @@ static u32 __secure stm32mp_get_gicd_base_address(void) return (periphbase & CBAR_MASK) + GIC_DIST_OFFSET; }
-static void __secure stm32mp_smp_kick_all_cpus(void) +static void __secure stm32mp_raise_sgi0(int cpu) { u32 gic_dist_addr;
gic_dist_addr = stm32mp_get_gicd_base_address();
- /* kick all CPUs (except this one) by writing to GICD_SGIR */ - writel(1U << 24, gic_dist_addr + GICD_SGIR); + /* ask cpu with SGI0 */ + writel((BIT(cpu) << 16), gic_dist_addr + GICD_SGIR); }
void __secure psci_arch_cpu_entry(void) @@ -62,6 +62,9 @@ void __secure psci_arch_cpu_entry(void) u32 cpu = psci_get_cpu_id();
psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON); + + /* reset magic in TAMP register */ + writel(0xFFFFFFFF, TAMP_BACKUP_MAGIC_NUMBER); }
int __secure psci_features(u32 function_id, u32 psci_fid) @@ -127,6 +130,16 @@ int __secure psci_cpu_on(u32 function_id, u32 target_cpu, u32 pc, if (psci_state[cpu] == PSCI_AFFINITY_LEVEL_ON) return ARM_PSCI_RET_ALREADY_ON;
+ /* reset magic in TAMP register */ + if (readl(TAMP_BACKUP_MAGIC_NUMBER)) + writel(0xFFFFFFFF, TAMP_BACKUP_MAGIC_NUMBER); + /* + * ROM code need a first SGI0 after core reset + * core is ready when magic is set to 0 in ROM code + */ + while (readl(TAMP_BACKUP_MAGIC_NUMBER)) + stm32mp_raise_sgi0(cpu); + /* store target PC and context id*/ psci_save(cpu, pc, context_id);
@@ -142,7 +155,8 @@ int __secure psci_cpu_on(u32 function_id, u32 target_cpu, u32 pc, writel(BOOT_API_A7_CORE0_MAGIC_NUMBER, TAMP_BACKUP_MAGIC_NUMBER);
- stm32mp_smp_kick_all_cpus(); + /* Generate an IT to start the core */ + stm32mp_raise_sgi0(cpu);
return ARM_PSCI_RET_SUCCESS; }

RCC is no more a mfd and add a complete example and alignment with latest TF-A binding
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
doc/device-tree-bindings/clock/st,stm32mp1.txt | 427 +++++++++++++++++-------- 1 file changed, 287 insertions(+), 140 deletions(-)
diff --git a/doc/device-tree-bindings/clock/st,stm32mp1.txt b/doc/device-tree-bindings/clock/st,stm32mp1.txt index ffcf8cd..02e1460 100644 --- a/doc/device-tree-bindings/clock/st,stm32mp1.txt +++ b/doc/device-tree-bindings/clock/st,stm32mp1.txt @@ -1,185 +1,186 @@ STMicroelectronics STM32MP1 clock tree initialization =====================================================
-The STM32MP clock tree initialization is based on device tree information -for RCC IP and on fixed clocks. +The STM32MP1 clock tree initialization is based on device tree information +for RCC IP node (st,stm32mp1-rcc) and on fixed-clock nodes.
-------------------------------- -RCC CLOCK = st,stm32mp1-rcc-clk -------------------------------- +RCC IP = st,stm32mp1-rcc +========================
The RCC IP is both a reset and a clock controller but this documentation only describes the fields added for clock tree initialization which are not present -in Linux binding. +in Linux binding for compatible "st,stm32mp1-rcc" defined in st,stm32mp1-rcc.txt +file.
-Please refer to ../mfd/st,stm32-rcc.txt for all the other properties common -with Linux. +The added properties for clock tree initialization are:
Required properties: +- st,clksrc : The clock sources configuration array in a platform specific + order.
-- compatible: Should be "st,stm32mp1-rcc-clk" + For the STM32MP15x family there are 9 clock sources selector which are + configured in the following order: + MPU AXI MCU PLL12 PLL3 PLL4 RTC MCO1 MCO2
-- st,clksrc : The clock source in this order + Clock source configuration values are defined by macros CLK_<NAME>_<SOURCE> + from dt-bindings/clock/stm32mp1-clksrc.h.
- for STM32MP15x: 9 clock sources are requested - MPU AXI MCU PLL12 PLL3 PLL4 RTC MCO1 MCO2 - - with value equals to RCC clock specifier as defined in - dt-bindings/clock/stm32mp1-clksrc.h: CLK_<NAME>_<SOURCE> - -- st,clkdiv : The div parameters in this order - for STM32MP15x: 11 dividers value are requested + Example: + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + +- st,clkdiv : The clock main dividers value specified in an array + in a platform specific order. + + When used, it shall describe the whole clock dividers tree. + + For the STM32MP15x family there are 11 dividers values expected. + They shall be configured in the following order: MPU AXI MCU APB1 APB2 APB3 APB4 APB5 RTC MCO1 MCO2
- with DIV coding defined in RCC associated register RCC_xxxDIVR - - most the case, it is: + The each divider value uses the DIV coding defined in RCC associated + register RCC_xxxDIVR. In most the case, it is: 0x0: not divided 0x1: division by 2 0x2: division by 4 0x3: division by 8 ...
- but for RTC MCO1 MCO2, the coding is different: + Note that for RTC MCO1 MCO2, the coding is different: 0x0: not divided 0x1: division by 2 0x2: division by 3 0x3: division by 4 ...
-Optional Properties: -- st,pll - PLL children node for PLL1 to PLL4 : (see ref manual for details) - with associated index 0 to 3 (st,pll@0 to st,pll@4) - PLLx is off when the associated node is absent + Example: + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >;
- - Sub-nodes: +Optional Properties: +- st,pll : A specific PLL configuration, including frequency.
- - cfg: The parameters for PLL configuration in this order: - DIVM DIVN DIVP DIVQ DIVR Output + PLL children nodes for PLL1 to PLL4 (see ref manual for details) + are listed with associated index 0 to 3 (st,pll@0 to st,pll@3). + PLLx is off when the associated node is absent.
- with DIV value as defined in RCC spec: - 0x0: bypass (division by 1) - 0x1: division by 2 - 0x2: division by 3 - 0x3: division by 4 - ... + Here are the available properties for each PLL node:
- and Output = bitfield for each output value = 1:ON/0:OFF - BIT(0) => output P : DIVPEN - BIT(1) => output Q : DIVQEN - BIT(2) => output R : DIVREN - NB : macro PQR(p,q,r) can be used to build this value - with p,p,r = 0 or 1 + - cfg: The parameters for PLL configuration in the following order: + DIVM DIVN DIVP DIVQ DIVR Output.
- - frac : Fractional part of the multiplication factor - (optional, PLL is in integer mode when absent) + DIVx values are defined as in RCC spec: + 0x0: bypass (division by 1) + 0x1: division by 2 + 0x2: division by 3 + 0x3: division by 4 + ...
- - csg : Clock Spreading Generator (optional) - with parameters in this order: - MOD_PER INC_STEP SSCG_MODE + Output contains a bitfield for each output value (1:ON/0:OFF) + BIT(0) => output P : DIVPEN + BIT(1) => output Q : DIVQEN + BIT(2) => output R : DIVREN + NB: macro PQR(p,q,r) can be used to build this value + with p,q,r = 0 or 1. + + - frac : Fractional part of the multiplication factor + (optional, PLL is in integer mode when absent). + + - csg : Clock Spreading Generator (optional) with parameters in the + following order: MOD_PER INC_STEP SSCG_MODE. + + MOD_PER: Modulation Period Adjustment + INC_STEP: Modulation Depth Adjustment + SSCG_MODE: Spread spectrum clock generator mode, with associated + defined from stm32mp1-clksrc.h: + - SSCG_MODE_CENTER_SPREAD = 0 + - SSCG_MODE_DOWN_SPREAD = 1 + + Example: + st,pll@0 { + cfg = < 1 53 0 0 0 1 >; + frac = < 0x810 >; + }; + st,pll@1 { + cfg = < 1 43 1 0 0 PQR(0,1,1) >; + csg = < 10 20 1 >; + }; + st,pll@2 { + cfg = < 2 85 3 13 3 0 >; + csg = < 10 20 SSCG_MODE_CENTER_SPREAD >; + }; + st,pll@3 { + cfg = < 2 78 4 7 9 3 >; + };
- * MOD_PER: Modulation Period Adjustment - * INC_STEP: Modulation Depth Adjustment - * SSCG_MODE: Spread spectrum clock generator mode - you can use associated defines from stm32mp1-clksrc.h - * SSCG_MODE_CENTER_SPREAD = 0 - * SSCG_MODE_DOWN_SPREAD = 1 +- st,pkcs : used to configure the peripherals kernel clock selection.
+ The property is a list of peripheral kernel clock source identifiers defined + by macros CLK_<KERNEL-CLOCK>_<PARENT-CLOCK> as defined by header file + dt-bindings/clock/stm32mp1-clksrc.h.
-- st,pkcs : used to configure the peripherals kernel clock selection - containing a list of peripheral kernel clock source identifier as defined - in the file dt-bindings/clock/stm32mp1-clksrc.h + st,pkcs may not list all the kernel clocks and has no ordering requirements.
Example: + st,pkcs = < + CLK_STGEN_HSE + CLK_CKPER_HSI + CLK_USBPHY_PLL2P + CLK_DSI_PLL2Q + CLK_I2C46_HSI + CLK_UART1_HSI + CLK_UART24_HSI + >;
- rcc: rcc@50000000 { - compatible = "syscon", "simple-mfd"; - - reg = <0x50000000 0x1000>; - - rcc_clk: rcc-clk@50000000 { - #clock-cells = <1>; - compatible = "st,stm32mp1-rcc-clk"; - - st,clksrc = < CLK_MPU_PLL1P - CLK_AXI_PLL2P - CLK_MCU_HSI - CLK_PLL12_HSE - CLK_PLL3_HSE - CLK_PLL4_HSE - CLK_RTC_HSE - CLK_MCO1_DISABLED - CLK_MCO2_DISABLED - >; - - st,clkdiv = < - 1 /*MPU*/ - 0 /*AXI*/ - 0 /*MCU*/ - 1 /*APB1*/ - 1 /*APB2*/ - 1 /*APB3*/ - 1 /*APB4*/ - 5 /*APB5*/ - 23 /*RTC*/ - 0 /*MCO1*/ - 0 /*MCO2*/ - >; - - st,pll@0 { - cfg = < 1 53 0 0 0 1 >; - frac = < 0x810 >; - }; - st,pll@1 { - cfg = < 1 43 1 0 0 PQR(0,1,1) >; - csg = < 10 20 1 >; - }; - st,pll@2 { - cfg = < 2 85 3 13 3 0 >; - csg = < 10 20 SSCG_MODE_CENTER_SPREAD >; - }; - st,pll@3 { - cfg = < 2 78 4 7 9 3 >; - }; - st,pkcs = < - CLK_STGEN_HSE - CLK_CKPER_HSI - CLK_USBPHY_PLL2P - CLK_DSI_PLL2Q - >; - }; - }; - --------------------------- other clocks = fixed-clock --------------------------- +========================== + The clock tree is also based on 5 fixed-clock in clocks node used to define the state of associated ST32MP1 oscillators: -- clk-lsi -- clk-lse -- clk-hsi -- clk-hse -- clk-csi + - clk-lsi + - clk-lse + - clk-hsi + - clk-hse + - clk-csi
At boot the clock tree initialization will -- enable the oscillator present in device tree -- disable HSI oscillator if the node is absent (always activated by bootrom) + - enable oscillators present in device tree + - disable HSI oscillator if the node is absent (always activated by bootrom)
Optional properties :
a) for external oscillator: "clk-lse", "clk-hse"
- 4 optional fields are managed - - "st,bypass" Configure the oscillator bypass mode (HSEBYP, LSEBYP) - - "st,digbypass" Configure the bypass mode as full-swing digital signal - (DIGBYP) - - "st,css" Activate the clock security system (HSECSSON, LSECSSON) - - "st,drive" (only for LSE) value of the drive for the oscillator - (see LSEDRV_ define in the file dt-bindings/clock/stm32mp1-clksrc.h) - - Example board file: + 4 optional fields are managed + - "st,bypass" configures the oscillator bypass mode (HSEBYP, LSEBYP) + - "st,digbypass" configures the bypass mode as full-swing digital + signal (DIGBYP) + - "st,css" activates the clock security system (HSECSSON, LSECSSON) + - "st,drive" (only for LSE) contains the value of the drive for the + oscillator (see LSEDRV_ defined in the file + dt-bindings/clock/stm32mp1-clksrc.h)
+ Example board file: / { clocks { clk_hse: clk-hse { @@ -200,13 +201,12 @@ a) for external oscillator: "clk-lse", "clk-hse"
b) for internal oscillator: "clk-hsi"
- internally HSI clock is fixed to 64MHz for STM32MP157 soc - in device tree clk-hsi is the clock after HSIDIV (ck_hsi in RCC doc) - So this clock frequency is used to compute the expected HSI_DIV - for the clock tree initialisation - - ex: for HSIDIV = /1 + Internally HSI clock is fixed to 64MHz for STM32MP157 SoC. + In device tree, clk-hsi is the clock after HSIDIV (clk_hsi in RCC + doc). So this clock frequency is used to compute the expected HSI_DIV + for the clock tree initialization.
+ Example with HSIDIV = /1: / { clocks { clk_hsi: clk-hsi { @@ -216,8 +216,7 @@ b) for internal oscillator: "clk-hsi" }; };
- ex: for HSIDIV = /2 - + Example with HSIDIV = /2 / { clocks { clk_hsi: clk-hsi { @@ -226,3 +225,151 @@ b) for internal oscillator: "clk-hsi" clock-frequency = <32000000>; }; }; + +Example of clock tree initialization +==================================== + +/ { + clocks { + u-boot,dm-pre-reloc; + clk_hse: clk-hse { + u-boot,dm-pre-reloc; + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + st,digbypass; + }; + + clk_hsi: clk-hsi { + u-boot,dm-pre-reloc; + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <64000000>; + }; + + clk_lse: clk-lse { + u-boot,dm-pre-reloc; + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_lsi: clk-lsi { + u-boot,dm-pre-reloc; + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32000>; + }; + + clk_csi: clk-csi { + u-boot,dm-pre-reloc; + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <4000000>; + }; + }; + + soc { + + rcc: rcc@50000000 { + u-boot,dm-pre-reloc; + compatible = "st,stm32mp1-rcc", "syscon"; + reg = <0x50000000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; + + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_DISABLED + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4Q + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@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 { + cfg = < 2 65 1 0 0 PQR(1,1,1) >; + frac = < 0x1400 >; + u-boot,dm-pre-reloc; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + cfg = < 1 33 1 16 36 PQR(1,1,1) >; + frac = < 0x1a04 >; + u-boot,dm-pre-reloc; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { + cfg = < 3 98 5 7 7 PQR(1,1,1) >; + u-boot,dm-pre-reloc; + }; + }; + }; +};

From: Nicolas Le Bayon nicolas.le.bayon@st.com
It conforms with Reference Manual I2C timing section.
Signed-off-by: Nicolas Le Bayon nicolas.le.bayon@st.com Reviewed-by: Patrick DELAUNAY patrick.delaunay@st.com Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/i2c/stm32f7_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index 3872364..e7e0268 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -500,7 +500,7 @@ static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup, af_delay_max = setup->analog_filter ? STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0;
- sdadel_min = setup->fall_time - i2c_specs[setup->speed].hddat_min - + sdadel_min = i2c_specs[setup->speed].hddat_min + setup->fall_time - af_delay_min - (setup->dnf + 3) * i2cclk;
sdadel_max = i2c_specs[setup->speed].vddat_max - setup->rise_time -

From: Nicolas Le Bayon nicolas.le.bayon@st.com
This avoids useless loops inside the I2C timing algorithm. Actually, we support only one possible solution per prescaler value. So after finding a solution with a prescaler, the algorithm can switch directly to the next prescaler value.
Signed-off-by: Nicolas Le Bayon nicolas.le.bayon@st.com Reviewed-by: Patrick DELAUNAY patrick.delaunay@st.com Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/i2c/stm32f7_i2c.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index e7e0268..50c4fd0 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -540,8 +540,12 @@ static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup, p_prev = p;
list_add_tail(&v->node, solutions); + break; } } + + if (p_prev == p) + break; } }

To get more information from STM32 Header about the generated binary, we will add a new byte with the following field: replace padding byte 255 with 0x00 for "U-Boot"
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
tools/stm32image.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/tools/stm32image.c b/tools/stm32image.c index 08b32ba..ff3ec5f 100644 --- a/tools/stm32image.c +++ b/tools/stm32image.c @@ -14,6 +14,8 @@ #define HEADER_VERSION_V1 0x1 /* default option : bit0 => no signature */ #define HEADER_DEFAULT_OPTION (cpu_to_le32(0x00000001)) +/* default binary type for U-Boot */ +#define HEADER_TYPE_UBOOT (cpu_to_le32(0x00000000))
struct stm32_header { uint32_t magic_number; @@ -29,7 +31,8 @@ struct stm32_header { uint32_t option_flags; uint32_t ecdsa_algorithm; uint32_t ecdsa_public_key[64 / 4]; - uint32_t padding[84 / 4]; + uint32_t padding[83 / 4]; + uint32_t binary_type; };
static struct stm32_header stm32image_header; @@ -43,6 +46,7 @@ static void stm32image_default_header(struct stm32_header *ptr) ptr->header_version[VER_MAJOR_IDX] = HEADER_VERSION_V1; ptr->option_flags = HEADER_DEFAULT_OPTION; ptr->ecdsa_algorithm = 1; + ptr->binary_type = HEADER_TYPE_UBOOT; }
static uint32_t stm32image_checksum(void *start, uint32_t len) @@ -112,6 +116,8 @@ static void stm32image_print_header(const void *ptr) le32_to_cpu(stm32hdr->image_checksum)); printf("Option : 0x%08x\n", le32_to_cpu(stm32hdr->option_flags)); + printf("BinaryType : 0x%08x\n", + le32_to_cpu(stm32hdr->binary_type)); }
static void stm32image_set_header(void *ptr, struct stat *sbuf, int ifd,

Activate bootcount and use TAMP register to store the count value.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
arch/arm/mach-stm32mp/Kconfig | 11 +++++++++++ arch/arm/mach-stm32mp/include/mach/stm32.h | 1 + 2 files changed, 12 insertions(+)
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig index 26dace10..c984616 100644 --- a/arch/arm/mach-stm32mp/Kconfig +++ b/arch/arm/mach-stm32mp/Kconfig @@ -39,6 +39,8 @@ config TARGET_STM32MP1 select STM32_RCC select STM32_RESET select SYS_ARCH_TIMER + imply BOOTCOUNT_LIMIT + imply CMD_BOOTCOUNT imply SYSRESET_PSCI if STM32MP1_TRUSTED imply SYSRESET_SYSCON if !STM32MP1_TRUSTED help @@ -76,6 +78,15 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2 Partition on the second MMC to load U-Boot from when the MMC is being used in raw mode
+if BOOTCOUNT_LIMIT +config SYS_BOOTCOUNT_SINGLEWORD + default y + +# TAMP_BOOTCOUNT = TAMP_BACKUP_REGISTER(21) +config SYS_BOOTCOUNT_ADDR + default 0x5C00A154 +endif + if DEBUG_UART
config DEBUG_UART_BOARD_INIT diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index c526c88..6795352 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -88,6 +88,7 @@ enum boot_device { #define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4) #define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5) #define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20) +#define TAMP_BOOTCOUNT TAMP_BACKUP_REGISTER(21)
#define TAMP_BOOT_MODE_MASK GENMASK(15, 8) #define TAMP_BOOT_MODE_SHIFT 8

In initf_bootstage() we call bootstage_mark_name() which ends up calling timer_get_us() before timer_init(); that cause crash for stm32mp1.
This patch solve the issue without changing the initialization sequence. See also commit 97d20f69f53e ("Enable CONFIG_TIMER_EARLY with bootstage") for other solution when DM is activated for TIMER.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
arch/arm/cpu/armv7/arch_timer.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/arm/cpu/armv7/arch_timer.c b/arch/arm/cpu/armv7/arch_timer.c index 3db31c0..5de6305 100644 --- a/arch/arm/cpu/armv7/arch_timer.c +++ b/arch/arm/cpu/armv7/arch_timer.c @@ -49,6 +49,9 @@ unsigned long long get_ticks(void)
ulong timer_get_boot_us(void) { + if (!gd->arch.timer_rate_hz) + timer_init(); + return lldiv(get_ticks(), gd->arch.timer_rate_hz / 1000000); }

Add the needed configurations for bootstage and activate bootstage command.
BOOTSTAGE_REPORT is not activated by default.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
arch/arm/mach-stm32mp/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig index c984616..77f66c6 100644 --- a/arch/arm/mach-stm32mp/Kconfig +++ b/arch/arm/mach-stm32mp/Kconfig @@ -17,6 +17,8 @@ config SPL select SPL_DM_RESET select SPL_SERIAL_SUPPORT select SPL_SYSCON + imply BOOTSTAGE_STASH if SPL_BOOTSTAGE + imply SPL_BOOTSTAGE if BOOTSTAGE imply SPL_DISPLAY_PRINT imply SPL_LIBDISK_SUPPORT
@@ -40,7 +42,9 @@ config TARGET_STM32MP1 select STM32_RESET select SYS_ARCH_TIMER imply BOOTCOUNT_LIMIT + imply BOOTSTAGE imply CMD_BOOTCOUNT + imply CMD_BOOTSTAGE imply SYSRESET_PSCI if STM32MP1_TRUSTED imply SYSRESET_SYSCON if !STM32MP1_TRUSTED help @@ -78,6 +82,9 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2 Partition on the second MMC to load U-Boot from when the MMC is being used in raw mode
+config BOOTSTAGE_STASH_ADDR + default 0xC3000000 + if BOOTCOUNT_LIMIT config SYS_BOOTCOUNT_SINGLEWORD default y

Add the DDRPHYC support for clk_set_rate, used in DDR interactive mode
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/clk/clk_stm32mp1.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+)
diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index 24859fd..6272b00 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -1448,6 +1448,71 @@ static void pll_csg(struct stm32mp1_clk_priv *priv, int pll_id, u32 *csg) setbits_le32(priv->base + pll[pll_id].pllxcr, RCC_PLLNCR_SSCG_CTRL); }
+static __maybe_unused int pll_set_rate(struct udevice *dev, + int pll_id, + int div_id, + unsigned long clk_rate) +{ + struct stm32mp1_clk_priv *priv = dev_get_priv(dev); + unsigned int pllcfg[PLLCFG_NB]; + ofnode plloff; + char name[12]; + const struct stm32mp1_clk_pll *pll = priv->data->pll; + enum stm32mp1_plltype type = pll[pll_id].plltype; + int divm, divn, divy; + int ret; + ulong fck_ref; + u32 fracv; + u64 value; + + if (div_id > _DIV_NB) + return -EINVAL; + + sprintf(name, "st,pll@%d", pll_id); + plloff = dev_read_subnode(dev, name); + if (!ofnode_valid(plloff)) + return -FDT_ERR_NOTFOUND; + + ret = ofnode_read_u32_array(plloff, "cfg", + pllcfg, PLLCFG_NB); + if (ret < 0) + return -FDT_ERR_NOTFOUND; + + fck_ref = pll_get_fref_ck(priv, pll_id); + + divm = pllcfg[PLLCFG_M]; + /* select output divider = 0: for _DIV_P, 1:_DIV_Q 2:_DIV_R */ + divy = pllcfg[PLLCFG_P + div_id]; + + /* For: PLL1 & PLL2 => VCO is * 2 but ck_pll_y is also / 2 + * So same final result than PLL2 et 4 + * with FRACV + * Fck_pll_y = Fck_ref * ((DIVN + 1) + FRACV / 2^13) + * / (DIVy + 1) * (DIVM + 1) + * value = (DIVN + 1) * 2^13 + FRACV / 2^13 + * = Fck_pll_y (DIVy + 1) * (DIVM + 1) * 2^13 / Fck_ref + */ + value = ((u64)clk_rate * (divy + 1) * (divm + 1)) << 13; + value = lldiv(value, fck_ref); + + divn = (value >> 13) - 1; + if (divn < DIVN_MIN || + divn > stm32mp1_pll[type].divn_max) { + pr_err("divn invalid = %d", divn); + return -EINVAL; + } + fracv = value - ((divn + 1) << 13); + pllcfg[PLLCFG_N] = divn; + + /* reconfigure PLL */ + pll_stop(priv, pll_id); + pll_config(priv, pll_id, pllcfg, fracv); + pll_start(priv, pll_id); + pll_output(priv, pll_id, pllcfg[PLLCFG_O]); + + return 0; +} + static int set_clksrc(struct stm32mp1_clk_priv *priv, unsigned int clksrc) { u32 address = priv->base + (clksrc >> 4); @@ -1820,6 +1885,11 @@ static ulong stm32mp1_clk_set_rate(struct clk *clk, unsigned long clk_rate) int p;
switch (clk->id) { +#if defined(STM32MP1_CLOCK_TREE_INIT) && \ + defined(CONFIG_STM32MP1_DDR_INTERACTIVE) + case DDRPHYC: + break; +#endif case LTDC_PX: case DSI_PX: break; @@ -1833,6 +1903,19 @@ static ulong stm32mp1_clk_set_rate(struct clk *clk, unsigned long clk_rate) return -EINVAL;
switch (p) { +#if defined(STM32MP1_CLOCK_TREE_INIT) && \ + defined(CONFIG_STM32MP1_DDR_INTERACTIVE) + case _PLL2_R: /* DDRPHYC */ + { + /* only for change DDR clock in interactive mode */ + ulong result; + + set_clksrc(priv, CLK_AXI_HSI); + result = pll_set_rate(clk->dev, _PLL2, _DIV_R, clk_rate); + set_clksrc(priv, CLK_AXI_PLL2P); + return result; + } +#endif case _PLL4_Q: /* for LTDC_PX and DSI_PX case */ return pll_set_output_rate(clk->dev, _PLL4, _DIV_Q, clk_rate);

Solve compilation issue when cli_simple.o is used in SPL and CONFIG_SPL_ENV_SUPPORT is not defined.
env/built-in.o:(.data.env_htab+0xc): undefined reference to `env_flags_validate' u-boot/scripts/Makefile.spl:384: recipe for target 'spl/u-boot-spl' failed make[2]: *** [spl/u-boot-spl] Error 1 u-boot/Makefile:1649: recipe for target 'spl/u-boot-spl' failed make[1]: *** [spl/u-boot-spl] Error 2
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
env/common.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/env/common.c b/env/common.c index 324502e..bd340fe 100644 --- a/env/common.c +++ b/env/common.c @@ -23,7 +23,10 @@ DECLARE_GLOBAL_DATA_PTR; #include <env_default.h>
struct hsearch_data env_htab = { +#if CONFIG_IS_ENABLED(ENV_SUPPORT) + /* defined in flags.c, only compile with ENV_SUPPORT */ .change_ok = env_flags_validate, +#endif };
/* @@ -225,7 +228,9 @@ void env_relocate(void) #if defined(CONFIG_NEEDS_MANUAL_RELOC) env_reloc(); env_fix_drivers(); - env_htab.change_ok += gd->reloc_off; + + if (env_htab.change_ok) + env_htab.change_ok += gd->reloc_off; #endif if (gd->env_valid == ENV_INVALID) { #if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)

Remove the trace indicating the end of the DEBUG initialization
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/serial/serial_stm32.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c index e31c87b..315b5a2 100644 --- a/drivers/serial/serial_stm32.c +++ b/drivers/serial/serial_stm32.c @@ -269,7 +269,6 @@ static inline void _debug_uart_init(void) _stm32_serial_setbrg(base, uart_info, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); - printf("DEBUG done\n"); }
static inline void _debug_uart_putc(int c)

For STM32MP, the watchdog is based on DM and the function watchod_reset call the function uclass_get_device(UCLASS_WDT) to found the driver associated IWDG2.
As this reset is not mandatory in debug putc (the uart fifo will be empty after some us), we can simplify the code by removing this call.
And this patch avoid issue when putc is called before initialization of DM core, before the parsing of the device tree parsing and each node bound to driver; that also avoid memory leak.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/serial/serial_stm32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c index 315b5a2..cca8b70 100644 --- a/drivers/serial/serial_stm32.c +++ b/drivers/serial/serial_stm32.c @@ -277,7 +277,7 @@ static inline void _debug_uart_putc(int c) struct stm32_uart_info *uart_info = _debug_uart_info();
while (_stm32_serial_putc(base, uart_info, c) == -EAGAIN) - WATCHDOG_RESET(); + ; }
DEBUG_UART_FUNCS
participants (1)
-
Patrick Delaunay