Explorar o código

Merge tag 'u-boot-stm32-20200514' of https://gitlab.denx.de/u-boot/custodians/u-boot-stm

- stm32mp1: migrate MTD and DFU configuration in Kconfig
- stm32mp1: add command stm32prog
- stm32mp1: several board and arch updates
- stm32mp1: activate data cache in SPL and before relocation
- Many improvment for AV96 board and DHCOR SoM
  (add new defconfig, DDR3 coding on DHCOR SoM, split between board and SOM
   Synchronize DDR setttings on DH SoMs, setting for I2C EEPROM)
- clk: stm32mp1: fix CK_MPU calculation
- DT alignment of stm32mp1 device tree with Linux 5.7-rc2
Tom Rini %!s(int64=4) %!d(string=hai) anos
pai
achega
e2b86e23ce
Modificáronse 64 ficheiros con 5334 adicións e 893 borrados
  1. 221 137
      arch/arm/dts/stm32mp15-ddr.dtsi
  2. 24 25
      arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
  3. 24 25
      arch/arm/dts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
  4. 120 0
      arch/arm/dts/stm32mp15-ddr3-dhsom-2x1Gb-1066-binG.dtsi
  5. 120 0
      arch/arm/dts/stm32mp15-ddr3-dhsom-2x2Gb-1066-binG.dtsi
  6. 120 0
      arch/arm/dts/stm32mp15-ddr3-dhsom-2x4Gb-1066-binG.dtsi
  7. 92 0
      arch/arm/dts/stm32mp15-pinctrl.dtsi
  8. 25 0
      arch/arm/dts/stm32mp15-u-boot.dtsi
  9. 12 1
      arch/arm/dts/stm32mp151.dtsi
  10. 1 0
      arch/arm/dts/stm32mp153.dtsi
  11. 0 4
      arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
  12. 0 4
      arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi
  13. 11 6
      arch/arm/dts/stm32mp157c-ed1.dts
  14. 8 5
      arch/arm/dts/stm32mp157c-ev1.dts
  15. 14 1
      arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi
  16. 2 1
      arch/arm/dts/stm32mp15xx-dhcom.dtsi
  17. 1 0
      arch/arm/dts/stm32mp15xx-dhcor-avenger96-u-boot.dtsi
  18. 1 1
      arch/arm/dts/stm32mp15xx-dhcor-avenger96.dts
  19. 24 0
      arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi
  20. 1 20
      arch/arm/dts/stm32mp15xx-dhcor-io3v3.dtsi
  21. 11 1
      arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi
  22. 10 5
      arch/arm/dts/stm32mp15xx-dkx.dtsi
  23. 17 12
      arch/arm/mach-stm32mp/Kconfig
  24. 2 0
      arch/arm/mach-stm32mp/Makefile
  25. 45 0
      arch/arm/mach-stm32mp/boot_params.c
  26. 9 0
      arch/arm/mach-stm32mp/cmd_stm32prog/Makefile
  27. 192 0
      arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
  28. 1745 0
      arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
  29. 185 0
      arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
  30. 993 0
      arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_serial.c
  31. 230 0
      arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c
  32. 52 6
      arch/arm/mach-stm32mp/cpu.c
  33. 18 0
      arch/arm/mach-stm32mp/dram_init.c
  34. 25 0
      arch/arm/mach-stm32mp/fdt.c
  35. 3 0
      arch/arm/mach-stm32mp/include/mach/stm32.h
  36. 16 0
      arch/arm/mach-stm32mp/include/mach/stm32prog.h
  37. 5 0
      arch/arm/mach-stm32mp/include/mach/sys_proto.h
  38. 35 3
      arch/arm/mach-stm32mp/spl.c
  39. 2 1
      board/dhelectronics/dh_stm32mp1/Kconfig
  40. 1 0
      board/dhelectronics/dh_stm32mp1/MAINTAINERS
  41. 3 0
      board/dhelectronics/dh_stm32mp1/Makefile
  42. 90 142
      board/dhelectronics/dh_stm32mp1/board.c
  43. 39 0
      board/dhelectronics/dh_stm32mp1/u-boot-dhcom.its
  44. 39 0
      board/dhelectronics/dh_stm32mp1/u-boot-dhcor.its
  45. 64 0
      board/st/common/Kconfig
  46. 5 0
      board/st/common/Makefile
  47. 245 0
      board/st/common/stm32mp_dfu.c
  48. 167 0
      board/st/common/stm32mp_mtdparts.c
  49. 0 1
      board/st/stm32mp1/MAINTAINERS
  50. 78 279
      board/st/stm32mp1/stm32mp1.c
  51. 3 6
      configs/stm32mp15_basic_defconfig
  52. 7 0
      configs/stm32mp15_dhcom_basic_defconfig
  53. 46 39
      configs/stm32mp15_dhcor_basic_defconfig
  54. 6 6
      configs/stm32mp15_trusted_defconfig
  55. 61 86
      doc/board/st/stm32mp1.rst
  56. 4 3
      drivers/clk/clk_stm32mp1.c
  57. 1 6
      drivers/gpio/stm32_gpio.c
  58. 1 1
      drivers/mmc/stm32_sdmmc2.c
  59. 28 5
      drivers/ram/stm32mp1/stm32mp1_ram.c
  60. 8 0
      drivers/usb/gadget/g_dnl.c
  61. 15 0
      include/configs/dh_stm32mp1.h
  62. 3 61
      include/configs/stm32mp1.h
  63. 3 0
      include/dfu.h
  64. 1 0
      include/g_dnl.h

+ 221 - 137
arch/arm/dts/stm32mp15-ddr.dtsi

@@ -2,156 +2,240 @@
 /*
  * Copyright : STMicroelectronics 2018
  */
+#include <linux/stringify.h>
 
-/ {
-	soc {
-		ddr: ddr@5a003000 {
-			u-boot,dm-pre-reloc;
+&ddr {
+	config-DDR_MEM_COMPATIBLE {
+		u-boot,dm-pre-reloc;
 
-			compatible = "st,stm32mp1-ddr";
+		compatible = __stringify(st,DDR_MEM_COMPATIBLE);
 
-			reg = <0x5A003000 0x550
-			       0x5A004000 0x234>;
+		st,mem-name = DDR_MEM_NAME;
+		st,mem-speed = <DDR_MEM_SPEED>;
+		st,mem-size = <DDR_MEM_SIZE>;
 
-			clocks = <&rcc AXIDCG>,
-				 <&rcc DDRC1>,
-				 <&rcc DDRC2>,
-				 <&rcc DDRPHYC>,
-				 <&rcc DDRCAPB>,
-				 <&rcc DDRPHYCAPB>;
+		st,ctl-reg = <
+			DDR_MSTR
+			DDR_MRCTRL0
+			DDR_MRCTRL1
+			DDR_DERATEEN
+			DDR_DERATEINT
+			DDR_PWRCTL
+			DDR_PWRTMG
+			DDR_HWLPCTL
+			DDR_RFSHCTL0
+			DDR_RFSHCTL3
+			DDR_CRCPARCTL0
+			DDR_ZQCTL0
+			DDR_DFITMG0
+			DDR_DFITMG1
+			DDR_DFILPCFG0
+			DDR_DFIUPD0
+			DDR_DFIUPD1
+			DDR_DFIUPD2
+			DDR_DFIPHYMSTR
+			DDR_ODTMAP
+			DDR_DBG0
+			DDR_DBG1
+			DDR_DBGCMD
+			DDR_POISONCFG
+			DDR_PCCFG
+		>;
 
-			clock-names = "axidcg",
-				      "ddrc1",
-				      "ddrc2",
-				      "ddrphyc",
-				      "ddrcapb",
-				      "ddrphycapb";
+		st,ctl-timing = <
+			DDR_RFSHTMG
+			DDR_DRAMTMG0
+			DDR_DRAMTMG1
+			DDR_DRAMTMG2
+			DDR_DRAMTMG3
+			DDR_DRAMTMG4
+			DDR_DRAMTMG5
+			DDR_DRAMTMG6
+			DDR_DRAMTMG7
+			DDR_DRAMTMG8
+			DDR_DRAMTMG14
+			DDR_ODTCFG
+		>;
 
-			st,mem-name = DDR_MEM_NAME;
-			st,mem-speed = <DDR_MEM_SPEED>;
-			st,mem-size = <DDR_MEM_SIZE>;
+		st,ctl-map = <
+			DDR_ADDRMAP1
+			DDR_ADDRMAP2
+			DDR_ADDRMAP3
+			DDR_ADDRMAP4
+			DDR_ADDRMAP5
+			DDR_ADDRMAP6
+			DDR_ADDRMAP9
+			DDR_ADDRMAP10
+			DDR_ADDRMAP11
+		>;
 
-			st,ctl-reg = <
-				DDR_MSTR
-				DDR_MRCTRL0
-				DDR_MRCTRL1
-				DDR_DERATEEN
-				DDR_DERATEINT
-				DDR_PWRCTL
-				DDR_PWRTMG
-				DDR_HWLPCTL
-				DDR_RFSHCTL0
-				DDR_RFSHCTL3
-				DDR_CRCPARCTL0
-				DDR_ZQCTL0
-				DDR_DFITMG0
-				DDR_DFITMG1
-				DDR_DFILPCFG0
-				DDR_DFIUPD0
-				DDR_DFIUPD1
-				DDR_DFIUPD2
-				DDR_DFIPHYMSTR
-				DDR_ODTMAP
-				DDR_DBG0
-				DDR_DBG1
-				DDR_DBGCMD
-				DDR_POISONCFG
-				DDR_PCCFG
-			>;
+		st,ctl-perf = <
+			DDR_SCHED
+			DDR_SCHED1
+			DDR_PERFHPR1
+			DDR_PERFLPR1
+			DDR_PERFWR1
+			DDR_PCFGR_0
+			DDR_PCFGW_0
+			DDR_PCFGQOS0_0
+			DDR_PCFGQOS1_0
+			DDR_PCFGWQOS0_0
+			DDR_PCFGWQOS1_0
+			DDR_PCFGR_1
+			DDR_PCFGW_1
+			DDR_PCFGQOS0_1
+			DDR_PCFGQOS1_1
+			DDR_PCFGWQOS0_1
+			DDR_PCFGWQOS1_1
+		>;
 
-			st,ctl-timing = <
-				DDR_RFSHTMG
-				DDR_DRAMTMG0
-				DDR_DRAMTMG1
-				DDR_DRAMTMG2
-				DDR_DRAMTMG3
-				DDR_DRAMTMG4
-				DDR_DRAMTMG5
-				DDR_DRAMTMG6
-				DDR_DRAMTMG7
-				DDR_DRAMTMG8
-				DDR_DRAMTMG14
-				DDR_ODTCFG
-			>;
+		st,phy-reg = <
+			DDR_PGCR
+			DDR_ACIOCR
+			DDR_DXCCR
+			DDR_DSGCR
+			DDR_DCR
+			DDR_ODTCR
+			DDR_ZQ0CR1
+			DDR_DX0GCR
+			DDR_DX1GCR
+			DDR_DX2GCR
+			DDR_DX3GCR
+		>;
 
-			st,ctl-map = <
-				DDR_ADDRMAP1
-				DDR_ADDRMAP2
-				DDR_ADDRMAP3
-				DDR_ADDRMAP4
-				DDR_ADDRMAP5
-				DDR_ADDRMAP6
-				DDR_ADDRMAP9
-				DDR_ADDRMAP10
-				DDR_ADDRMAP11
-			>;
-
-			st,ctl-perf = <
-				DDR_SCHED
-				DDR_SCHED1
-				DDR_PERFHPR1
-				DDR_PERFLPR1
-				DDR_PERFWR1
-				DDR_PCFGR_0
-				DDR_PCFGW_0
-				DDR_PCFGQOS0_0
-				DDR_PCFGQOS1_0
-				DDR_PCFGWQOS0_0
-				DDR_PCFGWQOS1_0
-				DDR_PCFGR_1
-				DDR_PCFGW_1
-				DDR_PCFGQOS0_1
-				DDR_PCFGQOS1_1
-				DDR_PCFGWQOS0_1
-				DDR_PCFGWQOS1_1
-			>;
-
-			st,phy-reg = <
-				DDR_PGCR
-				DDR_ACIOCR
-				DDR_DXCCR
-				DDR_DSGCR
-				DDR_DCR
-				DDR_ODTCR
-				DDR_ZQ0CR1
-				DDR_DX0GCR
-				DDR_DX1GCR
-				DDR_DX2GCR
-				DDR_DX3GCR
-			>;
-
-			st,phy-timing = <
-				DDR_PTR0
-				DDR_PTR1
-				DDR_PTR2
-				DDR_DTPR0
-				DDR_DTPR1
-				DDR_DTPR2
-				DDR_MR0
-				DDR_MR1
-				DDR_MR2
-				DDR_MR3
-			>;
+		st,phy-timing = <
+			DDR_PTR0
+			DDR_PTR1
+			DDR_PTR2
+			DDR_DTPR0
+			DDR_DTPR1
+			DDR_DTPR2
+			DDR_MR0
+			DDR_MR1
+			DDR_MR2
+			DDR_MR3
+		>;
 
 #ifdef DDR_PHY_CAL_SKIP
-			st,phy-cal = <
-				DDR_DX0DLLCR
-				DDR_DX0DQTR
-				DDR_DX0DQSTR
-				DDR_DX1DLLCR
-				DDR_DX1DQTR
-				DDR_DX1DQSTR
-				DDR_DX2DLLCR
-				DDR_DX2DQTR
-				DDR_DX2DQSTR
-				DDR_DX3DLLCR
-				DDR_DX3DQTR
-				DDR_DX3DQSTR
-			>;
+		st,phy-cal = <
+			DDR_DX0DLLCR
+			DDR_DX0DQTR
+			DDR_DX0DQSTR
+			DDR_DX1DLLCR
+			DDR_DX1DQTR
+			DDR_DX1DQSTR
+			DDR_DX2DLLCR
+			DDR_DX2DQTR
+			DDR_DX2DQSTR
+			DDR_DX3DLLCR
+			DDR_DX3DQTR
+			DDR_DX3DQSTR
+		>;
 
 #endif
 
-			status = "okay";
-		};
+		status = "okay";
 	};
 };
+
+#undef DDR_MEM_COMPATIBLE
+#undef DDR_MEM_NAME
+#undef DDR_MEM_SPEED
+#undef DDR_MEM_SIZE
+
+#undef DDR_MSTR
+#undef DDR_MRCTRL0
+#undef DDR_MRCTRL1
+#undef DDR_DERATEEN
+#undef DDR_DERATEINT
+#undef DDR_PWRCTL
+#undef DDR_PWRTMG
+#undef DDR_HWLPCTL
+#undef DDR_RFSHCTL0
+#undef DDR_RFSHCTL3
+#undef DDR_RFSHTMG
+#undef DDR_CRCPARCTL0
+#undef DDR_DRAMTMG0
+#undef DDR_DRAMTMG1
+#undef DDR_DRAMTMG2
+#undef DDR_DRAMTMG3
+#undef DDR_DRAMTMG4
+#undef DDR_DRAMTMG5
+#undef DDR_DRAMTMG6
+#undef DDR_DRAMTMG7
+#undef DDR_DRAMTMG8
+#undef DDR_DRAMTMG14
+#undef DDR_ZQCTL0
+#undef DDR_DFITMG0
+#undef DDR_DFITMG1
+#undef DDR_DFILPCFG0
+#undef DDR_DFIUPD0
+#undef DDR_DFIUPD1
+#undef DDR_DFIUPD2
+#undef DDR_DFIPHYMSTR
+#undef DDR_ADDRMAP1
+#undef DDR_ADDRMAP2
+#undef DDR_ADDRMAP3
+#undef DDR_ADDRMAP4
+#undef DDR_ADDRMAP5
+#undef DDR_ADDRMAP6
+#undef DDR_ADDRMAP9
+#undef DDR_ADDRMAP10
+#undef DDR_ADDRMAP11
+#undef DDR_ODTCFG
+#undef DDR_ODTMAP
+#undef DDR_SCHED
+#undef DDR_SCHED1
+#undef DDR_PERFHPR1
+#undef DDR_PERFLPR1
+#undef DDR_PERFWR1
+#undef DDR_DBG0
+#undef DDR_DBG1
+#undef DDR_DBGCMD
+#undef DDR_POISONCFG
+#undef DDR_PCCFG
+#undef DDR_PCFGR_0
+#undef DDR_PCFGW_0
+#undef DDR_PCFGQOS0_0
+#undef DDR_PCFGQOS1_0
+#undef DDR_PCFGWQOS0_0
+#undef DDR_PCFGWQOS1_0
+#undef DDR_PCFGR_1
+#undef DDR_PCFGW_1
+#undef DDR_PCFGQOS0_1
+#undef DDR_PCFGQOS1_1
+#undef DDR_PCFGWQOS0_1
+#undef DDR_PCFGWQOS1_1
+#undef DDR_PGCR
+#undef DDR_PTR0
+#undef DDR_PTR1
+#undef DDR_PTR2
+#undef DDR_ACIOCR
+#undef DDR_DXCCR
+#undef DDR_DSGCR
+#undef DDR_DCR
+#undef DDR_DTPR0
+#undef DDR_DTPR1
+#undef DDR_DTPR2
+#undef DDR_MR0
+#undef DDR_MR1
+#undef DDR_MR2
+#undef DDR_MR3
+#undef DDR_ODTCR
+#undef DDR_ZQ0CR1
+#undef DDR_DX0GCR
+#undef DDR_DX0DLLCR
+#undef DDR_DX0DQTR
+#undef DDR_DX0DQSTR
+#undef DDR_DX1GCR
+#undef DDR_DX1DLLCR
+#undef DDR_DX1DQTR
+#undef DDR_DX1DQSTR
+#undef DDR_DX2GCR
+#undef DDR_DX2DLLCR
+#undef DDR_DX2DQTR
+#undef DDR_DX2DQSTR
+#undef DDR_DX3GCR
+#undef DDR_DX3DLLCR
+#undef DDR_DX3DQTR
+#undef DDR_DX3DQSTR

+ 24 - 25
arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi

@@ -1,24 +1,23 @@
 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
 /*
  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+/*
+ * File generated by STMicroelectronics STM32CubeMX DDR Tool for MPUs
+ * DDR type: DDR3 / DDR3L
+ * DDR width: 16bits
+ * DDR density: 4Gb
+ * System frequency: 533000Khz
+ * Relaxed Timing Mode: false
+ * Address mapping type: RBC
  *
- * STM32MP157C DK1/DK2 BOARD configuration
- * 1x DDR3L 4Gb, 16-bit, 533MHz.
- * Reference used NT5CC256M16DP-DI from NANYA
- *
- * DDR type / Platform	DDR3/3L
- * freq		533MHz
- * width	16
- * datasheet	0  = MT41J256M16-187 / DDR3-1066 bin G
- * DDR density	4
- * timing mode	optimized
- * Scheduling/QoS options : type = 2
- * address mapping : RBC
- * Tc > + 85C : N
+ * Save Date: 2020.02.20, save Time: 18:45:20
  */
-#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.45"
-#define DDR_MEM_SPEED 533000
-#define DDR_MEM_SIZE 0x20000000
+#define DDR_MEM_COMPATIBLE ddr3-1066-888-bin-g-1x4gb-533mhz
+#define DDR_MEM_NAME	"DDR3-DDR3L 16bits 533000Khz"
+#define DDR_MEM_SPEED	533000
+#define DDR_MEM_SIZE	0x20000000
 
 #define DDR_MSTR 0x00041401
 #define DDR_MRCTRL0 0x00000010
@@ -50,15 +49,6 @@
 #define DDR_DFIUPD1 0x00000000
 #define DDR_DFIUPD2 0x00000000
 #define DDR_DFIPHYMSTR 0x00000000
-#define DDR_ADDRMAP1 0x00070707
-#define DDR_ADDRMAP2 0x00000000
-#define DDR_ADDRMAP3 0x1F000000
-#define DDR_ADDRMAP4 0x00001F1F
-#define DDR_ADDRMAP5 0x06060606
-#define DDR_ADDRMAP6 0x0F060606
-#define DDR_ADDRMAP9 0x00000000
-#define DDR_ADDRMAP10 0x00000000
-#define DDR_ADDRMAP11 0x00000000
 #define DDR_ODTCFG 0x06000600
 #define DDR_ODTMAP 0x00000001
 #define DDR_SCHED 0x00000C01
@@ -83,6 +73,15 @@
 #define DDR_PCFGQOS1_1 0x00800040
 #define DDR_PCFGWQOS0_1 0x01100C03
 #define DDR_PCFGWQOS1_1 0x01000200
+#define DDR_ADDRMAP1 0x00070707
+#define DDR_ADDRMAP2 0x00000000
+#define DDR_ADDRMAP3 0x1F000000
+#define DDR_ADDRMAP4 0x00001F1F
+#define DDR_ADDRMAP5 0x06060606
+#define DDR_ADDRMAP6 0x0F060606
+#define DDR_ADDRMAP9 0x00000000
+#define DDR_ADDRMAP10 0x00000000
+#define DDR_ADDRMAP11 0x00000000
 #define DDR_PGCR 0x01442E02
 #define DDR_PTR0 0x0022AA5B
 #define DDR_PTR1 0x04841104

+ 24 - 25
arch/arm/dts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi

@@ -1,24 +1,23 @@
 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
 /*
  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+/*
+ * File generated by STMicroelectronics STM32CubeMX DDR Tool for MPUs
+ * DDR type: DDR3 / DDR3L
+ * DDR width: 32bits
+ * DDR density: 8Gb
+ * System frequency: 533000Khz
+ * Relaxed Timing Mode: false
+ * Address mapping type: RBC
  *
- * STM32MP157C ED1 BOARD configuration
- * 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology.
- * Reference used NT5CC256M16DP-DI from NANYA
- *
- * DDR type / Platform	DDR3/3L
- * freq		533MHz
- * width	32
- * datasheet	0  = MT41J256M16-187 / DDR3-1066 bin G
- * DDR density	8
- * timing mode	optimized
- * Scheduling/QoS options : type = 2
- * address mapping : RBC
- * Tc > + 85C : N
+ * Save Date: 2020.02.20, save Time: 18:49:33
  */
-#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.45"
-#define DDR_MEM_SPEED 533000
-#define DDR_MEM_SIZE 0x40000000
+#define DDR_MEM_COMPATIBLE ddr3-1066-888-bin-g-2x4gb-533mhz
+#define DDR_MEM_NAME	"DDR3-DDR3L 32bits 533000Khz"
+#define DDR_MEM_SPEED	533000
+#define DDR_MEM_SIZE	0x40000000
 
 #define DDR_MSTR 0x00040401
 #define DDR_MRCTRL0 0x00000010
@@ -50,15 +49,6 @@
 #define DDR_DFIUPD1 0x00000000
 #define DDR_DFIUPD2 0x00000000
 #define DDR_DFIPHYMSTR 0x00000000
-#define DDR_ADDRMAP1 0x00080808
-#define DDR_ADDRMAP2 0x00000000
-#define DDR_ADDRMAP3 0x00000000
-#define DDR_ADDRMAP4 0x00001F1F
-#define DDR_ADDRMAP5 0x07070707
-#define DDR_ADDRMAP6 0x0F070707
-#define DDR_ADDRMAP9 0x00000000
-#define DDR_ADDRMAP10 0x00000000
-#define DDR_ADDRMAP11 0x00000000
 #define DDR_ODTCFG 0x06000600
 #define DDR_ODTMAP 0x00000001
 #define DDR_SCHED 0x00000C01
@@ -83,6 +73,15 @@
 #define DDR_PCFGQOS1_1 0x00800040
 #define DDR_PCFGWQOS0_1 0x01100C03
 #define DDR_PCFGWQOS1_1 0x01000200
+#define DDR_ADDRMAP1 0x00080808
+#define DDR_ADDRMAP2 0x00000000
+#define DDR_ADDRMAP3 0x00000000
+#define DDR_ADDRMAP4 0x00001F1F
+#define DDR_ADDRMAP5 0x07070707
+#define DDR_ADDRMAP6 0x0F070707
+#define DDR_ADDRMAP9 0x00000000
+#define DDR_ADDRMAP10 0x00000000
+#define DDR_ADDRMAP11 0x00000000
 #define DDR_PGCR 0x01442E02
 #define DDR_PTR0 0x0022AA5B
 #define DDR_PTR1 0x04841104

+ 120 - 0
arch/arm/dts/stm32mp15-ddr3-dhsom-2x1Gb-1066-binG.dtsi

@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2020, DH electronics - All Rights Reserved
+ *
+ * STM32MP15xx DHSOM configuration
+ * 2x DDR3L 1Gb each, 16-bit, 533MHz, Single Die Package in flyby topology.
+ * Reference used W631GU6MB15I from Winbond
+ *
+ * DDR type / Platform	DDR3/3L
+ * freq		533MHz
+ * width	32
+ * datasheet	0  = W631GU6MB15I / DDR3-1333
+ * DDR density	2
+ * timing mode	optimized
+ * address mapping : RBC
+ * Tc > + 85C : J
+ */
+#define DDR_MEM_COMPATIBLE ddr3l-dhsom-1066-888-bin-g-2x1gb-533mhz
+#define DDR_MEM_NAME "DDR3L 32bits 2x1Gb 533MHz"
+#define DDR_MEM_SPEED 533000
+#define DDR_MEM_SIZE 0x10000000
+
+#define DDR_MSTR 0x00040401
+#define DDR_MRCTRL0 0x00000010
+#define DDR_MRCTRL1 0x00000000
+#define DDR_DERATEEN 0x00000000
+#define DDR_DERATEINT 0x00800000
+#define DDR_PWRCTL 0x00000000
+#define DDR_PWRTMG 0x00400010
+#define DDR_HWLPCTL 0x00000000
+#define DDR_RFSHCTL0 0x00210000
+#define DDR_RFSHCTL3 0x00000000
+#define DDR_RFSHTMG 0x0040008B
+#define DDR_CRCPARCTL0 0x00000000
+#define DDR_DRAMTMG0 0x121B1214
+#define DDR_DRAMTMG1 0x000A041C
+#define DDR_DRAMTMG2 0x0608090F
+#define DDR_DRAMTMG3 0x0050400C
+#define DDR_DRAMTMG4 0x08040608
+#define DDR_DRAMTMG5 0x06060403
+#define DDR_DRAMTMG6 0x02020002
+#define DDR_DRAMTMG7 0x00000202
+#define DDR_DRAMTMG8 0x00001005
+#define DDR_DRAMTMG14 0x000000A0
+#define DDR_ZQCTL0 0xC2000040
+#define DDR_DFITMG0 0x02060105
+#define DDR_DFITMG1 0x00000202
+#define DDR_DFILPCFG0 0x07000000
+#define DDR_DFIUPD0 0xC0400003
+#define DDR_DFIUPD1 0x00000000
+#define DDR_DFIUPD2 0x00000000
+#define DDR_DFIPHYMSTR 0x00000000
+#define DDR_ODTCFG 0x06000600
+#define DDR_ODTMAP 0x00000001
+#define DDR_SCHED 0x00000C01
+#define DDR_SCHED1 0x00000000
+#define DDR_PERFHPR1 0x01000001
+#define DDR_PERFLPR1 0x08000200
+#define DDR_PERFWR1 0x08000400
+#define DDR_DBG0 0x00000000
+#define DDR_DBG1 0x00000000
+#define DDR_DBGCMD 0x00000000
+#define DDR_POISONCFG 0x00000000
+#define DDR_PCCFG 0x00000010
+#define DDR_PCFGR_0 0x00010000
+#define DDR_PCFGW_0 0x00000000
+#define DDR_PCFGQOS0_0 0x02100C03
+#define DDR_PCFGQOS1_0 0x00800100
+#define DDR_PCFGWQOS0_0 0x01100C03
+#define DDR_PCFGWQOS1_0 0x01000200
+#define DDR_PCFGR_1 0x00010000
+#define DDR_PCFGW_1 0x00000000
+#define DDR_PCFGQOS0_1 0x02100C03
+#define DDR_PCFGQOS1_1 0x00800040
+#define DDR_PCFGWQOS0_1 0x01100C03
+#define DDR_PCFGWQOS1_1 0x01000200
+#define DDR_ADDRMAP1 0x00080808
+#define DDR_ADDRMAP2 0x00000000
+#define DDR_ADDRMAP3 0x00000000
+#define DDR_ADDRMAP4 0x00001F1F
+#define DDR_ADDRMAP5 0x07070707
+#define DDR_ADDRMAP6 0x0F0F0F07
+#define DDR_ADDRMAP9 0x00000000
+#define DDR_ADDRMAP10 0x00000000
+#define DDR_ADDRMAP11 0x00000000
+#define DDR_PGCR 0x01442E02
+#define DDR_PTR0 0x0022AA5B
+#define DDR_PTR1 0x04841104
+#define DDR_PTR2 0x042DA068
+#define DDR_ACIOCR 0x10400812
+#define DDR_DXCCR 0x00000C40
+#define DDR_DSGCR 0xF200011F
+#define DDR_DCR 0x0000000B
+#define DDR_DTPR0 0x38D488D0
+#define DDR_DTPR1 0x098B00D8
+#define DDR_DTPR2 0x10023600
+#define DDR_MR0 0x00000840
+#define DDR_MR1 0x00000000
+#define DDR_MR2 0x00000248
+#define DDR_MR3 0x00000000
+#define DDR_ODTCR 0x00010000
+#define DDR_ZQ0CR1 0x00000038
+#define DDR_DX0GCR 0x0000CE81
+#define DDR_DX0DLLCR 0x40000000
+#define DDR_DX0DQTR 0xFFFFFFFF
+#define DDR_DX0DQSTR 0x3DB02000
+#define DDR_DX1GCR 0x0000CE81
+#define DDR_DX1DLLCR 0x40000000
+#define DDR_DX1DQTR 0xFFFFFFFF
+#define DDR_DX1DQSTR 0x3DB02000
+#define DDR_DX2GCR 0x0000CE81
+#define DDR_DX2DLLCR 0x40000000
+#define DDR_DX2DQTR 0xFFFFFFFF
+#define DDR_DX2DQSTR 0x3DB02000
+#define DDR_DX3GCR 0x0000CE81
+#define DDR_DX3DLLCR 0x40000000
+#define DDR_DX3DQTR 0xFFFFFFFF
+#define DDR_DX3DQSTR 0x3DB02000
+
+#include "stm32mp15-ddr.dtsi"

+ 120 - 0
arch/arm/dts/stm32mp15-ddr3-dhsom-2x2Gb-1066-binG.dtsi

@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2020, DH electronics - All Rights Reserved
+ *
+ * STM32MP15xx DHSOM configuration
+ * 2x DDR3L 2Gb each, 16-bit, 533MHz, Single Die Package in flyby topology.
+ * Reference used W632GU6NB15I from Winbond
+ *
+ * DDR type / Platform	DDR3/3L
+ * freq		533MHz
+ * width	32
+ * datasheet	0  = W632GU6NB15I / DDR3-1333
+ * DDR density	4
+ * timing mode	optimized
+ * address mapping : RBC
+ * Tc > + 85C : J
+ */
+#define DDR_MEM_COMPATIBLE ddr3l-dhsom-1066-888-bin-g-2x2gb-533mhz
+#define DDR_MEM_NAME "DDR3L 32bits 2x2Gb 533MHz"
+#define DDR_MEM_SPEED 533000
+#define DDR_MEM_SIZE 0x20000000
+
+#define DDR_MSTR 0x00040401
+#define DDR_MRCTRL0 0x00000010
+#define DDR_MRCTRL1 0x00000000
+#define DDR_DERATEEN 0x00000000
+#define DDR_DERATEINT 0x00800000
+#define DDR_PWRCTL 0x00000000
+#define DDR_PWRTMG 0x00400010
+#define DDR_HWLPCTL 0x00000000
+#define DDR_RFSHCTL0 0x00210000
+#define DDR_RFSHCTL3 0x00000000
+#define DDR_RFSHTMG 0x0040008B
+#define DDR_CRCPARCTL0 0x00000000
+#define DDR_DRAMTMG0 0x121B1214
+#define DDR_DRAMTMG1 0x000A041C
+#define DDR_DRAMTMG2 0x0608090F
+#define DDR_DRAMTMG3 0x0050400C
+#define DDR_DRAMTMG4 0x08040608
+#define DDR_DRAMTMG5 0x06060403
+#define DDR_DRAMTMG6 0x02020002
+#define DDR_DRAMTMG7 0x00000202
+#define DDR_DRAMTMG8 0x00001005
+#define DDR_DRAMTMG14 0x000000A0
+#define DDR_ZQCTL0 0xC2000040
+#define DDR_DFITMG0 0x02060105
+#define DDR_DFITMG1 0x00000202
+#define DDR_DFILPCFG0 0x07000000
+#define DDR_DFIUPD0 0xC0400003
+#define DDR_DFIUPD1 0x00000000
+#define DDR_DFIUPD2 0x00000000
+#define DDR_DFIPHYMSTR 0x00000000
+#define DDR_ODTCFG 0x06000600
+#define DDR_ODTMAP 0x00000001
+#define DDR_SCHED 0x00000C01
+#define DDR_SCHED1 0x00000000
+#define DDR_PERFHPR1 0x01000001
+#define DDR_PERFLPR1 0x08000200
+#define DDR_PERFWR1 0x08000400
+#define DDR_DBG0 0x00000000
+#define DDR_DBG1 0x00000000
+#define DDR_DBGCMD 0x00000000
+#define DDR_POISONCFG 0x00000000
+#define DDR_PCCFG 0x00000010
+#define DDR_PCFGR_0 0x00010000
+#define DDR_PCFGW_0 0x00000000
+#define DDR_PCFGQOS0_0 0x02100C03
+#define DDR_PCFGQOS1_0 0x00800100
+#define DDR_PCFGWQOS0_0 0x01100C03
+#define DDR_PCFGWQOS1_0 0x01000200
+#define DDR_PCFGR_1 0x00010000
+#define DDR_PCFGW_1 0x00000000
+#define DDR_PCFGQOS0_1 0x02100C03
+#define DDR_PCFGQOS1_1 0x00800040
+#define DDR_PCFGWQOS0_1 0x01100C03
+#define DDR_PCFGWQOS1_1 0x01000200
+#define DDR_ADDRMAP1 0x00080808
+#define DDR_ADDRMAP2 0x00000000
+#define DDR_ADDRMAP3 0x00000000
+#define DDR_ADDRMAP4 0x00001F1F
+#define DDR_ADDRMAP5 0x07070707
+#define DDR_ADDRMAP6 0x0F0F0707
+#define DDR_ADDRMAP9 0x00000000
+#define DDR_ADDRMAP10 0x00000000
+#define DDR_ADDRMAP11 0x00000000
+#define DDR_PGCR 0x01442E02
+#define DDR_PTR0 0x0022AA5B
+#define DDR_PTR1 0x04841104
+#define DDR_PTR2 0x042DA068
+#define DDR_ACIOCR 0x10400812
+#define DDR_DXCCR 0x00000C40
+#define DDR_DSGCR 0xF200011F
+#define DDR_DCR 0x0000000B
+#define DDR_DTPR0 0x38D488D0
+#define DDR_DTPR1 0x098B00D8
+#define DDR_DTPR2 0x10023600
+#define DDR_MR0 0x00000840
+#define DDR_MR1 0x00000000
+#define DDR_MR2 0x00000248
+#define DDR_MR3 0x00000000
+#define DDR_ODTCR 0x00010000
+#define DDR_ZQ0CR1 0x00000038
+#define DDR_DX0GCR 0x0000CE81
+#define DDR_DX0DLLCR 0x40000000
+#define DDR_DX0DQTR 0xFFFFFFFF
+#define DDR_DX0DQSTR 0x3DB02000
+#define DDR_DX1GCR 0x0000CE81
+#define DDR_DX1DLLCR 0x40000000
+#define DDR_DX1DQTR 0xFFFFFFFF
+#define DDR_DX1DQSTR 0x3DB02000
+#define DDR_DX2GCR 0x0000CE81
+#define DDR_DX2DLLCR 0x40000000
+#define DDR_DX2DQTR 0xFFFFFFFF
+#define DDR_DX2DQSTR 0x3DB02000
+#define DDR_DX3GCR 0x0000CE81
+#define DDR_DX3DLLCR 0x40000000
+#define DDR_DX3DQTR 0xFFFFFFFF
+#define DDR_DX3DQSTR 0x3DB02000
+
+#include "stm32mp15-ddr.dtsi"

+ 120 - 0
arch/arm/dts/stm32mp15-ddr3-dhsom-2x4Gb-1066-binG.dtsi

@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2020, DH electronics - All Rights Reserved
+ *
+ * STM32MP15xx DHSOM configuration
+ * 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology.
+ * Reference used W634GU6NB15I from Winbond
+ *
+ * DDR type / Platform	DDR3/3L
+ * freq		533MHz
+ * width	32
+ * datasheet	0  = W634GU6NB15I / DDR3-1333
+ * DDR density	8
+ * timing mode	optimized
+ * address mapping : RBC
+ * Tc > + 85C : J
+ */
+#define DDR_MEM_COMPATIBLE ddr3l-dhsom-1066-888-bin-g-2x4gb-533mhz
+#define DDR_MEM_NAME "DDR3L 32bits 2x4Gb 533MHz"
+#define DDR_MEM_SPEED 533000
+#define DDR_MEM_SIZE 0x40000000
+
+#define DDR_MSTR 0x00040401
+#define DDR_MRCTRL0 0x00000010
+#define DDR_MRCTRL1 0x00000000
+#define DDR_DERATEEN 0x00000000
+#define DDR_DERATEINT 0x00800000
+#define DDR_PWRCTL 0x00000000
+#define DDR_PWRTMG 0x00400010
+#define DDR_HWLPCTL 0x00000000
+#define DDR_RFSHCTL0 0x00210000
+#define DDR_RFSHCTL3 0x00000000
+#define DDR_RFSHTMG 0x0040008B
+#define DDR_CRCPARCTL0 0x00000000
+#define DDR_DRAMTMG0 0x121B1214
+#define DDR_DRAMTMG1 0x000A041C
+#define DDR_DRAMTMG2 0x0608090F
+#define DDR_DRAMTMG3 0x0050400C
+#define DDR_DRAMTMG4 0x08040608
+#define DDR_DRAMTMG5 0x06060403
+#define DDR_DRAMTMG6 0x02020002
+#define DDR_DRAMTMG7 0x00000202
+#define DDR_DRAMTMG8 0x00001005
+#define DDR_DRAMTMG14 0x000000A0
+#define DDR_ZQCTL0 0xC2000040
+#define DDR_DFITMG0 0x02060105
+#define DDR_DFITMG1 0x00000202
+#define DDR_DFILPCFG0 0x07000000
+#define DDR_DFIUPD0 0xC0400003
+#define DDR_DFIUPD1 0x00000000
+#define DDR_DFIUPD2 0x00000000
+#define DDR_DFIPHYMSTR 0x00000000
+#define DDR_ODTCFG 0x06000600
+#define DDR_ODTMAP 0x00000001
+#define DDR_SCHED 0x00000C01
+#define DDR_SCHED1 0x00000000
+#define DDR_PERFHPR1 0x01000001
+#define DDR_PERFLPR1 0x08000200
+#define DDR_PERFWR1 0x08000400
+#define DDR_DBG0 0x00000000
+#define DDR_DBG1 0x00000000
+#define DDR_DBGCMD 0x00000000
+#define DDR_POISONCFG 0x00000000
+#define DDR_PCCFG 0x00000010
+#define DDR_PCFGR_0 0x00010000
+#define DDR_PCFGW_0 0x00000000
+#define DDR_PCFGQOS0_0 0x02100C03
+#define DDR_PCFGQOS1_0 0x00800100
+#define DDR_PCFGWQOS0_0 0x01100C03
+#define DDR_PCFGWQOS1_0 0x01000200
+#define DDR_PCFGR_1 0x00010000
+#define DDR_PCFGW_1 0x00000000
+#define DDR_PCFGQOS0_1 0x02100C03
+#define DDR_PCFGQOS1_1 0x00800040
+#define DDR_PCFGWQOS0_1 0x01100C03
+#define DDR_PCFGWQOS1_1 0x01000200
+#define DDR_ADDRMAP1 0x00080808
+#define DDR_ADDRMAP2 0x00000000
+#define DDR_ADDRMAP3 0x00000000
+#define DDR_ADDRMAP4 0x00001F1F
+#define DDR_ADDRMAP5 0x07070707
+#define DDR_ADDRMAP6 0x0F070707
+#define DDR_ADDRMAP9 0x00000000
+#define DDR_ADDRMAP10 0x00000000
+#define DDR_ADDRMAP11 0x00000000
+#define DDR_PGCR 0x01442E02
+#define DDR_PTR0 0x0022AA5B
+#define DDR_PTR1 0x04841104
+#define DDR_PTR2 0x042DA068
+#define DDR_ACIOCR 0x10400812
+#define DDR_DXCCR 0x00000C40
+#define DDR_DSGCR 0xF200011F
+#define DDR_DCR 0x0000000B
+#define DDR_DTPR0 0x38D488D0
+#define DDR_DTPR1 0x098B00D8
+#define DDR_DTPR2 0x10023600
+#define DDR_MR0 0x00000840
+#define DDR_MR1 0x00000000
+#define DDR_MR2 0x00000248
+#define DDR_MR3 0x00000000
+#define DDR_ODTCR 0x00010000
+#define DDR_ZQ0CR1 0x00000038
+#define DDR_DX0GCR 0x0000CE81
+#define DDR_DX0DLLCR 0x40000000
+#define DDR_DX0DQTR 0xFFFFFFFF
+#define DDR_DX0DQSTR 0x3DB02000
+#define DDR_DX1GCR 0x0000CE81
+#define DDR_DX1DLLCR 0x40000000
+#define DDR_DX1DQTR 0xFFFFFFFF
+#define DDR_DX1DQSTR 0x3DB02000
+#define DDR_DX2GCR 0x0000CE81
+#define DDR_DX2DLLCR 0x40000000
+#define DDR_DX2DQTR 0xFFFFFFFF
+#define DDR_DX2DQSTR 0x3DB02000
+#define DDR_DX3GCR 0x0000CE81
+#define DDR_DX3DLLCR 0x40000000
+#define DDR_DX3DQTR 0xFFFFFFFF
+#define DDR_DX3DQSTR 0x3DB02000
+
+#include "stm32mp15-ddr.dtsi"

+ 92 - 0
arch/arm/dts/stm32mp15-pinctrl.dtsi

@@ -213,6 +213,40 @@
 		};
 	};
 
+	ethernet0_rmii_pins_a: rmii-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 13, AF11)>, /* ETH1_RMII_TXD0 */
+				 <STM32_PINMUX('G', 14, AF11)>, /* ETH1_RMII_TXD1 */
+				 <STM32_PINMUX('B', 11, AF11)>, /* ETH1_RMII_TX_EN */
+				 <STM32_PINMUX('A', 1, AF0)>,   /* ETH1_RMII_REF_CLK */
+				 <STM32_PINMUX('A', 2, AF11)>,  /* ETH1_MDIO */
+				 <STM32_PINMUX('C', 1, AF11)>;  /* ETH1_MDC */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <2>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('C', 4, AF11)>,  /* ETH1_RMII_RXD0 */
+				 <STM32_PINMUX('C', 5, AF11)>,  /* ETH1_RMII_RXD1 */
+				 <STM32_PINMUX('A', 7, AF11)>;  /* ETH1_RMII_CRS_DV */
+			bias-disable;
+		};
+	};
+
+	ethernet0_rmii_pins_sleep_a: rmii-sleep-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('G', 13, ANALOG)>, /* ETH1_RMII_TXD0 */
+				 <STM32_PINMUX('G', 14, ANALOG)>, /* ETH1_RMII_TXD1 */
+				 <STM32_PINMUX('B', 11, ANALOG)>, /* ETH1_RMII_TX_EN */
+				 <STM32_PINMUX('A', 2, ANALOG)>,  /* ETH1_MDIO */
+				 <STM32_PINMUX('C', 1, ANALOG)>,  /* ETH1_MDC */
+				 <STM32_PINMUX('C', 4, ANALOG)>,  /* ETH1_RMII_RXD0 */
+				 <STM32_PINMUX('C', 5, ANALOG)>,  /* ETH1_RMII_RXD1 */
+				 <STM32_PINMUX('A', 1, ANALOG)>,  /* ETH1_RMII_REF_CLK */
+				 <STM32_PINMUX('A', 7, ANALOG)>;  /* ETH1_RMII_CRS_DV */
+		};
+	};
+
 	fmc_pins_a: fmc-0 {
 		pins1 {
 			pinmux = <STM32_PINMUX('D', 4, AF12)>, /* FMC_NOE */
@@ -736,6 +770,25 @@
 		};
 	};
 
+	sai2a_pins_b: sai2a-2 {
+		pins1 {
+			pinmux = <STM32_PINMUX('I', 6, AF10)>,	/* SAI2_SD_A */
+				 <STM32_PINMUX('I', 7, AF10)>,	/* SAI2_FS_A */
+				 <STM32_PINMUX('D', 13, AF10)>;	/* SAI2_SCK_A */
+			slew-rate = <0>;
+			drive-push-pull;
+			bias-disable;
+		};
+	};
+
+	sai2a_sleep_pins_b: sai2a-sleep-3 {
+		pins {
+			pinmux = <STM32_PINMUX('I', 6, ANALOG)>,  /* SAI2_SD_A */
+				 <STM32_PINMUX('I', 7, ANALOG)>,  /* SAI2_FS_A */
+				 <STM32_PINMUX('D', 13, ANALOG)>; /* SAI2_SCK_A */
+		};
+	};
+
 	sai2b_pins_a: sai2b-0 {
 		pins1 {
 			pinmux = <STM32_PINMUX('E', 12, AF10)>, /* SAI2_SCK_B */
@@ -1118,6 +1171,19 @@
 		};
 	};
 
+	usart3_pins_a: usart3-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('B', 10, AF7)>; /* USART3_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('B', 12, AF8)>; /* USART3_RX */
+			bias-disable;
+		};
+	};
+
 	uart4_pins_a: uart4-0 {
 		pins1 {
 			pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
@@ -1158,6 +1224,32 @@
 			bias-disable;
 		};
 	};
+
+	uart8_pins_a: uart8-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('E', 1, AF8)>; /* UART8_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('E', 0, AF8)>; /* UART8_RX */
+			bias-disable;
+		};
+	};
+
+	usbotg_hs_pins_a: usbotg-hs-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 10, ANALOG)>; /* OTG_ID */
+		};
+	};
+
+	usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 11, ANALOG)>, /* OTG_FS_DM */
+				 <STM32_PINMUX('A', 12, ANALOG)>; /* OTG_FS_DP */
+		};
+	};
 };
 
 &pinctrl_z {

+ 25 - 0
arch/arm/dts/stm32mp15-u-boot.dtsi

@@ -36,6 +36,31 @@
 
 	soc {
 		u-boot,dm-pre-reloc;
+
+		ddr: ddr@5a003000 {
+			u-boot,dm-pre-reloc;
+
+			compatible = "st,stm32mp1-ddr";
+
+			reg = <0x5A003000 0x550
+			       0x5A004000 0x234>;
+
+			clocks = <&rcc AXIDCG>,
+				 <&rcc DDRC1>,
+				 <&rcc DDRC2>,
+				 <&rcc DDRPHYC>,
+				 <&rcc DDRCAPB>,
+				 <&rcc DDRPHYCAPB>;
+
+			clock-names = "axidcg",
+				      "ddrc1",
+				      "ddrc2",
+				      "ddrphyc",
+				      "ddrcapb",
+				      "ddrphycapb";
+
+			status = "okay";
+		};
 	};
 };
 

+ 12 - 1
arch/arm/dts/stm32mp151.dtsi

@@ -17,6 +17,7 @@
 
 		cpu0: cpu@0 {
 			compatible = "arm,cortex-a7";
+			clock-frequency = <650000000>;
 			device_type = "cpu";
 			reg = <0>;
 		};
@@ -490,6 +491,7 @@
 			resets = <&rcc I2C1_R>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			wakeup-source;
 			status = "disabled";
 		};
 
@@ -503,6 +505,7 @@
 			resets = <&rcc I2C2_R>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			wakeup-source;
 			status = "disabled";
 		};
 
@@ -516,6 +519,7 @@
 			resets = <&rcc I2C3_R>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			wakeup-source;
 			status = "disabled";
 		};
 
@@ -529,6 +533,7 @@
 			resets = <&rcc I2C5_R>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			wakeup-source;
 			status = "disabled";
 		};
 
@@ -966,6 +971,7 @@
 				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&rcc DMA1>;
+			resets = <&rcc DMA1_R>;
 			#dma-cells = <4>;
 			st,mem2mem;
 			dma-requests = <8>;
@@ -983,6 +989,7 @@
 				     <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&rcc DMA2>;
+			resets = <&rcc DMA2_R>;
 			#dma-cells = <4>;
 			st,mem2mem;
 			dma-requests = <8>;
@@ -996,6 +1003,7 @@
 			dma-masters = <&dma1 &dma2>;
 			dma-channels = <16>;
 			clocks = <&rcc DMAMUX>;
+			resets = <&rcc DMAMUX_R>;
 		};
 
 		adc: adc@48003000 {
@@ -1051,7 +1059,7 @@
 		};
 
 		usbotg_hs: usb-otg@49000000 {
-			compatible = "snps,dwc2";
+			compatible = "st,stm32mp15-hsotg", "snps,dwc2";
 			reg = <0x49000000 0x10000>;
 			clocks = <&rcc USBO_K>;
 			clock-names = "otg";
@@ -1296,6 +1304,7 @@
 			reg = <0x58000000 0x1000>;
 			interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&rcc MDMA>;
+			resets = <&rcc MDMA_R>;
 			#dma-cells = <5>;
 			dma-channels = <32>;
 			dma-requests = <48>;
@@ -1495,6 +1504,7 @@
 			resets = <&rcc I2C4_R>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			wakeup-source;
 			status = "disabled";
 		};
 
@@ -1530,6 +1540,7 @@
 			resets = <&rcc I2C6_R>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			wakeup-source;
 			status = "disabled";
 		};
 

+ 1 - 0
arch/arm/dts/stm32mp153.dtsi

@@ -10,6 +10,7 @@
 	cpus {
 		cpu1: cpu@1 {
 			compatible = "arm,cortex-a7";
+			clock-frequency = <650000000>;
 			device_type = "cpu";
 			reg = <1>;
 		};

+ 0 - 4
arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi

@@ -27,10 +27,6 @@
 			default-state = "off";
 			status = "okay";
 		};
-
-		blue {
-			default-state = "on";
-		};
 	};
 };
 

+ 0 - 4
arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi

@@ -28,10 +28,6 @@
 			default-state = "off";
 			status = "okay";
 		};
-
-		blue {
-			default-state = "on";
-		};
 	};
 };
 

+ 11 - 6
arch/arm/dts/stm32mp157c-ed1.dts

@@ -70,6 +70,11 @@
 			reg = <0xe8000000 0x8000000>;
 			no-map;
 		};
+
+		optee@fe000000 {
+			reg = <0xfe000000 0x02000000>;
+			no-map;
+		};
 	};
 
 	aliases {
@@ -130,10 +135,12 @@
 };
 
 &i2c4 {
-	pinctrl-names = "default";
+	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&i2c4_pins_a>;
+	pinctrl-1 = <&i2c4_pins_sleep_a>;
 	i2c-scl-rising-time-ns = <185>;
 	i2c-scl-falling-time-ns = <20>;
+	clock-frequency = <400000>;
 	status = "okay";
 	/* spare dmas for other usage */
 	/delete-property/dmas;
@@ -218,8 +225,6 @@
 
 			vdd_usb: ldo4 {
 				regulator-name = "vdd_usb";
-				regulator-min-microvolt = <3300000>;
-				regulator-max-microvolt = <3300000>;
 				interrupts = <IT_CURLIM_LDO4 0>;
 			};
 
@@ -241,7 +246,6 @@
 			vref_ddr: vref_ddr {
 				regulator-name = "vref_ddr";
 				regulator-always-on;
-				regulator-over-current-protection;
 			};
 
 			bst_out: boost {
@@ -313,7 +317,8 @@
 	pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
 	pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>;
 	pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>;
-	broken-cd;
+	cd-gpios = <&gpiog 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+	disable-wp;
 	st,sig-dir;
 	st,neg-edge;
 	st,use-ckin;
@@ -334,7 +339,7 @@
 	st,neg-edge;
 	bus-width = <8>;
 	vmmc-supply = <&v3v3>;
-	vqmmc-supply = <&v3v3>;
+	vqmmc-supply = <&vdd>;
 	mmc-ddr-3_3v;
 	status = "okay";
 };

+ 8 - 5
arch/arm/dts/stm32mp157c-ev1.dts

@@ -174,8 +174,9 @@
 };
 
 &i2c2 {
-	pinctrl-names = "default";
+	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&i2c2_pins_a>;
+	pinctrl-1 = <&i2c2_pins_sleep_a>;
 	i2c-scl-rising-time-ns = <185>;
 	i2c-scl-falling-time-ns = <20>;
 	status = "okay";
@@ -210,7 +211,7 @@
 		interrupt-parent = <&gpioi>;
 		vdd-supply = <&v3v3>;
 
-		stmfx_pinctrl: stmfx-pin-controller {
+		stmfx_pinctrl: pinctrl {
 			compatible = "st,stmfx-0300-pinctrl";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -218,7 +219,7 @@
 			#interrupt-cells = <2>;
 			gpio-ranges = <&stmfx_pinctrl 0 0 24>;
 
-			joystick_pins: joystick {
+			joystick_pins: joystick-pins {
 				pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4";
 				bias-pull-down;
 			};
@@ -227,8 +228,9 @@
 };
 
 &i2c5 {
-	pinctrl-names = "default";
+	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&i2c5_pins_a>;
+	pinctrl-1 = <&i2c5_pins_sleep_a>;
 	i2c-scl-rising-time-ns = <185>;
 	i2c-scl-falling-time-ns = <20>;
 	status = "okay";
@@ -353,7 +355,8 @@
 };
 
 &usbotg_hs {
-	dr_mode = "peripheral";
+	pinctrl-0 = <&usbotg_hs_pins_a>;
+	pinctrl-names = "default";
 	phys = <&usbphyc_port1 0>;
 	phy-names = "usb2-phy";
 	status = "okay";

+ 14 - 1
arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi

@@ -5,7 +5,9 @@
 
 #include <dt-bindings/clock/stm32mp1-clksrc.h>
 #include "stm32mp15-u-boot.dtsi"
-#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi"
+#include "stm32mp15-ddr3-dhsom-2x1Gb-1066-binG.dtsi"
+#include "stm32mp15-ddr3-dhsom-2x2Gb-1066-binG.dtsi"
+#include "stm32mp15-ddr3-dhsom-2x4Gb-1066-binG.dtsi"
 
 / {
 	aliases {
@@ -23,6 +25,8 @@
 		u-boot,error-led = "error";
 		st,fastboot-gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
 		st,stm32prog-gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
+		dh,som-coding-gpios = <&gpiof 12 0>, <&gpiof 13 0>, <&gpiof 15 0>;
+		dh,ddr3-coding-gpios = <&gpioz 6 0>, <&gpioz 7 0>;
 	};
 
 	led {
@@ -45,6 +49,15 @@
 	};
 };
 
+&gpiof {
+	snor-nwp {
+		gpio-hog;
+		gpios = <7 0>;
+		output-high;
+		line-name = "spi-nor-nwp";
+	};
+};
+
 &i2c4 {
 	u-boot,dm-pre-reloc;
 };

+ 2 - 1
arch/arm/dts/stm32mp15xx-dhcom.dtsi

@@ -269,7 +269,8 @@
 	pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
 	pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>;
 	pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>;
-	broken-cd;
+	cd-gpios = <&gpioi 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+	disable-wp;
 	st,sig-dir;
 	st,neg-edge;
 	st,use-ckin;

+ 1 - 0
arch/arm/dts/stm32mp15xx-dhcor-avenger96-u-boot.dtsi

@@ -15,6 +15,7 @@
 	config {
 		u-boot,boot-led = "led1";
 		u-boot,error-led = "led4";
+		dh,board-coding-gpios = <&gpiog 13 0>, <&gpiod 9 0>;
 	};
 };
 

+ 1 - 1
arch/arm/dts/stm32mp15xx-dhcor-avenger96.dts

@@ -7,7 +7,7 @@
 
 /dts-v1/;
 
-#include "stm32mp15xx-dhcor.dtsi"
+#include "stm32mp15xx-dhcor-io1v8.dtsi"
 #include "stm32mp15xx-dhcor-avenger96-u-boot.dtsi"
 
 / {

+ 24 - 0
arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi

@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Copyright (C) 2020 Marek Vasut <marex@denx.de>
+ */
+
+#include "stm32mp15xx-dhcor-io3v3.dtsi"
+
+/ {
+	/* Enpirion EP3A8LQI U2 on the 1V8 IO DHCOR */
+	vdd_io: regulator-buck-io {
+		compatible = "regulator-fixed";
+		regulator-name = "buck-io";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vdd>;
+	};
+};
+
+&pwr_regulators {
+	vdd-supply = <&vdd_io>;
+	vdd_3v3_usbfs-supply = <&vdd_usb>;
+};

+ 1 - 20
arch/arm/dts/stm32mp15xx-dhcor.dtsi → arch/arm/dts/stm32mp15xx-dhcor-io3v3.dtsi

@@ -21,17 +21,6 @@
 		device_type = "memory";
 		reg = <0xc0000000 0x40000000>;
 	};
-
-	/* Enpirion EP3A8LQI U2 on the DHCOR */
-	vdd_io: regulator-buck-io {
-		compatible = "regulator-fixed";
-		regulator-name = "buck-io";
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-		regulator-always-on;
-		regulator-boot-on;
-		vin-supply = <&vdd>;
-	};
 };
 
 &i2c4 {
@@ -51,10 +40,6 @@
 		#interrupt-cells = <2>;
 		status = "okay";
 
-		st,main-control-register = <0x04>;
-		st,vin-control-register = <0xc0>;
-		st,usb-control-register = <0x30>;
-
 		regulators {
 			compatible = "st,stpmic1-regulators";
 
@@ -89,7 +74,6 @@
 				regulator-min-microvolt = <2900000>;
 				regulator-max-microvolt = <2900000>;
 				regulator-always-on;
-				st,mask_reset;
 				regulator-initial-mode = <0>;
 				regulator-over-current-protection;
 			};
@@ -129,8 +113,6 @@
 
 			vdd_usb: ldo4 {
 				regulator-name = "vdd_usb";
-				regulator-min-microvolt = <3300000>;
-				regulator-max-microvolt = <3300000>;
 				interrupts = <IT_CURLIM_LDO4 0>;
 				interrupt-parent = <&pmic>;
 			};
@@ -156,7 +138,6 @@
 			vref_ddr: vref_ddr {
 				regulator-name = "vref_ddr";
 				regulator-always-on;
-				regulator-over-current-protection;
 			};
 
 			bst_out: boost {
@@ -200,7 +181,7 @@
 };
 
 &pwr_regulators {
-	vdd-supply = <&vdd_io>;
+	vdd-supply = <&vdd>;
 	vdd_3v3_usbfs-supply = <&vdd_usb>;
 };
 

+ 11 - 1
arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi

@@ -9,7 +9,17 @@
 
 #include <dt-bindings/clock/stm32mp1-clksrc.h>
 #include "stm32mp15-u-boot.dtsi"
-#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi"
+#include "stm32mp15-ddr3-dhsom-2x1Gb-1066-binG.dtsi"
+#include "stm32mp15-ddr3-dhsom-2x2Gb-1066-binG.dtsi"
+#include "stm32mp15-ddr3-dhsom-2x4Gb-1066-binG.dtsi"
+
+/ {
+	u-boot,dm-pre-reloc;
+	config {
+		dh,ddr3-coding-gpios = <&gpiog 0 0>, <&gpiog 1 0>;
+		dh,som-coding-gpios = <&gpioz 7 0>, <&gpiof 3 0>;
+	};
+};
 
 &i2c4 {
 	u-boot,dm-pre-reloc;

+ 10 - 5
arch/arm/dts/stm32mp15xx-dkx.dtsi

@@ -58,6 +58,11 @@
 			reg = <0xd4000000 0x4000000>;
 			no-map;
 		};
+
+		optee@de000000 {
+			reg = <0xde000000 0x02000000>;
+			no-map;
+		};
 	};
 
 	led {
@@ -216,10 +221,12 @@
 };
 
 &i2c4 {
-	pinctrl-names = "default";
+	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&i2c4_pins_a>;
+	pinctrl-1 = <&i2c4_pins_sleep_a>;
 	i2c-scl-rising-time-ns = <185>;
 	i2c-scl-falling-time-ns = <20>;
+	clock-frequency = <400000>;
 	status = "okay";
 	/* spare dmas for other usage */
 	/delete-property/dmas;
@@ -322,8 +329,6 @@
 
 			vdd_usb: ldo4 {
 				regulator-name = "vdd_usb";
-				regulator-min-microvolt = <3300000>;
-				regulator-max-microvolt = <3300000>;
 				interrupts = <IT_CURLIM_LDO4 0>;
 			};
 
@@ -346,7 +351,6 @@
 			vref_ddr: vref_ddr {
 				regulator-name = "vref_ddr";
 				regulator-always-on;
-				regulator-over-current-protection;
 			};
 
 			 bst_out: boost {
@@ -497,7 +501,8 @@
 	pinctrl-0 = <&sdmmc1_b4_pins_a>;
 	pinctrl-1 = <&sdmmc1_b4_od_pins_a>;
 	pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
-	broken-cd;
+	cd-gpios = <&gpiob 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+	disable-wp;
 	st,neg-edge;
 	bus-width = <4>;
 	vmmc-supply = <&v3v3>;

+ 17 - 12
arch/arm/mach-stm32mp/Kconfig

@@ -86,16 +86,6 @@ config TARGET_DH_STM32MP1_PDK2
 
 endchoice
 
-config STM32MP1_OPTEE
-	bool "Support trusted boot with TF-A and OP-TEE"
-	depends on TFABOOT
-	default n
-	help
-		Say Y here to enable boot with TF-A and OP-TEE
-		Trusted boot chain is :
-		BootRom => TF-A.stm32 (clock & DDR) => OP-TEE => U-Boot.stm32
-		OP-TEE monitor provides ST SMC to access to secure resources
-
 config SYS_TEXT_BASE
 	default 0xC0100000
 
@@ -117,15 +107,30 @@ config STM32_ETZPC
 	help
 	  Say y to enable STM32 Extended TrustZone Protection
 
+config CMD_STM32PROG
+	bool "command stm32prog for STM32CudeProgrammer"
+	select DFU
+	select DFU_RAM
+	select DFU_VIRT
+	select PARTITION_TYPE_GUID
+	imply CMD_GPT if MMC
+	imply CMD_MTD if MTD
+	imply DFU_MMC if MMC
+	imply DFU_MTD if MTD
+	help
+		activate a specific command stm32prog for STM32MP soc family
+		witch update the device with the tools STM32CubeProgrammer,
+		using UART with STM32 protocol or USB with DFU protocol
+		NB: access to not volatile memory (NOR/NAND/SD/eMMC) is based
+		    on U-Boot DFU framework
+
 config CMD_STM32KEY
 	bool "command stm32key to fuse public key hash"
 	default y
-	depends on CMD_FUSE
 	help
 		fuse public key hash in corresponding fuse used to authenticate
 		binary.
 
-
 config PRE_CON_BUF_ADDR
 	default 0xC02FF000
 

+ 2 - 0
arch/arm/mach-stm32mp/Makefile

@@ -10,9 +10,11 @@ obj-y += syscon.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
 endif
 
 obj-$(CONFIG_$(SPL_)DM_REGULATOR) += pwr_regulator.o

+ 45 - 0
arch/arm/mach-stm32mp/boot_params.c

@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <asm/sections.h>
+#include <asm/system.h>
+
+/*
+ * Force data-section, as .bss will not be valid
+ * when save_boot_params is invoked.
+ */
+static unsigned long nt_fw_dtb __section(".data");
+
+/*
+ * Save the FDT address provided by TF-A in r2 at boot time
+ * This function is called from start.S
+ */
+void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2,
+		      unsigned long r3)
+{
+	nt_fw_dtb = r2;
+
+	save_boot_params_ret();
+}
+
+/*
+ * Use the saved FDT address provided by TF-A at boot time (NT_FW_CONFIG =
+ * Non Trusted Firmware configuration file) when the pointer is valid
+ */
+void *board_fdt_blob_setup(void)
+{
+	debug("%s: nt_fw_dtb=%lx\n", __func__, nt_fw_dtb);
+
+	/* use external device tree only if address is valid */
+	if (nt_fw_dtb >= STM32_DDR_BASE) {
+		if (fdt_magic(nt_fw_dtb) == FDT_MAGIC)
+			return (void *)nt_fw_dtb;
+		debug("%s: DTB not found.\n", __func__);
+	}
+	debug("%s: fall back to builtin DTB, %p\n", __func__, &_end);
+
+	return (void *)&_end;
+}

+ 9 - 0
arch/arm/mach-stm32mp/cmd_stm32prog/Makefile

@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+#
+
+obj-y += cmd_stm32prog.o
+obj-y += stm32prog.o
+obj-y += stm32prog_serial.o
+obj-y += stm32prog_usb.o

+ 192 - 0
arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c

@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dfu.h>
+#include <image.h>
+#include <asm/arch/stm32prog.h>
+#include "stm32prog.h"
+
+struct stm32prog_data *stm32prog_data;
+
+static void enable_vidconsole(void)
+{
+#ifdef CONFIG_DM_VIDEO
+	char *stdname;
+	char buf[64];
+
+	stdname = env_get("stdout");
+	if (!stdname || !strstr(stdname, "vidconsole")) {
+		if (!stdname)
+			snprintf(buf, sizeof(buf), "serial,vidconsole");
+		else
+			snprintf(buf, sizeof(buf), "%s,vidconsole", stdname);
+		env_set("stdout", buf);
+	}
+
+	stdname = env_get("stderr");
+	if (!stdname || !strstr(stdname, "vidconsole")) {
+		if (!stdname)
+			snprintf(buf, sizeof(buf), "serial,vidconsole");
+		else
+			snprintf(buf, sizeof(buf), "%s,vidconsole", stdname);
+		env_set("stderr", buf);
+	}
+#endif
+}
+
+static int do_stm32prog(cmd_tbl_t *cmdtp, int flag, int argc,
+			char * const argv[])
+{
+	ulong	addr, size;
+	int dev, ret;
+	enum stm32prog_link_t link = LINK_UNDEFINED;
+	bool reset = false;
+	struct image_header_s header;
+	struct stm32prog_data *data;
+	u32 uimage, dtb;
+
+	if (argc < 3 ||  argc > 5)
+		return CMD_RET_USAGE;
+
+	if (!strcmp(argv[1], "usb"))
+		link = LINK_USB;
+	else if (!strcmp(argv[1], "serial"))
+		link = LINK_SERIAL;
+
+	if (link == LINK_UNDEFINED) {
+		pr_err("not supported link=%s\n", argv[1]);
+		return CMD_RET_USAGE;
+	}
+
+	dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+	addr = STM32_DDR_BASE;
+	size = 0;
+	if (argc > 3) {
+		addr = simple_strtoul(argv[3], NULL, 16);
+		if (!addr)
+			return CMD_RET_FAILURE;
+	}
+	if (argc > 4)
+		size = simple_strtoul(argv[4], NULL, 16);
+
+	/* check STM32IMAGE presence */
+	if (size == 0 &&
+	    !stm32prog_header_check((struct raw_header_s *)addr, &header)) {
+		size = header.image_length + BL_HEADER_SIZE;
+
+		/* uImage detected in STM32IMAGE, execute the script */
+		if (IMAGE_FORMAT_LEGACY ==
+		    genimg_get_format((void *)(addr + BL_HEADER_SIZE)))
+			return image_source_script(addr + BL_HEADER_SIZE,
+						   "script@1");
+	}
+
+	enable_vidconsole();
+
+	data = (struct stm32prog_data *)malloc(sizeof(*data));
+
+	if (!data) {
+		pr_err("Alloc failed.");
+		return CMD_RET_FAILURE;
+	}
+	stm32prog_data = data;
+
+	ret = stm32prog_init(data, addr, size);
+	if (ret)
+		printf("Invalid or missing layout file.");
+
+	/* prepare DFU for device read/write */
+	ret = stm32prog_dfu_init(data);
+	if (ret)
+		goto cleanup;
+
+	switch (link) {
+	case LINK_SERIAL:
+		ret = stm32prog_serial_init(data, dev);
+		if (ret)
+			goto cleanup;
+		reset = stm32prog_serial_loop(data);
+		break;
+	case LINK_USB:
+		reset = stm32prog_usb_loop(data, dev);
+		break;
+	default:
+		goto cleanup;
+	}
+
+	uimage = data->uimage;
+	dtb = data->dtb;
+
+	stm32prog_clean(data);
+	free(stm32prog_data);
+	stm32prog_data = NULL;
+
+	puts("Download done\n");
+
+	if (uimage) {
+		char boot_addr_start[20];
+		char dtb_addr[20];
+		char *bootm_argv[5] = {
+			"bootm", boot_addr_start, "-", dtb_addr, NULL
+		};
+		if (!dtb)
+			bootm_argv[3] = env_get("fdtcontroladdr");
+		else
+			snprintf(dtb_addr, sizeof(dtb_addr) - 1,
+				 "0x%x", dtb);
+
+		snprintf(boot_addr_start, sizeof(boot_addr_start) - 1,
+			 "0x%x", uimage);
+		printf("Booting kernel at %s - %s...\n\n\n",
+		       boot_addr_start, bootm_argv[3]);
+		/* Try bootm for legacy and FIT format image */
+		if (genimg_get_format((void *)uimage) != IMAGE_FORMAT_INVALID)
+			do_bootm(cmdtp, 0, 4, bootm_argv);
+		else if CONFIG_IS_ENABLED(CMD_BOOTZ)
+			do_bootz(cmdtp, 0, 4, bootm_argv);
+	}
+
+	if (reset) {
+		puts("Reset...\n");
+		run_command("reset", 0);
+	}
+
+	return CMD_RET_SUCCESS;
+
+cleanup:
+	stm32prog_clean(data);
+	free(stm32prog_data);
+	stm32prog_data = NULL;
+
+	return CMD_RET_FAILURE;
+}
+
+U_BOOT_CMD(stm32prog, 5, 0, do_stm32prog,
+	   "<link> <dev> [<addr>] [<size>]\n"
+	   "start communication with tools STM32Cubeprogrammer on <link> with Flashlayout at <addr>",
+	   "<link> = serial|usb\n"
+	   "<dev>  = device instance\n"
+	   "<addr> = address of flashlayout\n"
+	   "<size> = size of flashlayout\n"
+);
+
+bool stm32prog_get_tee_partitions(void)
+{
+	if (stm32prog_data)
+		return stm32prog_data->tee_detected;
+
+	return false;
+}
+
+bool stm32prog_get_fsbl_nor(void)
+{
+	if (stm32prog_data)
+		return stm32prog_data->fsbl_nor_detected;
+
+	return false;
+}

+ 1745 - 0
arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c

@@ -0,0 +1,1745 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dfu.h>
+#include <malloc.h>
+#include <misc.h>
+#include <mmc.h>
+#include <part.h>
+#include <asm/arch/stm32mp1_smc.h>
+#include <dm/uclass.h>
+#include <jffs2/load_kernel.h>
+#include <linux/list.h>
+#include <linux/list_sort.h>
+#include <linux/mtd/mtd.h>
+#include <linux/sizes.h>
+
+#include "stm32prog.h"
+
+/* Primary GPT header size for 128 entries : 17kB = 34 LBA of 512B */
+#define GPT_HEADER_SZ	34
+
+#define OPT_SELECT	BIT(0)
+#define OPT_EMPTY	BIT(1)
+#define OPT_DELETE	BIT(2)
+
+#define IS_SELECT(part)	((part)->option & OPT_SELECT)
+#define IS_EMPTY(part)	((part)->option & OPT_EMPTY)
+#define IS_DELETE(part)	((part)->option & OPT_DELETE)
+
+#define ALT_BUF_LEN			SZ_1K
+
+#define ROOTFS_MMC0_UUID \
+	EFI_GUID(0xE91C4E10, 0x16E6, 0x4C0E, \
+		 0xBD, 0x0E, 0x77, 0xBE, 0xCF, 0x4A, 0x35, 0x82)
+
+#define ROOTFS_MMC1_UUID \
+	EFI_GUID(0x491F6117, 0x415D, 0x4F53, \
+		 0x88, 0xC9, 0x6E, 0x0D, 0xE5, 0x4D, 0xEA, 0xC6)
+
+#define ROOTFS_MMC2_UUID \
+	EFI_GUID(0xFD58F1C7, 0xBE0D, 0x4338, \
+		 0x88, 0xE9, 0xAD, 0x8F, 0x05, 0x0A, 0xEB, 0x18)
+
+/* RAW parttion (binary / bootloader) used Linux - reserved UUID */
+#define LINUX_RESERVED_UUID "8DA63339-0007-60C0-C436-083AC8230908"
+
+/*
+ * unique partition guid (uuid) for partition named "rootfs"
+ * on each MMC instance = SD Card or eMMC
+ * allow fixed kernel bootcmd: "rootf=PARTUID=e91c4e10-..."
+ */
+static const efi_guid_t uuid_mmc[3] = {
+	ROOTFS_MMC0_UUID,
+	ROOTFS_MMC1_UUID,
+	ROOTFS_MMC2_UUID
+};
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* order of column in flash layout file */
+enum stm32prog_col_t {
+	COL_OPTION,
+	COL_ID,
+	COL_NAME,
+	COL_TYPE,
+	COL_IP,
+	COL_OFFSET,
+	COL_NB_STM32
+};
+
+/* partition handling routines : CONFIG_CMD_MTDPARTS */
+int mtdparts_init(void);
+int find_dev_and_part(const char *id, struct mtd_device **dev,
+		      u8 *part_num, struct part_info **part);
+
+char *stm32prog_get_error(struct stm32prog_data *data)
+{
+	static const char error_msg[] = "Unspecified";
+
+	if (strlen(data->error) == 0)
+		strcpy(data->error, error_msg);
+
+	return data->error;
+}
+
+u8 stm32prog_header_check(struct raw_header_s *raw_header,
+			  struct image_header_s *header)
+{
+	unsigned int i;
+
+	header->present = 0;
+	header->image_checksum = 0x0;
+	header->image_length = 0x0;
+
+	if (!raw_header || !header) {
+		pr_debug("%s:no header data\n", __func__);
+		return -1;
+	}
+	if (raw_header->magic_number !=
+		(('S' << 0) | ('T' << 8) | ('M' << 16) | (0x32 << 24))) {
+		pr_debug("%s:invalid magic number : 0x%x\n",
+			 __func__, raw_header->magic_number);
+		return -2;
+	}
+	/* only header v1.0 supported */
+	if (raw_header->header_version != 0x00010000) {
+		pr_debug("%s:invalid header version : 0x%x\n",
+			 __func__, raw_header->header_version);
+		return -3;
+	}
+	if (raw_header->reserved1 != 0x0 || raw_header->reserved2) {
+		pr_debug("%s:invalid reserved field\n", __func__);
+		return -4;
+	}
+	for (i = 0; i < (sizeof(raw_header->padding) / 4); i++) {
+		if (raw_header->padding[i] != 0) {
+			pr_debug("%s:invalid padding field\n", __func__);
+			return -5;
+		}
+	}
+	header->present = 1;
+	header->image_checksum = le32_to_cpu(raw_header->image_checksum);
+	header->image_length = le32_to_cpu(raw_header->image_length);
+
+	return 0;
+}
+
+static u32 stm32prog_header_checksum(u32 addr, struct image_header_s *header)
+{
+	u32 i, checksum;
+	u8 *payload;
+
+	/* compute checksum on payload */
+	payload = (u8 *)addr;
+	checksum = 0;
+	for (i = header->image_length; i > 0; i--)
+		checksum += *(payload++);
+
+	return checksum;
+}
+
+/* FLASHLAYOUT PARSING *****************************************/
+static int parse_option(struct stm32prog_data *data,
+			int i, char *p, struct stm32prog_part_t *part)
+{
+	int result = 0;
+	char *c = p;
+
+	part->option = 0;
+	if (!strcmp(p, "-"))
+		return 0;
+
+	while (*c) {
+		switch (*c) {
+		case 'P':
+			part->option |= OPT_SELECT;
+			break;
+		case 'E':
+			part->option |= OPT_EMPTY;
+			break;
+		case 'D':
+			part->option |= OPT_DELETE;
+			break;
+		default:
+			result = -EINVAL;
+			stm32prog_err("Layout line %d: invalid option '%c' in %s)",
+				      i, *c, p);
+			return -EINVAL;
+		}
+		c++;
+	}
+	if (!(part->option & OPT_SELECT)) {
+		stm32prog_err("Layout line %d: missing 'P' in option %s", i, p);
+		return -EINVAL;
+	}
+
+	return result;
+}
+
+static int parse_id(struct stm32prog_data *data,
+		    int i, char *p, struct stm32prog_part_t *part)
+{
+	int result = 0;
+	unsigned long value;
+
+	result = strict_strtoul(p, 0, &value);
+	part->id = value;
+	if (result || value > PHASE_LAST_USER) {
+		stm32prog_err("Layout line %d: invalid phase value = %s", i, p);
+		result = -EINVAL;
+	}
+
+	return result;
+}
+
+static int parse_name(struct stm32prog_data *data,
+		      int i, char *p, struct stm32prog_part_t *part)
+{
+	int result = 0;
+
+	if (strlen(p) < sizeof(part->name)) {
+		strcpy(part->name, p);
+	} else {
+		stm32prog_err("Layout line %d: partition name too long [%d]: %s",
+			      i, strlen(p), p);
+		result = -EINVAL;
+	}
+
+	return result;
+}
+
+static int parse_type(struct stm32prog_data *data,
+		      int i, char *p, struct stm32prog_part_t *part)
+{
+	int result = 0;
+	int len = 0;
+
+	part->bin_nb = 0;
+	if (!strncmp(p, "Binary", 6)) {
+		part->part_type = PART_BINARY;
+
+		/* search for Binary(X) case */
+		len = strlen(p);
+		part->bin_nb = 1;
+		if (len > 6) {
+			if (len < 8 ||
+			    (p[6] != '(') ||
+			    (p[len - 1] != ')'))
+				result = -EINVAL;
+			else
+				part->bin_nb =
+					simple_strtoul(&p[7], NULL, 10);
+		}
+	} else if (!strcmp(p, "System")) {
+		part->part_type = PART_SYSTEM;
+	} else if (!strcmp(p, "FileSystem")) {
+		part->part_type = PART_FILESYSTEM;
+	} else if (!strcmp(p, "RawImage")) {
+		part->part_type = RAW_IMAGE;
+	} else {
+		result = -EINVAL;
+	}
+	if (result)
+		stm32prog_err("Layout line %d: type parsing error : '%s'",
+			      i, p);
+
+	return result;
+}
+
+static int parse_ip(struct stm32prog_data *data,
+		    int i, char *p, struct stm32prog_part_t *part)
+{
+	int result = 0;
+	unsigned int len = 0;
+
+	part->dev_id = 0;
+	if (!strcmp(p, "none")) {
+		part->target = STM32PROG_NONE;
+	} else if (!strncmp(p, "mmc", 3)) {
+		part->target = STM32PROG_MMC;
+		len = 3;
+	} else if (!strncmp(p, "nor", 3)) {
+		part->target = STM32PROG_NOR;
+		len = 3;
+	} else if (!strncmp(p, "nand", 4)) {
+		part->target = STM32PROG_NAND;
+		len = 4;
+	} else if (!strncmp(p, "spi-nand", 8)) {
+		part->target = STM32PROG_SPI_NAND;
+		len = 8;
+	} else if (!strncmp(p, "ram", 3)) {
+		part->target = STM32PROG_RAM;
+		len = 0;
+	} else {
+		result = -EINVAL;
+	}
+	if (len) {
+		/* only one digit allowed for device id */
+		if (strlen(p) != len + 1) {
+			result = -EINVAL;
+		} else {
+			part->dev_id = p[len] - '0';
+			if (part->dev_id > 9)
+				result = -EINVAL;
+		}
+	}
+	if (result)
+		stm32prog_err("Layout line %d: ip parsing error: '%s'", i, p);
+
+	return result;
+}
+
+static int parse_offset(struct stm32prog_data *data,
+			int i, char *p, struct stm32prog_part_t *part)
+{
+	int result = 0;
+	char *tail;
+
+	part->part_id = 0;
+	part->addr = 0;
+	part->size = 0;
+	/* eMMC boot parttion */
+	if (!strncmp(p, "boot", 4)) {
+		if (strlen(p) != 5) {
+			result = -EINVAL;
+		} else {
+			if (p[4] == '1')
+				part->part_id = -1;
+			else if (p[4] == '2')
+				part->part_id = -2;
+			else
+				result = -EINVAL;
+		}
+		if (result)
+			stm32prog_err("Layout line %d: invalid part '%s'",
+				      i, p);
+	} else {
+		part->addr = simple_strtoull(p, &tail, 0);
+		if (tail == p || *tail != '\0') {
+			stm32prog_err("Layout line %d: invalid offset '%s'",
+				      i, p);
+			result = -EINVAL;
+		}
+	}
+
+	return result;
+}
+
+static
+int (* const parse[COL_NB_STM32])(struct stm32prog_data *data, int i, char *p,
+				  struct stm32prog_part_t *part) = {
+	[COL_OPTION] = parse_option,
+	[COL_ID] = parse_id,
+	[COL_NAME] =  parse_name,
+	[COL_TYPE] = parse_type,
+	[COL_IP] = parse_ip,
+	[COL_OFFSET] = parse_offset,
+};
+
+static int parse_flash_layout(struct stm32prog_data *data,
+			      ulong addr,
+			      ulong size)
+{
+	int column = 0, part_nb = 0, ret;
+	bool end_of_line, eof;
+	char *p, *start, *last, *col;
+	struct stm32prog_part_t *part;
+	int part_list_size;
+	int i;
+
+	data->part_nb = 0;
+
+	/* check if STM32image is detected */
+	if (!stm32prog_header_check((struct raw_header_s *)addr,
+				    &data->header)) {
+		u32 checksum;
+
+		addr = addr + BL_HEADER_SIZE;
+		size = data->header.image_length;
+
+		checksum = stm32prog_header_checksum(addr, &data->header);
+		if (checksum != data->header.image_checksum) {
+			stm32prog_err("Layout: invalid checksum : 0x%x expected 0x%x",
+				      checksum, data->header.image_checksum);
+			return -EIO;
+		}
+	}
+	if (!size)
+		return -EINVAL;
+
+	start = (char *)addr;
+	last = start + size;
+
+	*last = 0x0; /* force null terminated string */
+	pr_debug("flash layout =\n%s\n", start);
+
+	/* calculate expected number of partitions */
+	part_list_size = 1;
+	p = start;
+	while (*p && (p < last)) {
+		if (*p++ == '\n') {
+			part_list_size++;
+			if (p < last && *p == '#')
+				part_list_size--;
+		}
+	}
+	if (part_list_size > PHASE_LAST_USER) {
+		stm32prog_err("Layout: too many partition (%d)",
+			      part_list_size);
+		return -1;
+	}
+	part = calloc(sizeof(struct stm32prog_part_t), part_list_size);
+	if (!part) {
+		stm32prog_err("Layout: alloc failed");
+		return -ENOMEM;
+	}
+	data->part_array = part;
+
+	/* main parsing loop */
+	i = 1;
+	eof = false;
+	p = start;
+	col = start; /* 1st column */
+	end_of_line = false;
+	while (!eof) {
+		switch (*p) {
+		/* CR is ignored and replaced by NULL character */
+		case '\r':
+			*p = '\0';
+			p++;
+			continue;
+		case '\0':
+			end_of_line = true;
+			eof = true;
+			break;
+		case '\n':
+			end_of_line = true;
+			break;
+		case '\t':
+			break;
+		case '#':
+			/* comment line is skipped */
+			if (column == 0 && p == col) {
+				while ((p < last) && *p)
+					if (*p++ == '\n')
+						break;
+				col = p;
+				i++;
+				if (p >= last || !*p) {
+					eof = true;
+					end_of_line = true;
+				}
+				continue;
+			}
+			/* fall through */
+		/* by default continue with the next character */
+		default:
+			p++;
+			continue;
+		}
+
+		/* replace by \0: allow string parsing for each column */
+		*p = '\0';
+		p++;
+		if (p >= last) {
+			eof = true;
+			end_of_line = true;
+		}
+
+		/* skip empty line and multiple TAB in tsv file */
+		if (strlen(col) == 0) {
+			col = p;
+			/* skip empty line */
+			if (column == 0 && end_of_line) {
+				end_of_line = false;
+				i++;
+			}
+			continue;
+		}
+
+		if (column < COL_NB_STM32) {
+			ret = parse[column](data, i, col, part);
+			if (ret)
+				return ret;
+		}
+
+		/* save the beginning of the next column */
+		column++;
+		col = p;
+
+		if (!end_of_line)
+			continue;
+
+		/* end of the line detected */
+		end_of_line = false;
+
+		if (column < COL_NB_STM32) {
+			stm32prog_err("Layout line %d: no enought column", i);
+			return -EINVAL;
+		}
+		column = 0;
+		part_nb++;
+		part++;
+		i++;
+		if (part_nb >= part_list_size) {
+			part = NULL;
+			if (!eof) {
+				stm32prog_err("Layout: no enought memory for %d part",
+					      part_nb);
+				return -EINVAL;
+			}
+		}
+	}
+	data->part_nb = part_nb;
+	if (data->part_nb == 0) {
+		stm32prog_err("Layout: no partition found");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int __init part_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+	struct stm32prog_part_t *parta, *partb;
+
+	parta = container_of(a, struct stm32prog_part_t, list);
+	partb = container_of(b, struct stm32prog_part_t, list);
+
+	if (parta->part_id != partb->part_id)
+		return parta->part_id - partb->part_id;
+	else
+		return parta->addr > partb->addr ? 1 : -1;
+}
+
+static void get_mtd_by_target(char *string, enum stm32prog_target target,
+			      int dev_id)
+{
+	const char *dev_str;
+
+	switch (target) {
+	case STM32PROG_NOR:
+		dev_str = "nor";
+		break;
+	case STM32PROG_NAND:
+		dev_str = "nand";
+		break;
+	case STM32PROG_SPI_NAND:
+		dev_str = "spi-nand";
+		break;
+	default:
+		dev_str = "invalid";
+		break;
+	}
+	sprintf(string, "%s%d", dev_str, dev_id);
+}
+
+static int init_device(struct stm32prog_data *data,
+		       struct stm32prog_dev_t *dev)
+{
+	struct mmc *mmc = NULL;
+	struct blk_desc *block_dev = NULL;
+#ifdef CONFIG_MTD
+	struct mtd_info *mtd = NULL;
+	char mtd_id[16];
+#endif
+	int part_id;
+	int ret;
+	u64 first_addr = 0, last_addr = 0;
+	struct stm32prog_part_t *part, *next_part;
+	u64 part_addr, part_size;
+	bool part_found;
+	const char *part_name;
+
+	switch (dev->target) {
+#ifdef CONFIG_MMC
+	case STM32PROG_MMC:
+		mmc = find_mmc_device(dev->dev_id);
+		if (mmc_init(mmc)) {
+			stm32prog_err("mmc device %d not found", dev->dev_id);
+			return -ENODEV;
+		}
+		block_dev = mmc_get_blk_desc(mmc);
+		if (!block_dev) {
+			stm32prog_err("mmc device %d not probed", dev->dev_id);
+			return -ENODEV;
+		}
+		dev->erase_size = mmc->erase_grp_size * block_dev->blksz;
+		dev->mmc = mmc;
+
+		/* reserve a full erase group for each GTP headers */
+		if (mmc->erase_grp_size > GPT_HEADER_SZ) {
+			first_addr = dev->erase_size;
+			last_addr = (u64)(block_dev->lba -
+					  mmc->erase_grp_size) *
+				    block_dev->blksz;
+		} else {
+			first_addr = (u64)GPT_HEADER_SZ * block_dev->blksz;
+			last_addr = (u64)(block_dev->lba - GPT_HEADER_SZ - 1) *
+				    block_dev->blksz;
+		}
+		pr_debug("MMC %d: lba=%ld blksz=%ld\n", dev->dev_id,
+			 block_dev->lba, block_dev->blksz);
+		pr_debug(" available address = 0x%llx..0x%llx\n",
+			 first_addr, last_addr);
+		pr_debug(" full_update = %d\n", dev->full_update);
+		break;
+#endif
+#ifdef CONFIG_MTD
+	case STM32PROG_NOR:
+	case STM32PROG_NAND:
+	case STM32PROG_SPI_NAND:
+		get_mtd_by_target(mtd_id, dev->target, dev->dev_id);
+		pr_debug("%s\n", mtd_id);
+
+		mtdparts_init();
+		mtd = get_mtd_device_nm(mtd_id);
+		if (IS_ERR(mtd)) {
+			stm32prog_err("MTD device %s not found", mtd_id);
+			return -ENODEV;
+		}
+		first_addr = 0;
+		last_addr = mtd->size;
+		dev->erase_size = mtd->erasesize;
+		pr_debug("MTD device %s: size=%lld erasesize=%d\n",
+			 mtd_id, mtd->size, mtd->erasesize);
+		pr_debug(" available address = 0x%llx..0x%llx\n",
+			 first_addr, last_addr);
+		dev->mtd = mtd;
+		break;
+#endif
+	case STM32PROG_RAM:
+		first_addr = gd->bd->bi_dram[0].start;
+		last_addr = first_addr + gd->bd->bi_dram[0].size;
+		dev->erase_size = 1;
+		break;
+	default:
+		stm32prog_err("unknown device type = %d", dev->target);
+		return -ENODEV;
+	}
+	pr_debug(" erase size = 0x%x\n", dev->erase_size);
+	pr_debug(" full_update = %d\n", dev->full_update);
+
+	/* order partition list in offset order */
+	list_sort(NULL, &dev->part_list, &part_cmp);
+	part_id = 1;
+	pr_debug("id : Opt Phase     Name target.n dev.n addr     size     part_off part_size\n");
+	list_for_each_entry(part, &dev->part_list, list) {
+		if (part->bin_nb > 1) {
+			if ((dev->target != STM32PROG_NAND &&
+			     dev->target != STM32PROG_SPI_NAND) ||
+			    part->id >= PHASE_FIRST_USER ||
+			    strncmp(part->name, "fsbl", 4)) {
+				stm32prog_err("%s (0x%x): multiple binary %d not supported",
+					      part->name, part->id,
+					      part->bin_nb);
+				return -EINVAL;
+			}
+		}
+		if (part->part_type == RAW_IMAGE) {
+			part->part_id = 0x0;
+			part->addr = 0x0;
+			if (block_dev)
+				part->size = block_dev->lba * block_dev->blksz;
+			else
+				part->size = last_addr;
+			pr_debug("-- : %1d %02x %14s %02d.%d %02d.%02d %08llx %08llx\n",
+				 part->option, part->id, part->name,
+				 part->part_type, part->bin_nb, part->target,
+				 part->dev_id, part->addr, part->size);
+			continue;
+		}
+		if (part->part_id < 0) { /* boot hw partition for eMMC */
+			if (mmc) {
+				part->size = mmc->capacity_boot;
+			} else {
+				stm32prog_err("%s (0x%x): hw partition not expected : %d",
+					      part->name, part->id,
+					      part->part_id);
+				return -ENODEV;
+			}
+		} else {
+			part->part_id = part_id++;
+
+			/* last partition : size to the end of the device */
+			if (part->list.next != &dev->part_list) {
+				next_part =
+					container_of(part->list.next,
+						     struct stm32prog_part_t,
+						     list);
+				if (part->addr < next_part->addr) {
+					part->size = next_part->addr -
+						     part->addr;
+				} else {
+					stm32prog_err("%s (0x%x): same address : 0x%llx == %s (0x%x): 0x%llx",
+						      part->name, part->id,
+						      part->addr,
+						      next_part->name,
+						      next_part->id,
+						      next_part->addr);
+					return -EINVAL;
+				}
+			} else {
+				if (part->addr <= last_addr) {
+					part->size = last_addr - part->addr;
+				} else {
+					stm32prog_err("%s (0x%x): invalid address 0x%llx (max=0x%llx)",
+						      part->name, part->id,
+						      part->addr, last_addr);
+					return -EINVAL;
+				}
+			}
+			if (part->addr < first_addr) {
+				stm32prog_err("%s (0x%x): invalid address 0x%llx (min=0x%llx)",
+					      part->name, part->id,
+					      part->addr, first_addr);
+				return -EINVAL;
+			}
+		}
+		if ((part->addr & ((u64)part->dev->erase_size - 1)) != 0) {
+			stm32prog_err("%s (0x%x): not aligned address : 0x%llx on erase size 0x%x",
+				      part->name, part->id, part->addr,
+				      part->dev->erase_size);
+			return -EINVAL;
+		}
+		pr_debug("%02d : %1d %02x %14s %02d.%d %02d.%02d %08llx %08llx",
+			 part->part_id, part->option, part->id, part->name,
+			 part->part_type, part->bin_nb, part->target,
+			 part->dev_id, part->addr, part->size);
+
+		part_addr = 0;
+		part_size = 0;
+		part_found = false;
+
+		/* check coherency with existing partition */
+		if (block_dev) {
+			/*
+			 * block devices with GPT: check user partition size
+			 * only for partial update, the GPT partions are be
+			 * created for full update
+			 */
+			if (dev->full_update || part->part_id < 0) {
+				pr_debug("\n");
+				continue;
+			}
+			disk_partition_t partinfo;
+
+			ret = part_get_info(block_dev, part->part_id,
+					    &partinfo);
+
+			if (ret) {
+				stm32prog_err("%s (0x%x):Couldn't find part %d on device mmc %d",
+					      part->name, part->id,
+					      part_id, part->dev_id);
+				return -ENODEV;
+			}
+			part_addr = (u64)partinfo.start * partinfo.blksz;
+			part_size = (u64)partinfo.size * partinfo.blksz;
+			part_name = (char *)partinfo.name;
+			part_found = true;
+		}
+
+#ifdef CONFIG_MTD
+		if (mtd) {
+			char mtd_part_id[32];
+			struct part_info *mtd_part;
+			struct mtd_device *mtd_dev;
+			u8 part_num;
+
+			sprintf(mtd_part_id, "%s,%d", mtd_id,
+				part->part_id - 1);
+			ret = find_dev_and_part(mtd_part_id, &mtd_dev,
+						&part_num, &mtd_part);
+			if (ret != 0) {
+				stm32prog_err("%s (0x%x): Invalid MTD partition %s",
+					      part->name, part->id,
+					      mtd_part_id);
+				return -ENODEV;
+			}
+			part_addr = mtd_part->offset;
+			part_size = mtd_part->size;
+			part_name = mtd_part->name;
+			part_found = true;
+		}
+#endif
+		if (!part_found) {
+			stm32prog_err("%s (0x%x): Invalid partition",
+				      part->name, part->id);
+			pr_debug("\n");
+			continue;
+		}
+
+		pr_debug(" %08llx %08llx\n", part_addr, part_size);
+
+		if (part->addr != part_addr) {
+			stm32prog_err("%s (0x%x): Bad address for partition %d (%s) = 0x%llx <> 0x%llx expected",
+				      part->name, part->id, part->part_id,
+				      part_name, part->addr, part_addr);
+			return -ENODEV;
+		}
+		if (part->size != part_size) {
+			stm32prog_err("%s (0x%x): Bad size for partition %d (%s) at 0x%llx = 0x%llx <> 0x%llx expected",
+				      part->name, part->id, part->part_id,
+				      part_name, part->addr, part->size,
+				      part_size);
+			return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+static int treat_partition_list(struct stm32prog_data *data)
+{
+	int i, j;
+	struct stm32prog_part_t *part;
+
+	for (j = 0; j < STM32PROG_MAX_DEV; j++) {
+		data->dev[j].target = STM32PROG_NONE;
+		INIT_LIST_HEAD(&data->dev[j].part_list);
+	}
+
+	data->tee_detected = false;
+	data->fsbl_nor_detected = false;
+	for (i = 0; i < data->part_nb; i++) {
+		part = &data->part_array[i];
+		part->alt_id = -1;
+
+		/* skip partition with IP="none" */
+		if (part->target == STM32PROG_NONE) {
+			if (IS_SELECT(part)) {
+				stm32prog_err("Layout: selected none phase = 0x%x",
+					      part->id);
+				return -EINVAL;
+			}
+			continue;
+		}
+
+		if (part->id == PHASE_FLASHLAYOUT ||
+		    part->id > PHASE_LAST_USER) {
+			stm32prog_err("Layout: invalid phase = 0x%x",
+				      part->id);
+			return -EINVAL;
+		}
+		for (j = i + 1; j < data->part_nb; j++) {
+			if (part->id == data->part_array[j].id) {
+				stm32prog_err("Layout: duplicated phase 0x%x at line %d and %d",
+					      part->id, i, j);
+				return -EINVAL;
+			}
+		}
+		for (j = 0; j < STM32PROG_MAX_DEV; j++) {
+			if (data->dev[j].target == STM32PROG_NONE) {
+				/* new device found */
+				data->dev[j].target = part->target;
+				data->dev[j].dev_id = part->dev_id;
+				data->dev[j].full_update = true;
+				data->dev_nb++;
+				break;
+			} else if ((part->target == data->dev[j].target) &&
+				   (part->dev_id == data->dev[j].dev_id)) {
+				break;
+			}
+		}
+		if (j == STM32PROG_MAX_DEV) {
+			stm32prog_err("Layout: too many device");
+			return -EINVAL;
+		}
+		switch (part->target)  {
+		case STM32PROG_NOR:
+			if (!data->fsbl_nor_detected &&
+			    !strncmp(part->name, "fsbl", 4))
+				data->fsbl_nor_detected = true;
+			/* fallthrough */
+		case STM32PROG_NAND:
+		case STM32PROG_SPI_NAND:
+			if (!data->tee_detected &&
+			    !strncmp(part->name, "tee", 3))
+				data->tee_detected = true;
+			break;
+		default:
+			break;
+		}
+		part->dev = &data->dev[j];
+		if (!IS_SELECT(part))
+			part->dev->full_update = false;
+		list_add_tail(&part->list, &data->dev[j].part_list);
+	}
+
+	return 0;
+}
+
+static int create_partitions(struct stm32prog_data *data)
+{
+#ifdef CONFIG_MMC
+	int offset = 0;
+	const int buflen = SZ_8K;
+	char *buf;
+	char uuid[UUID_STR_LEN + 1];
+	unsigned char *uuid_bin;
+	unsigned int mmc_id;
+	int i;
+	bool rootfs_found;
+	struct stm32prog_part_t *part;
+
+	buf = malloc(buflen);
+	if (!buf)
+		return -ENOMEM;
+
+	puts("partitions : ");
+	/* initialize the selected device */
+	for (i = 0; i < data->dev_nb; i++) {
+		/* create gpt partition support only for full update on MMC */
+		if (data->dev[i].target != STM32PROG_MMC ||
+		    !data->dev[i].full_update)
+			continue;
+
+		offset = 0;
+		rootfs_found = false;
+		memset(buf, 0, buflen);
+
+		list_for_each_entry(part, &data->dev[i].part_list, list) {
+			/* skip eMMC boot partitions */
+			if (part->part_id < 0)
+				continue;
+			/* skip Raw Image */
+			if (part->part_type == RAW_IMAGE)
+				continue;
+
+			if (offset + 100 > buflen) {
+				pr_debug("\n%s: buffer too small, %s skippped",
+					 __func__, part->name);
+				continue;
+			}
+
+			if (!offset)
+				offset += sprintf(buf, "gpt write mmc %d \"",
+						  data->dev[i].dev_id);
+
+			offset += snprintf(buf + offset, buflen - offset,
+					   "name=%s,start=0x%llx,size=0x%llx",
+					   part->name,
+					   part->addr,
+					   part->size);
+
+			if (part->part_type == PART_BINARY)
+				offset += snprintf(buf + offset,
+						   buflen - offset,
+						   ",type="
+						   LINUX_RESERVED_UUID);
+			else
+				offset += snprintf(buf + offset,
+						   buflen - offset,
+						   ",type=linux");
+
+			if (part->part_type == PART_SYSTEM)
+				offset += snprintf(buf + offset,
+						   buflen - offset,
+						   ",bootable");
+
+			if (!rootfs_found && !strcmp(part->name, "rootfs")) {
+				mmc_id = part->dev_id;
+				rootfs_found = true;
+				if (mmc_id < ARRAY_SIZE(uuid_mmc)) {
+					uuid_bin =
+					  (unsigned char *)uuid_mmc[mmc_id].b;
+					uuid_bin_to_str(uuid_bin, uuid,
+							UUID_STR_FORMAT_GUID);
+					offset += snprintf(buf + offset,
+							   buflen - offset,
+							   ",uuid=%s", uuid);
+				}
+			}
+
+			offset += snprintf(buf + offset, buflen - offset, ";");
+		}
+
+		if (offset) {
+			offset += snprintf(buf + offset, buflen - offset, "\"");
+			pr_debug("\ncmd: %s\n", buf);
+			if (run_command(buf, 0)) {
+				stm32prog_err("GPT partitionning fail: %s",
+					      buf);
+				free(buf);
+
+				return -1;
+			}
+		}
+
+		if (data->dev[i].mmc)
+			part_init(mmc_get_blk_desc(data->dev[i].mmc));
+
+#ifdef DEBUG
+		sprintf(buf, "gpt verify mmc %d", data->dev[i].dev_id);
+		pr_debug("\ncmd: %s", buf);
+		if (run_command(buf, 0))
+			printf("fail !\n");
+		else
+			printf("OK\n");
+
+		sprintf(buf, "part list mmc %d", data->dev[i].dev_id);
+		run_command(buf, 0);
+#endif
+	}
+	puts("done\n");
+
+#ifdef DEBUG
+	run_command("mtd list", 0);
+#endif
+	free(buf);
+#endif
+
+	return 0;
+}
+
+static int stm32prog_alt_add(struct stm32prog_data *data,
+			     struct dfu_entity *dfu,
+			     struct stm32prog_part_t *part)
+{
+	int ret = 0;
+	int offset = 0;
+	char devstr[10];
+	char dfustr[10];
+	char buf[ALT_BUF_LEN];
+	u32 size;
+	char multiplier,  type;
+
+	/* max 3 digit for sector size */
+	if (part->size > SZ_1M) {
+		size = (u32)(part->size / SZ_1M);
+		multiplier = 'M';
+	} else if (part->size > SZ_1K) {
+		size = (u32)(part->size / SZ_1K);
+		multiplier = 'K';
+	} else {
+		size = (u32)part->size;
+		multiplier = 'B';
+	}
+	if (IS_SELECT(part) && !IS_EMPTY(part))
+		type = 'e'; /*Readable and Writeable*/
+	else
+		type = 'a';/*Readable*/
+
+	memset(buf, 0, sizeof(buf));
+	offset = snprintf(buf, ALT_BUF_LEN - offset,
+			  "@%s/0x%02x/1*%d%c%c ",
+			  part->name, part->id,
+			  size, multiplier, type);
+
+	if (part->target == STM32PROG_RAM) {
+		offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
+				   "ram 0x%llx 0x%llx",
+				   part->addr, part->size);
+	} else if (part->part_type == RAW_IMAGE) {
+		u64 dfu_size;
+
+		if (part->dev->target == STM32PROG_MMC)
+			dfu_size = part->size / part->dev->mmc->read_bl_len;
+		else
+			dfu_size = part->size;
+		offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
+				   "raw 0x0 0x%llx", dfu_size);
+	} else if (part->part_id < 0) {
+		u64 nb_blk = part->size / part->dev->mmc->read_bl_len;
+
+		offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
+				   "raw 0x%llx 0x%llx",
+				   part->addr, nb_blk);
+		offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
+				   " mmcpart %d;", -(part->part_id));
+	} else {
+		if (part->part_type == PART_SYSTEM &&
+		    (part->target == STM32PROG_NAND ||
+		     part->target == STM32PROG_NOR ||
+		     part->target == STM32PROG_SPI_NAND))
+			offset += snprintf(buf + offset,
+					   ALT_BUF_LEN - offset,
+					   "partubi");
+		else
+			offset += snprintf(buf + offset,
+					   ALT_BUF_LEN - offset,
+					   "part");
+		/* dev_id requested by DFU MMC */
+		if (part->target == STM32PROG_MMC)
+			offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
+					   " %d", part->dev_id);
+		offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
+				   " %d;", part->part_id);
+	}
+	switch (part->target) {
+#ifdef CONFIG_MMC
+	case STM32PROG_MMC:
+		sprintf(dfustr, "mmc");
+		sprintf(devstr, "%d", part->dev_id);
+		break;
+#endif
+#ifdef CONFIG_MTD
+	case STM32PROG_NAND:
+	case STM32PROG_NOR:
+	case STM32PROG_SPI_NAND:
+		sprintf(dfustr, "mtd");
+		get_mtd_by_target(devstr, part->target, part->dev_id);
+		break;
+#endif
+	case STM32PROG_RAM:
+		sprintf(dfustr, "ram");
+		sprintf(devstr, "0");
+		break;
+	default:
+		stm32prog_err("invalid target: %d", part->target);
+		return -ENODEV;
+	}
+	pr_debug("dfu_alt_add(%s,%s,%s)\n", dfustr, devstr, buf);
+	ret = dfu_alt_add(dfu, dfustr, devstr, buf);
+	pr_debug("dfu_alt_add(%s,%s,%s) result %d\n",
+		 dfustr, devstr, buf, ret);
+
+	return ret;
+}
+
+static int stm32prog_alt_add_virt(struct dfu_entity *dfu,
+				  char *name, int phase, int size)
+{
+	int ret = 0;
+	char devstr[4];
+	char buf[ALT_BUF_LEN];
+
+	sprintf(devstr, "%d", phase);
+	sprintf(buf, "@%s/0x%02x/1*%dBe", name, phase, size);
+	ret = dfu_alt_add(dfu, "virt", devstr, buf);
+	pr_debug("dfu_alt_add(virt,%s,%s) result %d\n", devstr, buf, ret);
+
+	return ret;
+}
+
+static int dfu_init_entities(struct stm32prog_data *data)
+{
+	int ret = 0;
+	int phase, i, alt_id;
+	struct stm32prog_part_t *part;
+	struct dfu_entity *dfu;
+	int alt_nb;
+
+	alt_nb = 3; /* number of virtual = CMD, OTP, PMIC*/
+	if (data->part_nb == 0)
+		alt_nb++;  /* +1 for FlashLayout */
+	else
+		for (i = 0; i < data->part_nb; i++) {
+			if (data->part_array[i].target != STM32PROG_NONE)
+				alt_nb++;
+		}
+
+	if (dfu_alt_init(alt_nb, &dfu))
+		return -ENODEV;
+
+	puts("DFU alt info setting: ");
+	if (data->part_nb) {
+		alt_id = 0;
+		for (phase = 1;
+		     (phase <= PHASE_LAST_USER) &&
+		     (alt_id < alt_nb) && !ret;
+		     phase++) {
+			/* ordering alt setting by phase id */
+			part = NULL;
+			for (i = 0; i < data->part_nb; i++) {
+				if (phase == data->part_array[i].id) {
+					part = &data->part_array[i];
+					break;
+				}
+			}
+			if (!part)
+				continue;
+			if (part->target == STM32PROG_NONE)
+				continue;
+			part->alt_id = alt_id;
+			alt_id++;
+
+			ret = stm32prog_alt_add(data, dfu, part);
+		}
+	} else {
+		char buf[ALT_BUF_LEN];
+
+		sprintf(buf, "@FlashLayout/0x%02x/1*256Ke ram %x 40000",
+			PHASE_FLASHLAYOUT, STM32_DDR_BASE);
+		ret = dfu_alt_add(dfu, "ram", NULL, buf);
+		pr_debug("dfu_alt_add(ram, NULL,%s) result %d\n", buf, ret);
+	}
+
+	if (!ret)
+		ret = stm32prog_alt_add_virt(dfu, "virtual", PHASE_CMD, 512);
+
+	if (!ret)
+		ret = stm32prog_alt_add_virt(dfu, "OTP", PHASE_OTP, 512);
+
+	if (!ret && CONFIG_IS_ENABLED(DM_PMIC))
+		ret = stm32prog_alt_add_virt(dfu, "PMIC", PHASE_PMIC, 8);
+
+	if (ret)
+		stm32prog_err("dfu init failed: %d", ret);
+	puts("done\n");
+
+#ifdef DEBUG
+	dfu_show_entities();
+#endif
+	return ret;
+}
+
+int stm32prog_otp_write(struct stm32prog_data *data, u32 offset, u8 *buffer,
+			long *size)
+{
+	pr_debug("%s: %x %lx\n", __func__, offset, *size);
+
+	if (!data->otp_part) {
+		data->otp_part = memalign(CONFIG_SYS_CACHELINE_SIZE, OTP_SIZE);
+		if (!data->otp_part)
+			return -ENOMEM;
+	}
+
+	if (!offset)
+		memset(data->otp_part, 0, OTP_SIZE);
+
+	if (offset + *size > OTP_SIZE)
+		*size = OTP_SIZE - offset;
+
+	memcpy((void *)((u32)data->otp_part + offset), buffer, *size);
+
+	return 0;
+}
+
+int stm32prog_otp_read(struct stm32prog_data *data, u32 offset, u8 *buffer,
+		       long *size)
+{
+#ifndef CONFIG_ARM_SMCCC
+	stm32prog_err("OTP update not supported");
+
+	return -1;
+#else
+	int result = 0;
+
+	pr_debug("%s: %x %lx\n", __func__, offset, *size);
+	/* alway read for first packet */
+	if (!offset) {
+		if (!data->otp_part)
+			data->otp_part =
+				memalign(CONFIG_SYS_CACHELINE_SIZE, OTP_SIZE);
+
+		if (!data->otp_part) {
+			result = -ENOMEM;
+			goto end_otp_read;
+		}
+
+		/* init struct with 0 */
+		memset(data->otp_part, 0, OTP_SIZE);
+
+		/* call the service */
+		result = stm32_smc_exec(STM32_SMC_BSEC, STM32_SMC_READ_ALL,
+					(u32)data->otp_part, 0);
+		if (result)
+			goto end_otp_read;
+	}
+
+	if (!data->otp_part) {
+		result = -ENOMEM;
+		goto end_otp_read;
+	}
+
+	if (offset + *size > OTP_SIZE)
+		*size = OTP_SIZE - offset;
+	memcpy(buffer, (void *)((u32)data->otp_part + offset), *size);
+
+end_otp_read:
+	pr_debug("%s: result %i\n", __func__, result);
+
+	return result;
+#endif
+}
+
+int stm32prog_otp_start(struct stm32prog_data *data)
+{
+#ifndef CONFIG_ARM_SMCCC
+	stm32prog_err("OTP update not supported");
+
+	return -1;
+#else
+	int result = 0;
+	struct arm_smccc_res res;
+
+	if (!data->otp_part) {
+		stm32prog_err("start OTP without data");
+		return -1;
+	}
+
+	arm_smccc_smc(STM32_SMC_BSEC, STM32_SMC_WRITE_ALL,
+		      (u32)data->otp_part, 0, 0, 0, 0, 0, &res);
+
+	if (!res.a0) {
+		switch (res.a1) {
+		case 0:
+			result = 0;
+			break;
+		case 1:
+			stm32prog_err("Provisioning");
+			result = 0;
+			break;
+		default:
+			pr_err("%s: OTP incorrect value (err = %ld)\n",
+			       __func__, res.a1);
+			result = -EINVAL;
+			break;
+		}
+	} else {
+		pr_err("%s: Failed to exec svc=%x op=%x in secure mode (err = %ld)\n",
+		       __func__, STM32_SMC_BSEC, STM32_SMC_WRITE_ALL, res.a0);
+		result = -EINVAL;
+	}
+
+	free(data->otp_part);
+	data->otp_part = NULL;
+	pr_debug("%s: result %i\n", __func__, result);
+
+	return result;
+#endif
+}
+
+int stm32prog_pmic_write(struct stm32prog_data *data, u32 offset, u8 *buffer,
+			 long *size)
+{
+	pr_debug("%s: %x %lx\n", __func__, offset, *size);
+
+	if (!offset)
+		memset(data->pmic_part, 0, PMIC_SIZE);
+
+	if (offset + *size > PMIC_SIZE)
+		*size = PMIC_SIZE - offset;
+
+	memcpy(&data->pmic_part[offset], buffer, *size);
+
+	return 0;
+}
+
+int stm32prog_pmic_read(struct stm32prog_data *data, u32 offset, u8 *buffer,
+			long *size)
+{
+	int result = 0, ret;
+	struct udevice *dev;
+
+	if (!CONFIG_IS_ENABLED(PMIC_STPMIC1)) {
+		stm32prog_err("PMIC update not supported");
+
+		return -EOPNOTSUPP;
+	}
+
+	pr_debug("%s: %x %lx\n", __func__, offset, *size);
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+					  DM_GET_DRIVER(stpmic1_nvm),
+					  &dev);
+	if (ret)
+		return ret;
+
+	/* alway request PMIC for first packet */
+	if (!offset) {
+		/* init struct with 0 */
+		memset(data->pmic_part, 0, PMIC_SIZE);
+
+		ret = uclass_get_device_by_driver(UCLASS_MISC,
+						  DM_GET_DRIVER(stpmic1_nvm),
+						  &dev);
+		if (ret)
+			return ret;
+
+		ret = misc_read(dev, 0xF8, data->pmic_part, PMIC_SIZE);
+		if (ret < 0) {
+			result = ret;
+			goto end_pmic_read;
+		}
+		if (ret != PMIC_SIZE) {
+			result = -EACCES;
+			goto end_pmic_read;
+		}
+	}
+
+	if (offset + *size > PMIC_SIZE)
+		*size = PMIC_SIZE - offset;
+
+	memcpy(buffer, &data->pmic_part[offset], *size);
+
+end_pmic_read:
+	pr_debug("%s: result %i\n", __func__, result);
+	return result;
+}
+
+int stm32prog_pmic_start(struct stm32prog_data *data)
+{
+	int ret;
+	struct udevice *dev;
+
+	if (!CONFIG_IS_ENABLED(PMIC_STPMIC1)) {
+		stm32prog_err("PMIC update not supported");
+
+		return -EOPNOTSUPP;
+	}
+
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+					  DM_GET_DRIVER(stpmic1_nvm),
+					  &dev);
+	if (ret)
+		return ret;
+
+	return misc_write(dev, 0xF8, data->pmic_part, PMIC_SIZE);
+}
+
+/* copy FSBL on NAND to improve reliability on NAND */
+static int stm32prog_copy_fsbl(struct stm32prog_part_t *part)
+{
+	int ret, i;
+	void *fsbl;
+	struct image_header_s header;
+	struct raw_header_s raw_header;
+	struct dfu_entity *dfu;
+	long size, offset;
+
+	if (part->target != STM32PROG_NAND &&
+	    part->target != STM32PROG_SPI_NAND)
+		return -1;
+
+	dfu = dfu_get_entity(part->alt_id);
+
+	/* read header */
+	dfu_transaction_cleanup(dfu);
+	size = BL_HEADER_SIZE;
+	ret = dfu->read_medium(dfu, 0, (void *)&raw_header, &size);
+	if (ret)
+		return ret;
+	if (stm32prog_header_check(&raw_header, &header))
+		return -1;
+
+	/* read header + payload */
+	size = header.image_length + BL_HEADER_SIZE;
+	size = round_up(size, part->dev->mtd->erasesize);
+	fsbl = calloc(1, size);
+	if (!fsbl)
+		return -ENOMEM;
+	ret = dfu->read_medium(dfu, 0, fsbl, &size);
+	pr_debug("%s read size=%lx ret=%d\n", __func__, size, ret);
+	if (ret)
+		goto error;
+
+	dfu_transaction_cleanup(dfu);
+	offset = 0;
+	for (i = part->bin_nb - 1; i > 0; i--) {
+		offset += size;
+		/* write to the next erase block */
+		ret = dfu->write_medium(dfu, offset, fsbl, &size);
+		pr_debug("%s copy at ofset=%lx size=%lx ret=%d",
+			 __func__, offset, size, ret);
+		if (ret)
+			goto error;
+	}
+
+error:
+	free(fsbl);
+	return ret;
+}
+
+static void stm32prog_end_phase(struct stm32prog_data *data)
+{
+	if (data->phase == PHASE_FLASHLAYOUT) {
+		if (parse_flash_layout(data, STM32_DDR_BASE, 0))
+			stm32prog_err("Layout: invalid FlashLayout");
+		return;
+	}
+
+	if (!data->cur_part)
+		return;
+
+	if (data->cur_part->target == STM32PROG_RAM) {
+		if (data->cur_part->part_type == PART_SYSTEM)
+			data->uimage = data->cur_part->addr;
+		if (data->cur_part->part_type == PART_FILESYSTEM)
+			data->dtb = data->cur_part->addr;
+	}
+
+	if (CONFIG_IS_ENABLED(MMC) &&
+	    data->cur_part->part_id < 0) {
+		char cmdbuf[60];
+
+		sprintf(cmdbuf, "mmc bootbus %d 0 0 0; mmc partconf %d 1 %d 0",
+			data->cur_part->dev_id, data->cur_part->dev_id,
+			-(data->cur_part->part_id));
+		if (run_command(cmdbuf, 0)) {
+			stm32prog_err("commands '%s' failed", cmdbuf);
+			return;
+		}
+	}
+
+	if (CONFIG_IS_ENABLED(MTD) &&
+	    data->cur_part->bin_nb > 1) {
+		if (stm32prog_copy_fsbl(data->cur_part)) {
+			stm32prog_err("%s (0x%x): copy of fsbl failed",
+				      data->cur_part->name, data->cur_part->id);
+			return;
+		}
+	}
+}
+
+void stm32prog_do_reset(struct stm32prog_data *data)
+{
+	if (data->phase == PHASE_RESET) {
+		data->phase = PHASE_DO_RESET;
+		puts("Reset requested\n");
+	}
+}
+
+void stm32prog_next_phase(struct stm32prog_data *data)
+{
+	int phase, i;
+	struct stm32prog_part_t *part;
+	bool found;
+
+	phase = data->phase;
+	switch (phase) {
+	case PHASE_RESET:
+	case PHASE_END:
+	case PHASE_DO_RESET:
+		return;
+	}
+
+	/* found next selected partition */
+	data->dfu_seq = 0;
+	data->cur_part = NULL;
+	data->phase = PHASE_END;
+	found = false;
+	do {
+		phase++;
+		if (phase > PHASE_LAST_USER)
+			break;
+		for (i = 0; i < data->part_nb; i++) {
+			part = &data->part_array[i];
+			if (part->id == phase) {
+				if (IS_SELECT(part) && !IS_EMPTY(part)) {
+					data->cur_part = part;
+					data->phase = phase;
+					found = true;
+				}
+				break;
+			}
+		}
+	} while (!found);
+
+	if (data->phase == PHASE_END)
+		puts("Phase=END\n");
+}
+
+static int part_delete(struct stm32prog_data *data,
+		       struct stm32prog_part_t *part)
+{
+	int ret = 0;
+#ifdef CONFIG_MMC
+	unsigned long blks, blks_offset, blks_size;
+	struct blk_desc *block_dev = NULL;
+ #endif
+#ifdef CONFIG_MTD
+	char cmdbuf[40];
+	char devstr[10];
+#endif
+
+	printf("Erasing %s ", part->name);
+	switch (part->target) {
+#ifdef CONFIG_MMC
+	case STM32PROG_MMC:
+		printf("on mmc %d: ", part->dev->dev_id);
+		block_dev = mmc_get_blk_desc(part->dev->mmc);
+		blks_offset = lldiv(part->addr, part->dev->mmc->read_bl_len);
+		blks_size = lldiv(part->size, part->dev->mmc->read_bl_len);
+		/* -1 or -2 : delete boot partition of MMC
+		 * need to switch to associated hwpart 1 or 2
+		 */
+		if (part->part_id < 0)
+			if (blk_select_hwpart_devnum(IF_TYPE_MMC,
+						     part->dev->dev_id,
+						     -part->part_id))
+				return -1;
+
+		blks = blk_derase(block_dev, blks_offset, blks_size);
+
+		/* return to user partition */
+		if (part->part_id < 0)
+			blk_select_hwpart_devnum(IF_TYPE_MMC,
+						 part->dev->dev_id, 0);
+		if (blks != blks_size) {
+			ret = -1;
+			stm32prog_err("%s (0x%x): MMC erase failed",
+				      part->name, part->id);
+		}
+		break;
+#endif
+#ifdef CONFIG_MTD
+	case STM32PROG_NOR:
+	case STM32PROG_NAND:
+	case STM32PROG_SPI_NAND:
+		get_mtd_by_target(devstr, part->target, part->dev->dev_id);
+		printf("on %s: ", devstr);
+		sprintf(cmdbuf, "mtd erase %s 0x%llx 0x%llx",
+			devstr, part->addr, part->size);
+		if (run_command(cmdbuf, 0)) {
+			ret = -1;
+			stm32prog_err("%s (0x%x): MTD erase commands failed (%s)",
+				      part->name, part->id, cmdbuf);
+		}
+		break;
+#endif
+	case STM32PROG_RAM:
+		printf("on ram: ");
+		memset((void *)(uintptr_t)part->addr, 0, (size_t)part->size);
+		break;
+	default:
+		ret = -1;
+		stm32prog_err("%s (0x%x): erase invalid", part->name, part->id);
+		break;
+	}
+	if (!ret)
+		printf("done\n");
+
+	return ret;
+}
+
+static void stm32prog_devices_init(struct stm32prog_data *data)
+{
+	int i;
+	int ret;
+	struct stm32prog_part_t *part;
+
+	ret = treat_partition_list(data);
+	if (ret)
+		goto error;
+
+	/* initialize the selected device */
+	for (i = 0; i < data->dev_nb; i++) {
+		ret = init_device(data, &data->dev[i]);
+		if (ret)
+			goto error;
+	}
+
+	/* delete RAW partition before create partition */
+	for (i = 0; i < data->part_nb; i++) {
+		part = &data->part_array[i];
+
+		if (part->part_type != RAW_IMAGE)
+			continue;
+
+		if (!IS_SELECT(part) || !IS_DELETE(part))
+			continue;
+
+		ret = part_delete(data, part);
+		if (ret)
+			goto error;
+	}
+
+	ret = create_partitions(data);
+	if (ret)
+		goto error;
+
+	/* delete partition GPT or MTD */
+	for (i = 0; i < data->part_nb; i++) {
+		part = &data->part_array[i];
+
+		if (part->part_type == RAW_IMAGE)
+			continue;
+
+		if (!IS_SELECT(part) || !IS_DELETE(part))
+			continue;
+
+		ret = part_delete(data, part);
+		if (ret)
+			goto error;
+	}
+
+	return;
+
+error:
+	data->part_nb = 0;
+}
+
+int stm32prog_dfu_init(struct stm32prog_data *data)
+{
+	/* init device if no error */
+	if (data->part_nb)
+		stm32prog_devices_init(data);
+
+	if (data->part_nb)
+		stm32prog_next_phase(data);
+
+	/* prepare DFU for device read/write */
+	dfu_free_entities();
+	return dfu_init_entities(data);
+}
+
+int stm32prog_init(struct stm32prog_data *data, ulong addr, ulong size)
+{
+	memset(data, 0x0, sizeof(*data));
+	data->read_phase = PHASE_RESET;
+	data->phase = PHASE_FLASHLAYOUT;
+
+	return parse_flash_layout(data, addr, size);
+}
+
+void stm32prog_clean(struct stm32prog_data *data)
+{
+	/* clean */
+	dfu_free_entities();
+	free(data->part_array);
+	free(data->otp_part);
+	free(data->buffer);
+	free(data->header_data);
+}
+
+/* DFU callback: used after serial and direct DFU USB access */
+void dfu_flush_callback(struct dfu_entity *dfu)
+{
+	if (!stm32prog_data)
+		return;
+
+	if (dfu->dev_type == DFU_DEV_VIRT) {
+		if (dfu->data.virt.dev_num == PHASE_OTP)
+			stm32prog_otp_start(stm32prog_data);
+		else if (dfu->data.virt.dev_num == PHASE_PMIC)
+			stm32prog_pmic_start(stm32prog_data);
+		return;
+	}
+
+	if (dfu->dev_type == DFU_DEV_RAM) {
+		if (dfu->alt == 0 &&
+		    stm32prog_data->phase == PHASE_FLASHLAYOUT) {
+			stm32prog_end_phase(stm32prog_data);
+			/* waiting DFU DETACH for reenumeration */
+		}
+	}
+
+	if (!stm32prog_data->cur_part)
+		return;
+
+	if (dfu->alt == stm32prog_data->cur_part->alt_id) {
+		stm32prog_end_phase(stm32prog_data);
+		stm32prog_next_phase(stm32prog_data);
+	}
+}
+
+void dfu_initiated_callback(struct dfu_entity *dfu)
+{
+	if (!stm32prog_data)
+		return;
+
+	if (!stm32prog_data->cur_part)
+		return;
+
+	/* force the saved offset for the current partition */
+	if (dfu->alt == stm32prog_data->cur_part->alt_id) {
+		dfu->offset = stm32prog_data->offset;
+		stm32prog_data->dfu_seq = 0;
+		pr_debug("dfu offset = 0x%llx\n", dfu->offset);
+	}
+}

+ 185 - 0
arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h

@@ -0,0 +1,185 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef _STM32PROG_H_
+#define _STM32PROG_H_
+
+/* - phase defines ------------------------------------------------*/
+#define PHASE_FLASHLAYOUT	0x00
+#define PHASE_FIRST_USER	0x10
+#define PHASE_LAST_USER		0xF0
+#define PHASE_CMD		0xF1
+#define PHASE_OTP		0xF2
+#define PHASE_PMIC		0xF4
+#define PHASE_END		0xFE
+#define PHASE_RESET		0xFF
+#define PHASE_DO_RESET		0x1FF
+
+#define DEFAULT_ADDRESS		0xFFFFFFFF
+
+#define OTP_SIZE		1024
+#define PMIC_SIZE		8
+
+enum stm32prog_target {
+	STM32PROG_NONE,
+	STM32PROG_MMC,
+	STM32PROG_NAND,
+	STM32PROG_NOR,
+	STM32PROG_SPI_NAND,
+	STM32PROG_RAM
+};
+
+enum stm32prog_link_t {
+	LINK_SERIAL,
+	LINK_USB,
+	LINK_UNDEFINED,
+};
+
+struct image_header_s {
+	bool	present;
+	u32	image_checksum;
+	u32	image_length;
+};
+
+struct raw_header_s {
+	u32 magic_number;
+	u32 image_signature[64 / 4];
+	u32 image_checksum;
+	u32 header_version;
+	u32 image_length;
+	u32 image_entry_point;
+	u32 reserved1;
+	u32 load_address;
+	u32 reserved2;
+	u32 version_number;
+	u32 option_flags;
+	u32 ecdsa_algorithm;
+	u32 ecdsa_public_key[64 / 4];
+	u32 padding[83 / 4];
+	u32 binary_type;
+};
+
+#define BL_HEADER_SIZE	sizeof(struct raw_header_s)
+
+/* partition type in flashlayout file */
+enum stm32prog_part_type {
+	PART_BINARY,
+	PART_SYSTEM,
+	PART_FILESYSTEM,
+	RAW_IMAGE
+};
+
+/* device information */
+struct stm32prog_dev_t {
+	enum stm32prog_target	target;
+	char			dev_id;
+	u32			erase_size;
+	struct mmc		*mmc;
+	struct mtd_info		*mtd;
+	/* list of partition for this device / ordered in offset */
+	struct list_head	part_list;
+	bool			full_update;
+};
+
+/* partition information build from FlashLayout and device */
+struct stm32prog_part_t {
+	/* FlashLayout information */
+	int			option;
+	int			id;
+	enum stm32prog_part_type part_type;
+	enum stm32prog_target	target;
+	char			dev_id;
+
+	/* partition name
+	 * (16 char in gpt, + 1 for null terminated string
+	 */
+	char			name[16 + 1];
+	u64			addr;
+	u64			size;
+	enum stm32prog_part_type bin_nb;	/* SSBL repeatition */
+
+	/* information on associated device */
+	struct stm32prog_dev_t	*dev;		/* pointer to device */
+	s16			part_id;	/* partition id in device */
+	int			alt_id;		/* alt id in usb/dfu */
+
+	struct list_head	list;
+};
+
+#define STM32PROG_MAX_DEV 5
+struct stm32prog_data {
+	/* Layout information */
+	int			dev_nb;		/* device number*/
+	struct stm32prog_dev_t	dev[STM32PROG_MAX_DEV];	/* array of device */
+	int			part_nb;	/* nb of partition */
+	struct stm32prog_part_t	*part_array;	/* array of partition */
+	bool			tee_detected;
+	bool			fsbl_nor_detected;
+
+	/* command internal information */
+	unsigned int		phase;
+	u32			offset;
+	char			error[255];
+	struct stm32prog_part_t	*cur_part;
+	u32			*otp_part;
+	u8			pmic_part[PMIC_SIZE];
+
+	/* STM32 header information */
+	struct raw_header_s	*header_data;
+	struct image_header_s	header;
+
+	/* SERIAL information */
+	u32	cursor;
+	u32	packet_number;
+	u32	checksum;
+	u8	*buffer; /* size = USART_RAM_BUFFER_SIZE*/
+	int	dfu_seq;
+	u8	read_phase;
+
+	/* bootm information */
+	u32	uimage;
+	u32	dtb;
+};
+
+extern struct stm32prog_data *stm32prog_data;
+
+/* OTP access */
+int stm32prog_otp_write(struct stm32prog_data *data, u32 offset,
+			u8 *buffer, long *size);
+int stm32prog_otp_read(struct stm32prog_data *data, u32 offset,
+		       u8 *buffer, long *size);
+int stm32prog_otp_start(struct stm32prog_data *data);
+
+/* PMIC access */
+int stm32prog_pmic_write(struct stm32prog_data *data, u32 offset,
+			 u8 *buffer, long *size);
+int stm32prog_pmic_read(struct stm32prog_data *data, u32 offset,
+			u8 *buffer, long *size);
+int stm32prog_pmic_start(struct stm32prog_data *data);
+
+/* generic part*/
+u8 stm32prog_header_check(struct raw_header_s *raw_header,
+			  struct image_header_s *header);
+int stm32prog_dfu_init(struct stm32prog_data *data);
+void stm32prog_next_phase(struct stm32prog_data *data);
+void stm32prog_do_reset(struct stm32prog_data *data);
+
+char *stm32prog_get_error(struct stm32prog_data *data);
+
+#define stm32prog_err(args...) {\
+	if (data->phase != PHASE_RESET) { \
+		sprintf(data->error, args); \
+		data->phase = PHASE_RESET; \
+		pr_err("Error: %s\n", data->error); } \
+	}
+
+/* Main function */
+int stm32prog_init(struct stm32prog_data *data, ulong addr, ulong size);
+int stm32prog_serial_init(struct stm32prog_data *data, int link_dev);
+bool stm32prog_serial_loop(struct stm32prog_data *data);
+bool stm32prog_usb_loop(struct stm32prog_data *data, int dev);
+void stm32prog_clean(struct stm32prog_data *data);
+
+#endif

+ 993 - 0
arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_serial.c

@@ -0,0 +1,993 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dfu.h>
+#include <malloc.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <dm/lists.h>
+#include <dm/device-internal.h>
+#include "stm32prog.h"
+
+/* - configuration part -----------------------------*/
+#define USART_BL_VERSION	0x40	/* USART bootloader version V4.0*/
+#define UBOOT_BL_VERSION	0x03	/* bootloader version V0.3*/
+#define DEVICE_ID_BYTE1		0x05	/* MSB byte of device ID*/
+#define DEVICE_ID_BYTE2		0x00	/* LSB byte of device ID*/
+#define USART_RAM_BUFFER_SIZE	256	/* Size of USART_RAM_Buf buffer*/
+
+/* - Commands -----------------------------*/
+#define GET_CMD_COMMAND		0x00	/* Get CMD command*/
+#define GET_VER_COMMAND		0x01	/* Get Version command*/
+#define GET_ID_COMMAND		0x02	/* Get ID command*/
+#define GET_PHASE_COMMAND	0x03	/* Get Phase command*/
+#define RM_COMMAND		0x11	/* Read Memory command*/
+#define READ_PART_COMMAND	0x12	/* Read Partition command*/
+#define START_COMMAND		0x21	/* START command (Go)*/
+#define DOWNLOAD_COMMAND	0x31	/* Download command*/
+/* existing command for other STM32 but not used */
+/* ERASE			0x43 */
+/* EXTENDED_ERASE		0x44 */
+/* WRITE_UNPROTECTED		0x73 */
+/* READOUT_PROTECT		0x82 */
+/* READOUT_UNPROTECT		0x92 */
+
+/* - miscellaneous defines ----------------------------------------*/
+#define INIT_BYTE		0x7F	/*Init Byte ID*/
+#define ACK_BYTE		0x79	/*Acknowlede Byte ID*/
+#define NACK_BYTE		0x1F	/*No Acknowlede Byte ID*/
+#define ABORT_BYTE		0x5F	/*ABORT*/
+
+struct udevice *down_serial_dev;
+
+const u8 cmd_id[] = {
+	GET_CMD_COMMAND,
+	GET_VER_COMMAND,
+	GET_ID_COMMAND,
+	GET_PHASE_COMMAND,
+	RM_COMMAND,
+	READ_PART_COMMAND,
+	START_COMMAND,
+	DOWNLOAD_COMMAND
+};
+
+#define NB_CMD sizeof(cmd_id)
+
+/* DFU support for serial *********************************************/
+static struct dfu_entity *stm32prog_get_entity(struct stm32prog_data *data)
+{
+	int alt_id;
+
+	if (!data->cur_part)
+		if (data->phase == PHASE_FLASHLAYOUT)
+			alt_id = 0;
+		else
+			return NULL;
+	else
+		alt_id = data->cur_part->alt_id;
+
+	return dfu_get_entity(alt_id);
+}
+
+static int stm32prog_write(struct stm32prog_data *data, u8 *buffer,
+			   u32 buffer_size)
+{
+	struct dfu_entity *dfu_entity;
+	u8 ret = 0;
+
+	dfu_entity = stm32prog_get_entity(data);
+	if (!dfu_entity)
+		return -ENODEV;
+
+	ret = dfu_write(dfu_entity,
+			buffer,
+			buffer_size,
+			data->dfu_seq);
+
+	if (ret) {
+		stm32prog_err("DFU write failed [%d] cnt: %d",
+			      ret, data->dfu_seq);
+	}
+	data->dfu_seq++;
+	/* handle rollover as in driver/dfu/dfu.c */
+	data->dfu_seq &= 0xffff;
+	if (buffer_size == 0)
+		data->dfu_seq = 0; /* flush done */
+
+	return ret;
+}
+
+static int stm32prog_read(struct stm32prog_data *data, u8 phase, u32 offset,
+			  u8 *buffer, u32 buffer_size)
+{
+	struct dfu_entity *dfu_entity;
+	struct stm32prog_part_t *part;
+	u32 size;
+	int ret, i;
+
+	if (data->dfu_seq) {
+		stm32prog_err("DFU write pending for phase %d, seq %d",
+			      data->phase, data->dfu_seq);
+		return -EINVAL;
+	}
+	if (phase == PHASE_FLASHLAYOUT || phase > PHASE_LAST_USER) {
+		stm32prog_err("read failed : phase %d is invalid", phase);
+		return -EINVAL;
+	}
+	if (data->read_phase <= PHASE_LAST_USER &&
+	    phase != data->read_phase) {
+		/* clear previous read session */
+		dfu_entity = dfu_get_entity(data->read_phase - 1);
+		if (dfu_entity)
+			dfu_transaction_cleanup(dfu_entity);
+	}
+
+	dfu_entity = NULL;
+	/* found partition for the expected phase */
+	for (i = 0; i < data->part_nb; i++) {
+		part = &data->part_array[i];
+		if (part->id == phase)
+			dfu_entity = dfu_get_entity(part->alt_id);
+	}
+	if (!dfu_entity) {
+		stm32prog_err("read failed : phase %d is unknown", phase);
+		return -ENODEV;
+	}
+
+	/* clear pending read before to force offset */
+	if (dfu_entity->inited &&
+	    (data->read_phase != phase || data->offset != offset))
+		dfu_transaction_cleanup(dfu_entity);
+
+	/* initiate before to force offset */
+	if (!dfu_entity->inited) {
+		ret = dfu_transaction_initiate(dfu_entity, true);
+			if (ret < 0) {
+				stm32prog_err("DFU read init failed [%d] phase = %d offset = 0x%08x",
+					      ret, phase, offset);
+			return ret;
+		}
+	}
+	/* force new offset */
+	if (dfu_entity->offset != offset)
+		dfu_entity->offset = offset;
+	data->offset = offset;
+	data->read_phase = phase;
+	pr_debug("\nSTM32 download read %s offset=0x%x\n",
+		 dfu_entity->name, offset);
+	ret = dfu_read(dfu_entity, buffer, buffer_size,
+		       dfu_entity->i_blk_seq_num);
+	if (ret < 0) {
+		stm32prog_err("DFU read failed [%d] phase = %d offset = 0x%08x",
+			      ret, phase, offset);
+		return ret;
+	}
+
+	size = ret;
+
+	if (size < buffer_size) {
+		data->offset = 0;
+		data->read_phase = PHASE_END;
+		memset(buffer + size, 0, buffer_size - size);
+	} else {
+		data->offset += size;
+	}
+
+	return ret;
+}
+
+/* UART access ***************************************************/
+int stm32prog_serial_init(struct stm32prog_data *data, int link_dev)
+{
+	struct udevice *dev = NULL;
+	int node;
+	char alias[10];
+	const char *path;
+	struct dm_serial_ops *ops;
+	/* no parity, 8 bits, 1 stop */
+	u32 serial_config = SERIAL_DEFAULT_CONFIG;
+
+	down_serial_dev = NULL;
+
+	sprintf(alias, "serial%d", link_dev);
+	path = fdt_get_alias(gd->fdt_blob, alias);
+	if (!path) {
+		pr_err("%s alias not found", alias);
+		return -ENODEV;
+	}
+	node = fdt_path_offset(gd->fdt_blob, path);
+	if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node,
+					    &dev)) {
+		down_serial_dev = dev;
+	} else if (node > 0 &&
+		   !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node),
+				   &dev, false)) {
+		if (!device_probe(dev))
+			down_serial_dev = dev;
+	}
+	if (!down_serial_dev) {
+		pr_err("%s = %s device not found", alias, path);
+		return -ENODEV;
+	}
+
+	/* force silent console on uart only when used */
+	if (gd->cur_serial_dev == down_serial_dev)
+		gd->flags |= GD_FLG_DISABLE_CONSOLE | GD_FLG_SILENT;
+	else
+		gd->flags &= ~(GD_FLG_DISABLE_CONSOLE | GD_FLG_SILENT);
+
+	ops = serial_get_ops(down_serial_dev);
+
+	if (!ops) {
+		pr_err("%s = %s missing ops", alias, path);
+		return -ENODEV;
+	}
+	if (!ops->setconfig) {
+		pr_err("%s = %s missing setconfig", alias, path);
+		return -ENODEV;
+	}
+
+	clrsetbits_le32(&serial_config, SERIAL_PAR_MASK, SERIAL_PAR_EVEN);
+
+	data->buffer = memalign(CONFIG_SYS_CACHELINE_SIZE,
+				USART_RAM_BUFFER_SIZE);
+
+	return ops->setconfig(down_serial_dev, serial_config);
+}
+
+static void stm32prog_serial_flush(void)
+{
+	struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
+	int err;
+
+	do {
+		err = ops->getc(down_serial_dev);
+	} while (err != -EAGAIN);
+}
+
+static int stm32prog_serial_getc_err(void)
+{
+	struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
+	int err;
+
+	do {
+		err = ops->getc(down_serial_dev);
+		if (err == -EAGAIN) {
+			ctrlc();
+			WATCHDOG_RESET();
+		}
+	} while ((err == -EAGAIN) && (!had_ctrlc()));
+
+	return err;
+}
+
+static u8 stm32prog_serial_getc(void)
+{
+	int err;
+
+	err = stm32prog_serial_getc_err();
+
+	return err >= 0 ? err : 0;
+}
+
+static bool stm32prog_serial_get_buffer(u8 *buffer, u32 *count)
+{
+	struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
+	int err;
+
+	do {
+		err = ops->getc(down_serial_dev);
+		if (err >= 0) {
+			*buffer++ = err;
+			*count -= 1;
+		} else if (err == -EAGAIN) {
+			ctrlc();
+			WATCHDOG_RESET();
+		} else {
+			break;
+		}
+	} while (*count && !had_ctrlc());
+
+	return !!(err < 0);
+}
+
+static void stm32prog_serial_putc(u8 w_byte)
+{
+	struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
+	int err;
+
+	do {
+		err = ops->putc(down_serial_dev, w_byte);
+	} while (err == -EAGAIN);
+}
+
+/* Helper function ************************************************/
+
+static u8 stm32prog_header(struct stm32prog_data *data)
+{
+	u8 ret;
+	u8 boot = 0;
+	struct dfu_entity *dfu_entity;
+	u64 size = 0;
+
+	dfu_entity = stm32prog_get_entity(data);
+	if (!dfu_entity)
+		return -ENODEV;
+
+	printf("\nSTM32 download write %s\n", dfu_entity->name);
+
+	/* force cleanup to avoid issue with previous read */
+	dfu_transaction_cleanup(dfu_entity);
+
+	ret = stm32prog_header_check(data->header_data,
+				     &data->header);
+
+	/* no header : max size is partition size */
+	if (ret) {
+		dfu_entity->get_medium_size(dfu_entity, &size);
+		data->header.image_length = size;
+	}
+
+	/**** Flash the header if necessary for boot partition */
+	if (data->phase < PHASE_FIRST_USER)
+		boot = 1;
+
+	/* write header if boot partition */
+	if (boot) {
+		if (ret) {
+			stm32prog_err("invalid header (error %d)", ret);
+		} else {
+			ret = stm32prog_write(data,
+					      (u8 *)data->header_data,
+					      BL_HEADER_SIZE);
+		}
+	} else {
+		if (ret)
+			printf("  partition without checksum\n");
+		ret = 0;
+	}
+
+	free(data->header_data);
+	data->header_data = NULL;
+
+	return ret;
+}
+
+static u8 stm32prog_start(struct stm32prog_data *data, u32 address)
+{
+	u8 ret = 0;
+	struct dfu_entity *dfu_entity;
+
+	if (address < 0x100) {
+		if (address == PHASE_OTP)
+			return stm32prog_otp_start(data);
+
+		if (address == PHASE_PMIC)
+			return stm32prog_pmic_start(data);
+
+		if (address == PHASE_RESET || address == PHASE_END) {
+			data->cur_part = NULL;
+			data->dfu_seq = 0;
+			data->phase = address;
+			return 0;
+		}
+		if (address != data->phase) {
+			stm32prog_err("invalid received phase id %d, current phase is %d",
+				      (u8)address, (u8)data->phase);
+			return -EINVAL;
+		}
+	}
+	/* check the last loaded partition */
+	if (address == DEFAULT_ADDRESS || address == data->phase) {
+		switch (data->phase) {
+		case PHASE_END:
+		case PHASE_RESET:
+		case PHASE_DO_RESET:
+			data->cur_part = NULL;
+			data->phase = PHASE_DO_RESET;
+			return 0;
+		}
+		dfu_entity = stm32prog_get_entity(data);
+		if (!dfu_entity)
+			return -ENODEV;
+
+		if (data->dfu_seq) {
+			ret = dfu_flush(dfu_entity, NULL, 0, data->dfu_seq);
+			data->dfu_seq = 0;
+			if (ret) {
+				stm32prog_err("DFU flush failed [%d]", ret);
+				return ret;
+			}
+		}
+		printf("\n  received length = 0x%x\n", data->cursor);
+		if (data->header.present) {
+			if (data->cursor !=
+			    (data->header.image_length + BL_HEADER_SIZE)) {
+				stm32prog_err("transmission interrupted (length=0x%x expected=0x%x)",
+					      data->cursor,
+					      data->header.image_length +
+					      BL_HEADER_SIZE);
+				return -EIO;
+			}
+			if (data->header.image_checksum != data->checksum) {
+				stm32prog_err("invalid checksum received (0x%x expected 0x%x)",
+					      data->checksum,
+					      data->header.image_checksum);
+				return -EIO;
+			}
+			printf("\n  checksum OK (0x%x)\n", data->checksum);
+		}
+
+		/* update DFU with received flashlayout */
+		if (data->phase == PHASE_FLASHLAYOUT)
+			stm32prog_dfu_init(data);
+	} else {
+		void (*entry)(void) = (void *)address;
+
+		printf("## Starting application at 0x%x ...\n", address);
+		(*entry)();
+		printf("## Application terminated\n");
+		ret = -ENOEXEC;
+	}
+
+	return ret;
+}
+
+/**
+ * get_address() - Get address if it is valid
+ *
+ * @tmp_xor:		Current xor value to update
+ * @return The address area
+ */
+static u32 get_address(u8 *tmp_xor)
+{
+	u32 address = 0x0;
+	u8 data;
+
+	data = stm32prog_serial_getc();
+	*tmp_xor ^= data;
+	address |= ((u32)data) << 24;
+
+	data = stm32prog_serial_getc();
+	address |= ((u32)data) << 16;
+	*tmp_xor ^= data;
+
+	data = stm32prog_serial_getc();
+	address |= ((u32)data) << 8;
+	*tmp_xor ^= data;
+
+	data = stm32prog_serial_getc();
+	address |= ((u32)data);
+	*tmp_xor ^= data;
+
+	return address;
+}
+
+static void stm32prog_serial_result(u8 result)
+{
+	/* always flush fifo before to send result */
+	stm32prog_serial_flush();
+	stm32prog_serial_putc(result);
+}
+
+/* Command -----------------------------------------------*/
+/**
+ * get_cmd_command() - Respond to Get command
+ *
+ * @data:		Current command context
+ */
+static void get_cmd_command(struct stm32prog_data *data)
+{
+	u32 counter = 0x0;
+
+	stm32prog_serial_putc(NB_CMD);
+	stm32prog_serial_putc(USART_BL_VERSION);
+
+	for (counter = 0; counter < NB_CMD; counter++)
+		stm32prog_serial_putc(cmd_id[counter]);
+
+	stm32prog_serial_result(ACK_BYTE);
+}
+
+/**
+ * get_version_command() - Respond to Get Version command
+ *
+ * @data:		Current command context
+ */
+static void get_version_command(struct stm32prog_data *data)
+{
+	stm32prog_serial_putc(UBOOT_BL_VERSION);
+	stm32prog_serial_result(ACK_BYTE);
+}
+
+/**
+ * get_id_command() - Respond to Get ID command
+ *
+ * @data:		Current command context
+ */
+static void get_id_command(struct stm32prog_data *data)
+{
+	/* Send Device IDCode */
+	stm32prog_serial_putc(0x1);
+	stm32prog_serial_putc(DEVICE_ID_BYTE1);
+	stm32prog_serial_putc(DEVICE_ID_BYTE2);
+	stm32prog_serial_result(ACK_BYTE);
+}
+
+/**
+ * get_phase_command() - Respond to Get phase
+ *
+ * @data:		Current command context
+ */
+static void get_phase_command(struct stm32prog_data *data)
+{
+	char *err_msg = NULL;
+	u8 i, length = 0;
+	u32 destination = DEFAULT_ADDRESS; /* destination address */
+	int phase = data->phase;
+
+	if (phase == PHASE_RESET || phase == PHASE_DO_RESET) {
+		err_msg = stm32prog_get_error(data);
+		length = strlen(err_msg);
+	}
+	if (phase == PHASE_FLASHLAYOUT)
+		destination = STM32_DDR_BASE;
+
+	stm32prog_serial_putc(length + 5);           /* Total length */
+	stm32prog_serial_putc(phase & 0xFF);         /* partition ID */
+	stm32prog_serial_putc(destination);          /* byte 1 of address */
+	stm32prog_serial_putc(destination >> 8);     /* byte 2 of address */
+	stm32prog_serial_putc(destination >> 16);    /* byte 3 of address */
+	stm32prog_serial_putc(destination >> 24);    /* byte 4 of address */
+
+	stm32prog_serial_putc(length);               /* Information length */
+	for (i = 0; i < length; i++)
+		stm32prog_serial_putc(err_msg[i]);
+	stm32prog_serial_result(ACK_BYTE);
+
+	if (phase == PHASE_RESET)
+		stm32prog_do_reset(data);
+}
+
+/**
+ * read_memory_command() - Read data from memory
+ *
+ * @data:		Current command context
+ */
+static void read_memory_command(struct stm32prog_data *data)
+{
+	u32 address = 0x0;
+	u8 rcv_data = 0x0, tmp_xor = 0x0;
+	u32 counter = 0x0;
+
+	/* Read memory address */
+	address = get_address(&tmp_xor);
+
+	/* If address memory is not received correctly */
+	rcv_data = stm32prog_serial_getc();
+	if (rcv_data != tmp_xor) {
+		stm32prog_serial_result(NACK_BYTE);
+		return;
+	}
+
+	stm32prog_serial_result(ACK_BYTE);
+
+	/* Read the number of bytes to be received:
+	 * Max NbrOfData = Data + 1 = 256
+	 */
+	rcv_data = stm32prog_serial_getc();
+	tmp_xor = ~rcv_data;
+	if (stm32prog_serial_getc() != tmp_xor) {
+		stm32prog_serial_result(NACK_BYTE);
+		return;
+	}
+
+	/* If checksum is correct send ACK */
+	stm32prog_serial_result(ACK_BYTE);
+
+	/* Send data to the host:
+	 * Number of data to read = data + 1
+	 */
+	for (counter = (rcv_data + 1); counter != 0; counter--)
+		stm32prog_serial_putc(*(u8 *)(address++));
+}
+
+/**
+ * start_command() - Respond to start command
+ *
+ * Jump to user application in RAM or partition check
+ *
+ * @data:		Current command context
+ */
+static void start_command(struct stm32prog_data *data)
+{
+	u32 address = 0;
+	u8 tmp_xor = 0x0;
+	u8 ret, rcv_data;
+
+	/* Read memory address */
+	address = get_address(&tmp_xor);
+
+	/* If address memory is not received correctly */
+	rcv_data = stm32prog_serial_getc();
+	if (rcv_data != tmp_xor) {
+		stm32prog_serial_result(NACK_BYTE);
+		return;
+	}
+	/* validate partition */
+	ret = stm32prog_start(data,
+			      address);
+
+	if (ret)
+		stm32prog_serial_result(ABORT_BYTE);
+	else
+		stm32prog_serial_result(ACK_BYTE);
+}
+
+/**
+ * download_command() - Respond to download command
+ *
+ * Write data to not volatile memory, Flash
+ *
+ * @data:		Current command context
+ */
+static void download_command(struct stm32prog_data *data)
+{
+	u32 address = 0x0;
+	u8 my_xor = 0x0;
+	u8 rcv_xor;
+	u32 counter = 0x0, codesize = 0x0;
+	u8 *ramaddress = 0;
+	u8 rcv_data = 0x0;
+	struct image_header_s *image_header = &data->header;
+	u32 cursor = data->cursor;
+	long size = 0;
+	u8 operation;
+	u32 packet_number;
+	u32 result = ACK_BYTE;
+	u8 ret;
+	unsigned int i;
+	bool error;
+	int rcv;
+
+	address = get_address(&my_xor);
+
+	/* If address memory is not received correctly */
+	rcv_xor = stm32prog_serial_getc();
+	if (rcv_xor != my_xor) {
+		result = NACK_BYTE;
+		goto end;
+	}
+
+	/* If address valid send ACK */
+	stm32prog_serial_result(ACK_BYTE);
+
+	/* get packet number and operation type */
+	operation = (u8)((u32)address >> 24);
+	packet_number = ((u32)(((u32)address << 8))) >> 8;
+
+	switch (operation) {
+	/* supported operation */
+	case PHASE_FLASHLAYOUT:
+	case PHASE_OTP:
+	case PHASE_PMIC:
+		break;
+	default:
+		result = NACK_BYTE;
+		goto end;
+	}
+	/* check the packet number */
+	if (packet_number == 0) {
+		/* erase: re-initialize the image_header struct */
+		data->packet_number = 0;
+		if (data->header_data)
+			memset(data->header_data, 0, BL_HEADER_SIZE);
+		else
+			data->header_data = calloc(1, BL_HEADER_SIZE);
+		cursor = 0;
+		data->cursor = 0;
+		data->checksum = 0;
+		/*idx = cursor;*/
+	} else {
+		data->packet_number++;
+	}
+
+	/* Check with the number of current packet if the device receive
+	 * the true packet
+	 */
+	if (packet_number != data->packet_number) {
+		data->packet_number--;
+		result = NACK_BYTE;
+		goto end;
+	}
+
+	/*-- Read number of bytes to be written and data -----------*/
+
+	/* Read the number of bytes to be written:
+	 * Max NbrOfData = data + 1 <= 256
+	 */
+	rcv_data = stm32prog_serial_getc();
+
+	/* NbrOfData to write = data + 1 */
+	codesize = rcv_data + 0x01;
+
+	if (codesize > USART_RAM_BUFFER_SIZE) {
+		result = NACK_BYTE;
+		goto end;
+	}
+
+	/* Checksum Initialization */
+	my_xor = rcv_data;
+
+	/* UART receive data and send to Buffer */
+	counter = codesize;
+	error = stm32prog_serial_get_buffer(data->buffer, &counter);
+
+	/* read checksum */
+	if (!error) {
+		rcv = stm32prog_serial_getc_err();
+		error = !!(rcv < 0);
+		rcv_xor = rcv;
+	}
+
+	if (error) {
+		printf("transmission error on packet %d, byte %d\n",
+		       packet_number, codesize - counter);
+		/* waiting end of packet before flush & NACK */
+		mdelay(30);
+		data->packet_number--;
+		result = NACK_BYTE;
+		goto end;
+	}
+
+	/* Compute Checksum */
+	ramaddress = data->buffer;
+	for (counter = codesize; counter != 0; counter--)
+		my_xor ^= *(ramaddress++);
+
+	/* If Checksum is incorrect */
+	if (rcv_xor != my_xor) {
+		printf("checksum error on packet %d\n",
+		       packet_number);
+		/* wait to be sure that all data are received
+		 * in the FIFO before flush
+		 */
+		mdelay(30);
+		data->packet_number--;
+		result = NACK_BYTE;
+		goto end;
+	}
+
+	/* Update current position in buffer */
+	data->cursor += codesize;
+
+	if (operation == PHASE_OTP) {
+		size = data->cursor - cursor;
+		/* no header for OTP */
+		if (stm32prog_otp_write(data, cursor,
+					data->buffer, &size))
+			result = ABORT_BYTE;
+		goto end;
+	}
+
+	if (operation == PHASE_PMIC) {
+		size = data->cursor - cursor;
+		/* no header for PMIC */
+		if (stm32prog_pmic_write(data, cursor,
+					 data->buffer, &size))
+			result = ABORT_BYTE;
+		goto end;
+	}
+
+	if (cursor < BL_HEADER_SIZE) {
+		/* size = portion of header in this chunck */
+		if (data->cursor >= BL_HEADER_SIZE)
+			size = BL_HEADER_SIZE - cursor;
+		else
+			size = data->cursor - cursor;
+		memcpy((void *)((u32)(data->header_data) + cursor),
+		       data->buffer, size);
+		cursor += size;
+
+		if (cursor == BL_HEADER_SIZE) {
+			/* Check and Write the header */
+			if (stm32prog_header(data)) {
+				result = ABORT_BYTE;
+				goto end;
+			}
+		} else {
+			goto end;
+		}
+	}
+
+	if (image_header->present) {
+		if (data->cursor <= BL_HEADER_SIZE)
+			goto end;
+		/* compute checksum on payload */
+		for (i = (unsigned long)size; i < codesize; i++)
+			data->checksum += data->buffer[i];
+
+		if (data->cursor >
+		    image_header->image_length + BL_HEADER_SIZE) {
+			pr_err("expected size exceeded\n");
+			result = ABORT_BYTE;
+			goto end;
+		}
+
+		/* write data (payload) */
+		ret = stm32prog_write(data,
+				      &data->buffer[size],
+				      codesize - size);
+	} else {
+		/* write all */
+		ret = stm32prog_write(data,
+				      data->buffer,
+				      codesize);
+	}
+	if (ret)
+		result = ABORT_BYTE;
+
+end:
+	stm32prog_serial_result(result);
+}
+
+/**
+ * read_partition() - Respond to read command
+ *
+ * Read data from not volatile memory, Flash
+ *
+ * @data:		Current command context
+ */
+static void read_partition_command(struct stm32prog_data *data)
+{
+	u32 i, part_id, codesize, offset = 0, rcv_data;
+	long size;
+	u8 tmp_xor;
+	int res;
+	u8 buffer[256];
+
+	part_id = stm32prog_serial_getc();
+	tmp_xor = part_id;
+
+	offset = get_address(&tmp_xor);
+
+	rcv_data = stm32prog_serial_getc();
+	if (rcv_data != tmp_xor) {
+		pr_debug("1st checksum received = %x, computed %x\n",
+			 rcv_data, tmp_xor);
+		goto error;
+	}
+	stm32prog_serial_putc(ACK_BYTE);
+
+	/* NbrOfData to read = data + 1 */
+	rcv_data = stm32prog_serial_getc();
+	codesize = rcv_data + 0x01;
+	tmp_xor = rcv_data;
+
+	rcv_data = stm32prog_serial_getc();
+	if ((rcv_data ^ tmp_xor) != 0xFF) {
+		pr_debug("2nd checksum received = %x, computed %x\n",
+			 rcv_data, tmp_xor);
+		goto error;
+	}
+
+	pr_debug("%s : %x\n", __func__, part_id);
+	rcv_data = 0;
+	switch (part_id) {
+	case PHASE_OTP:
+		size = codesize;
+		if (!stm32prog_otp_read(data, offset, buffer, &size))
+			rcv_data = size;
+		break;
+	case PHASE_PMIC:
+		size = codesize;
+		if (!stm32prog_pmic_read(data, offset, buffer, &size))
+			rcv_data = size;
+		break;
+	default:
+		res = stm32prog_read(data, part_id, offset,
+				     buffer, codesize);
+		if (res > 0)
+			rcv_data = res;
+		break;
+	}
+	if (rcv_data > 0) {
+		stm32prog_serial_putc(ACK_BYTE);
+		/*----------- Send data to the host -----------*/
+		for (i = 0; i < rcv_data; i++)
+			stm32prog_serial_putc(buffer[i]);
+		/*----------- Send filler to the host -----------*/
+		for (; i < codesize; i++)
+			stm32prog_serial_putc(0x0);
+		return;
+	}
+	stm32prog_serial_result(ABORT_BYTE);
+	return;
+
+error:
+	stm32prog_serial_result(NACK_BYTE);
+}
+
+/* MAIN function = SERIAL LOOP ***********************************************/
+
+/**
+ * stm32prog_serial_loop() - USART bootloader Loop routine
+ *
+ * @data:		Current command context
+ * @return true if reset is needed after loop
+ */
+bool stm32prog_serial_loop(struct stm32prog_data *data)
+{
+	u32 counter = 0x0;
+	u8 command = 0x0;
+	u8 found;
+	int phase = data->phase;
+
+	/* element of cmd_func need to aligned with cmd_id[]*/
+	void (*cmd_func[NB_CMD])(struct stm32prog_data *) = {
+		/* GET_CMD_COMMAND */	get_cmd_command,
+		/* GET_VER_COMMAND */	get_version_command,
+		/* GET_ID_COMMAND */	get_id_command,
+		/* GET_PHASE_COMMAND */	get_phase_command,
+		/* RM_COMMAND */	read_memory_command,
+		/* READ_PART_COMMAND */	read_partition_command,
+		/* START_COMMAND */	start_command,
+		/* DOWNLOAD_COMMAND */	download_command
+	};
+
+	/* flush and NACK pending command received during u-boot init
+	 * request command reemit
+	 */
+	stm32prog_serial_result(NACK_BYTE);
+
+	clear_ctrlc(); /* forget any previous Control C */
+	while (!had_ctrlc()) {
+		phase = data->phase;
+
+		if (phase == PHASE_DO_RESET)
+			return true;
+
+		/* Get the user command: read first byte */
+		command = stm32prog_serial_getc();
+
+		if (command == INIT_BYTE) {
+			puts("\nConnected\n");
+			stm32prog_serial_result(ACK_BYTE);
+			continue;
+		}
+
+		found = 0;
+		for (counter = 0; counter < NB_CMD; counter++)
+			if (cmd_id[counter] == command) {
+				found = 1;
+				break;
+			}
+		if (found)
+			if ((command ^ stm32prog_serial_getc()) != 0xFF)
+				found = 0;
+		if (!found) {
+			/* wait to be sure that all data are received
+			 * in the FIFO before flush (CMD and XOR)
+			 */
+			mdelay(3);
+			stm32prog_serial_result(NACK_BYTE);
+		} else {
+			stm32prog_serial_result(ACK_BYTE);
+			cmd_func[counter](data);
+		}
+		WATCHDOG_RESET();
+	}
+
+	/* clean device */
+	if (gd->cur_serial_dev == down_serial_dev) {
+		/* restore console on uart */
+		gd->flags &= ~(GD_FLG_DISABLE_CONSOLE | GD_FLG_SILENT);
+	}
+	down_serial_dev = NULL;
+
+	return false; /* no reset after ctrlc */
+}

+ 230 - 0
arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c

@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <dfu.h>
+#include <g_dnl.h>
+#include <usb.h>
+#include <asm/arch/stm32prog.h>
+#include <asm/arch/sys_proto.h>
+#include "stm32prog.h"
+
+static int stm32prog_set_phase(struct stm32prog_data *data, u8 phase,
+			       u32 offset)
+{
+	struct stm32prog_part_t *part;
+	int i;
+
+	if (phase == data->phase) {
+		data->offset = offset;
+		data->dfu_seq = 0;
+		return 0;
+	}
+
+	/* found partition for phase */
+	for (i = 0; i < data->part_nb; i++) {
+		part = &data->part_array[i];
+		if (part->id == phase) {
+			data->cur_part = part;
+			data->phase = phase;
+			data->offset = offset;
+			data->dfu_seq = 0;
+			return 0;
+		}
+	}
+
+	return  -EINVAL;
+}
+
+static int stm32prog_cmd_write(u64 offset, void *buf, long *len)
+{
+	u8 phase;
+	u32 address;
+	u8 *pt = buf;
+	void (*entry)(void);
+	int ret;
+
+	if (*len < 5) {
+		pr_err("size not allowed\n");
+		return  -EINVAL;
+	}
+	if (offset) {
+		pr_err("invalid offset\n");
+		return  -EINVAL;
+	}
+	phase = pt[0];
+	address = (pt[1] << 24) | (pt[2] << 16) | (pt[3] << 8) | pt[4];
+	if (phase == PHASE_RESET) {
+		entry = (void *)address;
+		printf("## Starting application at 0x%x ...\n", address);
+		(*entry)();
+		printf("## Application terminated\n");
+		return 0;
+	}
+	/* set phase and offset */
+	ret = stm32prog_set_phase(stm32prog_data, phase, address);
+	if (ret)
+		pr_err("failed: %d\n", ret);
+	return ret;
+}
+
+#define PHASE_MIN_SIZE	9
+static int stm32prog_cmd_read(u64 offset, void *buf, long *len)
+{
+	u32 destination = DEFAULT_ADDRESS; /* destination address */
+	u32 dfu_offset;
+	u8 *pt_buf = buf;
+	int phase;
+	char *err_msg;
+	int length;
+
+	if (*len < PHASE_MIN_SIZE) {
+		pr_err("request exceeds allowed area\n");
+		return  -EINVAL;
+	}
+	if (offset) {
+		*len = 0; /* EOF for second request */
+		return 0;
+	}
+	phase = stm32prog_data->phase;
+	if (phase == PHASE_FLASHLAYOUT)
+		destination = STM32_DDR_BASE;
+	dfu_offset = stm32prog_data->offset;
+
+	/* mandatory header, size = PHASE_MIN_SIZE */
+	*pt_buf++ = (u8)(phase & 0xFF);
+	*pt_buf++ = (u8)(destination);
+	*pt_buf++ = (u8)(destination >> 8);
+	*pt_buf++ = (u8)(destination >> 16);
+	*pt_buf++ = (u8)(destination >> 24);
+	*pt_buf++ = (u8)(dfu_offset);
+	*pt_buf++ = (u8)(dfu_offset >> 8);
+	*pt_buf++ = (u8)(dfu_offset >> 16);
+	*pt_buf++ = (u8)(dfu_offset >> 24);
+
+	if (phase == PHASE_RESET || phase == PHASE_DO_RESET) {
+		err_msg = stm32prog_get_error(stm32prog_data);
+		length = strlen(err_msg);
+		if (length + PHASE_MIN_SIZE > *len)
+			length = *len - PHASE_MIN_SIZE;
+
+		memcpy(pt_buf, err_msg, length);
+		*len = PHASE_MIN_SIZE + length;
+		stm32prog_do_reset(stm32prog_data);
+	} else if (phase == PHASE_FLASHLAYOUT) {
+		*pt_buf++ = stm32prog_data->part_nb ? 1 : 0;
+		*len = PHASE_MIN_SIZE + 1;
+	} else {
+		*len = PHASE_MIN_SIZE;
+	}
+
+	return 0;
+}
+
+int stm32prog_write_medium_virt(struct dfu_entity *dfu, u64 offset,
+				void *buf, long *len)
+{
+	if (dfu->dev_type != DFU_DEV_VIRT)
+		return -EINVAL;
+
+	switch (dfu->data.virt.dev_num) {
+	case PHASE_CMD:
+		return stm32prog_cmd_write(offset, buf, len);
+
+	case PHASE_OTP:
+		return stm32prog_otp_write(stm32prog_data, (u32)offset,
+					   buf, len);
+
+	case PHASE_PMIC:
+		return stm32prog_pmic_write(stm32prog_data, (u32)offset,
+					    buf, len);
+	}
+	*len = 0;
+	return 0;
+}
+
+int stm32prog_read_medium_virt(struct dfu_entity *dfu, u64 offset,
+			       void *buf, long *len)
+{
+	if (dfu->dev_type != DFU_DEV_VIRT)
+		return -EINVAL;
+
+	switch (dfu->data.virt.dev_num) {
+	case PHASE_CMD:
+		return stm32prog_cmd_read(offset, buf, len);
+
+	case PHASE_OTP:
+		return stm32prog_otp_read(stm32prog_data, (u32)offset,
+					  buf, len);
+
+	case PHASE_PMIC:
+		return stm32prog_pmic_read(stm32prog_data, (u32)offset,
+					   buf, len);
+	}
+	*len = 0;
+	return 0;
+}
+
+int stm32prog_get_medium_size_virt(struct dfu_entity *dfu, u64 *size)
+{
+	if (dfu->dev_type != DFU_DEV_VIRT) {
+		*size = 0;
+		pr_debug("%s, invalid dev_type = %d\n",
+			 __func__, dfu->dev_type);
+		return -EINVAL;
+	}
+
+	switch (dfu->data.virt.dev_num) {
+	case PHASE_CMD:
+		*size = 512;
+		break;
+	case PHASE_OTP:
+		*size = OTP_SIZE;
+		break;
+	case PHASE_PMIC:
+		*size = PMIC_SIZE;
+		break;
+	}
+
+	return 0;
+}
+
+bool stm32prog_usb_loop(struct stm32prog_data *data, int dev)
+{
+	int ret;
+	bool result;
+	/* USB download gadget for STM32 Programmer */
+	char product[128];
+
+	snprintf(product, sizeof(product),
+		 "USB download gadget@Device ID /0x%03X, @Revision ID /0x%04X",
+		 get_cpu_dev(), get_cpu_rev());
+	g_dnl_set_product(product);
+
+	if (stm32prog_data->phase == PHASE_FLASHLAYOUT) {
+		ret = run_usb_dnl_gadget(dev, "usb_dnl_dfu");
+		if (ret || stm32prog_data->phase == PHASE_DO_RESET)
+			return ret;
+		/* prepare the second enumeration with the FlashLayout */
+		if (stm32prog_data->phase == PHASE_FLASHLAYOUT)
+			stm32prog_dfu_init(data);
+		/* found next selected partition */
+		stm32prog_next_phase(data);
+	}
+
+	ret = run_usb_dnl_gadget(dev, "usb_dnl_dfu");
+
+	result = !!(ret) || (stm32prog_data->phase == PHASE_DO_RESET);
+
+	g_dnl_set_product(NULL);
+
+	return result;
+}
+
+int g_dnl_get_board_bcd_device_number(int gcnum)
+{
+	pr_debug("%s\n", __func__);
+	return 0x200;
+}

+ 52 - 6
arch/arm/mach-stm32mp/cpu.c

@@ -75,6 +75,12 @@
 #define PKG_SHIFT	27
 #define PKG_MASK	GENMASK(2, 0)
 
+/*
+ * early TLB into the .data section so that it not get cleared
+ * with 16kB allignment (see TTBR0_BASE_ADDR_MASK)
+ */
+u8 early_tlb[PGTABLE_SIZE] __section(".data") __aligned(0x4000);
+
 #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
 #ifndef CONFIG_TFABOOT
 static void security_init(void)
@@ -186,6 +192,32 @@ u32 get_bootmode(void)
 		    TAMP_BOOT_MODE_SHIFT;
 }
 
+/*
+ * initialize the MMU and activate cache in SPL or in U-Boot pre-reloc stage
+ * MMU/TLB is updated in enable_caches() for U-Boot after relocation
+ * or is deactivated in U-Boot entry function start.S::cpu_init_cp15
+ */
+static void early_enable_caches(void)
+{
+	/* I-cache is already enabled in start.S: cpu_init_cp15 */
+
+	if (CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
+		return;
+
+	gd->arch.tlb_size = PGTABLE_SIZE;
+	gd->arch.tlb_addr = (unsigned long)&early_tlb;
+
+	dcache_enable();
+
+	if (IS_ENABLED(CONFIG_SPL_BUILD))
+		mmu_set_region_dcache_behaviour(STM32_SYSRAM_BASE,
+						STM32_SYSRAM_SIZE,
+						DCACHE_DEFAULT_OPTION);
+	else
+		mmu_set_region_dcache_behaviour(STM32_DDR_BASE, STM32_DDR_SIZE,
+						DCACHE_DEFAULT_OPTION);
+}
+
 /*
  * Early system init
  */
@@ -193,6 +225,8 @@ int arch_cpu_init(void)
 {
 	u32 boot_mode;
 
+	early_enable_caches();
+
 	/* early armv7 timer init: needed for polling */
 	timer_init();
 
@@ -225,7 +259,14 @@ int arch_cpu_init(void)
 
 void enable_caches(void)
 {
-	/* Enable D-cache. I-cache is already enabled in start.S */
+	/* I-cache is already enabled in start.S: icache_enable() not needed */
+
+	/* deactivate the data cache, early enabled in arch_cpu_init() */
+	dcache_disable();
+	/*
+	 * update MMU after relocation and enable the data cache
+	 * warning: the TLB location udpated in board_f.c::reserve_mmu
+	 */
 	dcache_enable();
 }
 
@@ -236,6 +277,11 @@ static u32 read_idc(void)
 	return readl(DBGMCU_IDC);
 }
 
+u32 get_cpu_dev(void)
+{
+	return (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT;
+}
+
 u32 get_cpu_rev(void)
 {
 	return (read_idc() & DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
@@ -266,11 +312,7 @@ static u32 get_cpu_rpn(void)
 
 u32 get_cpu_type(void)
 {
-	u32 id;
-
-	id = (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT;
-
-	return (id << 16) | get_cpu_rpn();
+	return (get_cpu_dev() << 16) | get_cpu_rpn();
 }
 
 /* Get Package options from OTP */
@@ -435,6 +477,10 @@ static void setup_boot_mode(void)
 		env_set("boot_device", "nand");
 		env_set("boot_instance", "0");
 		break;
+	case BOOT_FLASH_SPINAND:
+		env_set("boot_device", "spi-nand");
+		env_set("boot_instance", "0");
+		break;
 	case BOOT_FLASH_NOR:
 		env_set("boot_device", "nor");
 		env_set("boot_instance", "0");

+ 18 - 0
arch/arm/mach-stm32mp/dram_init.c

@@ -5,6 +5,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <lmb.h>
 #include <ram.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -31,3 +32,20 @@ int dram_init(void)
 
 	return 0;
 }
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	phys_addr_t reg;
+	struct lmb lmb;
+
+	/* found enough not-reserved memory to relocated U-Boot */
+	lmb_init(&lmb);
+	lmb_add(&lmb, gd->ram_base, gd->ram_size);
+	boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob);
+	reg = lmb_alloc(&lmb, CONFIG_SYS_MALLOC_LEN + total_size, SZ_4K);
+
+	if (reg)
+		return ALIGN(reg + CONFIG_SYS_MALLOC_LEN + total_size, SZ_4K);
+
+	return gd->ram_top;
+}

+ 25 - 0
arch/arm/mach-stm32mp/fdt.c

@@ -5,6 +5,7 @@
 
 #include <common.h>
 #include <fdt_support.h>
+#include <tee.h>
 #include <asm/arch/sys_proto.h>
 #include <dt-bindings/pinctrl/stm32-pinfunc.h>
 #include <linux/io.h>
@@ -218,6 +219,26 @@ static void stm32_fdt_disable(void *fdt, int offset, u32 addr,
 		       string, addr, name);
 }
 
+static void stm32_fdt_disable_optee(void *blob)
+{
+	int off, node;
+
+	off = fdt_node_offset_by_compatible(blob, -1, "linaro,optee-tz");
+	if (off >= 0 && fdtdec_get_is_enabled(blob, off))
+		fdt_status_disabled(blob, off);
+
+	/* Disabled "optee@..." reserved-memory node */
+	off = fdt_path_offset(blob, "/reserved-memory/");
+	if (off < 0)
+		return;
+	for (node = fdt_first_subnode(blob, off);
+	     node >= 0;
+	     node = fdt_next_subnode(blob, node)) {
+		if (!strncmp(fdt_get_name(blob, node, NULL), "optee@", 6))
+			fdt_status_disabled(blob, node);
+	}
+}
+
 /*
  * This function is called right before the kernel is booted. "blob" is the
  * device tree that will be passed to the kernel.
@@ -302,5 +323,9 @@ int ft_system_setup(void *blob, bd_t *bd)
 				       "st,package", pkg, false);
 	}
 
+	if (!CONFIG_IS_ENABLED(OPTEE) ||
+	    !tee_find_device(NULL, NULL, NULL, NULL))
+		stm32_fdt_disable_optee(blob);
+
 	return ret;
 }

+ 3 - 0
arch/arm/mach-stm32mp/include/mach/stm32.h

@@ -80,6 +80,9 @@ enum boot_device {
 
 	BOOT_SERIAL_USB = 0x60,
 	BOOT_SERIAL_USB_OTG = 0x62,
+
+	BOOT_FLASH_SPINAND = 0x70,
+	BOOT_FLASH_SPINAND_1 = 0x71,
 };
 
 /* TAMP registers */

+ 16 - 0
arch/arm/mach-stm32mp/include/mach/stm32prog.h

@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+ */
+
+#define STM32PROG_VIRT_FIRST_DEV_NUM		0xF1
+
+int stm32prog_write_medium_virt(struct dfu_entity *dfu, u64 offset,
+				void *buf, long *len);
+int stm32prog_read_medium_virt(struct dfu_entity *dfu, u64 offset,
+			       void *buf, long *len);
+int stm32prog_get_medium_size_virt(struct dfu_entity *dfu, u64 *size);
+
+bool stm32prog_get_tee_partitions(void);
+
+bool stm32prog_get_fsbl_nor(void);

+ 5 - 0
arch/arm/mach-stm32mp/include/mach/sys_proto.h

@@ -20,6 +20,11 @@
 /* return CPU_STMP32MP...Xxx constants */
 u32 get_cpu_type(void);
 
+#define CPU_DEV_STM32MP15	0x500
+
+/* return CPU_DEV constants */
+u32 get_cpu_dev(void);
+
 #define CPU_REVA	0x1000
 #define CPU_REVB	0x2000
 #define CPU_REVZ	0x2001

+ 35 - 3
arch/arm/mach-stm32mp/spl.c

@@ -4,6 +4,7 @@
  */
 
 #include <common.h>
+#include <cpu_func.h>
 #include <dm.h>
 #include <hang.h>
 #include <spl.h>
@@ -39,6 +40,8 @@ u32 spl_boot_device(void)
 		return BOOT_DEVICE_NAND;
 	case BOOT_FLASH_NOR_QSPI:
 		return BOOT_DEVICE_SPI;
+	case BOOT_FLASH_SPINAND_1:
+		return BOOT_DEVICE_NONE; /* SPINAND not supported in SPL */
 	}
 
 	return BOOT_DEVICE_MMC1;
@@ -76,6 +79,11 @@ void spl_display_print(void)
 }
 #endif
 
+__weak int board_early_init_f(void)
+{
+	return 0;
+}
+
 void board_init_f(ulong dummy)
 {
 	struct udevice *dev;
@@ -92,27 +100,51 @@ void board_init_f(ulong dummy)
 	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
 	if (ret) {
 		debug("Clock init failed: %d\n", ret);
-		return;
+		hang();
 	}
 
 	ret = uclass_get_device(UCLASS_RESET, 0, &dev);
 	if (ret) {
 		debug("Reset init failed: %d\n", ret);
-		return;
+		hang();
 	}
 
 	ret = uclass_get_device(UCLASS_PINCTRL, 0, &dev);
 	if (ret) {
 		debug("%s: Cannot find pinctrl device\n", __func__);
-		return;
+		hang();
 	}
 
 	/* enable console uart printing */
 	preloader_console_init();
 
+	ret = board_early_init_f();
+	if (ret) {
+		debug("board_early_init_f() failed: %d\n", ret);
+		hang();
+	}
+
 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
 	if (ret) {
 		printf("DRAM init failed: %d\n", ret);
 		hang();
 	}
+
+	/*
+	 * activate cache on DDR only when DDR is fully initialized
+	 * to avoid speculative access and issue in get_ram_size()
+	 */
+	if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
+		mmu_set_region_dcache_behaviour(STM32_DDR_BASE, STM32_DDR_SIZE,
+						DCACHE_DEFAULT_OPTION);
+}
+
+void spl_board_prepare_for_boot(void)
+{
+	dcache_disable();
+}
+
+void spl_board_prepare_for_boot_linux(void)
+{
+	dcache_disable();
 }

+ 2 - 1
board/dhelectronics/dh_stm32mp1/Kconfig

@@ -7,7 +7,7 @@ config SYS_VENDOR
 	default "dhelectronics"
 
 config SYS_CONFIG_NAME
-	default "stm32mp1"
+	default "dh_stm32mp1"
 
 config ENV_SECT_SIZE
 	default 0x10000 if ENV_IS_IN_SPI_FLASH
@@ -18,4 +18,5 @@ config ENV_OFFSET
 config ENV_OFFSET_REDUND
 	default 0x1F0000 if ENV_IS_IN_SPI_FLASH
 
+source "board/st/common/Kconfig"
 endif

+ 1 - 0
board/dhelectronics/dh_stm32mp1/MAINTAINERS

@@ -4,4 +4,5 @@ S:	Maintained
 F:	arch/arm/dts/stm32mp15xx-dhcom*
 F:	board/dhelectronics/dh_stm32mp1/
 F:	configs/stm32mp15_dhcom_basic_defconfig
+F:	configs/stm32mp15_dhcor_basic_defconfig
 F:	include/configs/stm32mp1.h

+ 3 - 0
board/dhelectronics/dh_stm32mp1/Makefile

@@ -8,3 +8,6 @@ obj-y += ../../st/stm32mp1/spl.o
 endif
 
 obj-y += ../../st/stm32mp1/board.o board.o
+
+obj-$(CONFIG_SYS_MTDPARTS_RUNTIME) += ../../st/common/stm32mp_mtdparts.o
+obj-$(CONFIG_SET_DFU_ALT_INFO) += ../../st/common/stm32mp_dfu.o

+ 90 - 142
board/dhelectronics/dh_stm32mp1/board.c

@@ -116,9 +116,7 @@ int checkboard(void)
 	const char *fdt_compat;
 	int fdt_compat_len;
 
-	if (IS_ENABLED(CONFIG_STM32MP1_OPTEE))
-		mode = "trusted with OP-TEE";
-	else if (IS_ENABLED(CONFIG_TFABOOT))
+	if (IS_ENABLED(CONFIG_TFABOOT))
 		mode = "trusted";
 	else
 		mode = "basic";
@@ -133,6 +131,89 @@ int checkboard(void)
 	return 0;
 }
 
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+static u8 brdcode __section("data");
+static u8 ddr3code __section("data");
+static u8 somcode __section("data");
+
+static void board_get_coding_straps(void)
+{
+	struct gpio_desc gpio[4];
+	ofnode node;
+	int i, ret;
+
+	node = ofnode_path("/config");
+	if (!ofnode_valid(node)) {
+		printf("%s: no /config node?\n", __func__);
+		return;
+	}
+
+	brdcode = 0;
+	ddr3code = 0;
+	somcode = 0;
+
+	ret = gpio_request_list_by_name_nodev(node, "dh,som-coding-gpios",
+					      gpio, ARRAY_SIZE(gpio),
+					      GPIOD_IS_IN);
+	for (i = 0; i < ret; i++)
+		somcode |= !!dm_gpio_get_value(&(gpio[i])) << i;
+
+	ret = gpio_request_list_by_name_nodev(node, "dh,ddr3-coding-gpios",
+					      gpio, ARRAY_SIZE(gpio),
+					      GPIOD_IS_IN);
+	for (i = 0; i < ret; i++)
+		ddr3code |= !!dm_gpio_get_value(&(gpio[i])) << i;
+
+	ret = gpio_request_list_by_name_nodev(node, "dh,board-coding-gpios",
+					      gpio, ARRAY_SIZE(gpio),
+					      GPIOD_IS_IN);
+	for (i = 0; i < ret; i++)
+		brdcode |= !!dm_gpio_get_value(&(gpio[i])) << i;
+
+	printf("Code:  SoM:rev=%d,ddr3=%d Board:rev=%d\n",
+		somcode, ddr3code, brdcode);
+}
+
+int board_stm32mp1_ddr_config_name_match(struct udevice *dev,
+					 const char *name)
+{
+	if (ddr3code == 1 &&
+	    !strcmp(name, "st,ddr3l-dhsom-1066-888-bin-g-2x1gb-533mhz"))
+		return 0;
+
+	if (ddr3code == 2 &&
+	    !strcmp(name, "st,ddr3l-dhsom-1066-888-bin-g-2x2gb-533mhz"))
+		return 0;
+
+	if (ddr3code == 3 &&
+	    !strcmp(name, "st,ddr3l-dhsom-1066-888-bin-g-2x4gb-533mhz"))
+		return 0;
+
+	return -EINVAL;
+}
+
+int board_early_init_f(void)
+{
+	board_get_coding_straps();
+
+	return 0;
+}
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+	char test[20];
+
+	snprintf(test, sizeof(test), "somrev%d_boardrev%d", somcode, brdcode);
+
+	if (!strcmp(name, test))
+		return 0;
+
+	return -EINVAL;
+}
+#endif
+#endif
+
 static void board_key_check(void)
 {
 #if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
@@ -478,6 +559,12 @@ int board_late_init(void)
 	if (!strcmp(boot_device, "serial") || !strcmp(boot_device, "usb"))
 		env_set("bootdelay", "0");
 
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+	env_set_ulong("dh_som_rev", somcode);
+	env_set_ulong("dh_board_rev", brdcode);
+	env_set_ulong("dh_ddr3_code", ddr3code);
+#endif
+
 	return 0;
 }
 
@@ -570,95 +657,6 @@ enum env_location env_get_location(enum env_operation op, int prio)
 #endif
 }
 
-#ifdef CONFIG_SYS_MTDPARTS_RUNTIME
-
-#define MTDPARTS_LEN		256
-#define MTDIDS_LEN		128
-
-/**
- * The mtdparts_nand0 and mtdparts_nor0 variable tends to be long.
- * If we need to access it before the env is relocated, then we need
- * to use our own stack buffer. gd->env_buf will be too small.
- *
- * @param buf temporary buffer pointer MTDPARTS_LEN long
- * @return mtdparts variable string, NULL if not found
- */
-static const char *env_get_mtdparts(const char *str, char *buf)
-{
-	if (gd->flags & GD_FLG_ENV_READY)
-		return env_get(str);
-	if (env_get_f(str, buf, MTDPARTS_LEN) != -1)
-		return buf;
-
-	return NULL;
-}
-
-/**
- * update the variables "mtdids" and "mtdparts" with content of mtdparts_<dev>
- */
-static void board_get_mtdparts(const char *dev,
-			       char *mtdids,
-			       char *mtdparts)
-{
-	char env_name[32] = "mtdparts_";
-	char tmp_mtdparts[MTDPARTS_LEN];
-	const char *tmp;
-
-	/* name of env variable to read = mtdparts_<dev> */
-	strcat(env_name, dev);
-	tmp = env_get_mtdparts(env_name, tmp_mtdparts);
-	if (tmp) {
-		/* mtdids: "<dev>=<dev>, ...." */
-		if (mtdids[0] != '\0')
-			strcat(mtdids, ",");
-		strcat(mtdids, dev);
-		strcat(mtdids, "=");
-		strcat(mtdids, dev);
-
-		/* mtdparts: "mtdparts=<dev>:<mtdparts_<dev>>;..." */
-		if (mtdparts[0] != '\0')
-			strncat(mtdparts, ";", MTDPARTS_LEN);
-		else
-			strcat(mtdparts, "mtdparts=");
-		strncat(mtdparts, dev, MTDPARTS_LEN);
-		strncat(mtdparts, ":", MTDPARTS_LEN);
-		strncat(mtdparts, tmp, MTDPARTS_LEN);
-	}
-}
-
-void board_mtdparts_default(const char **mtdids, const char **mtdparts)
-{
-	struct udevice *dev;
-	static char parts[3 * MTDPARTS_LEN + 1];
-	static char ids[MTDIDS_LEN + 1];
-	static bool mtd_initialized;
-
-	if (mtd_initialized) {
-		*mtdids = ids;
-		*mtdparts = parts;
-		return;
-	}
-
-	memset(parts, 0, sizeof(parts));
-	memset(ids, 0, sizeof(ids));
-
-	/* probe all MTD devices */
-	for (uclass_first_device(UCLASS_MTD, &dev);
-	     dev;
-	     uclass_next_device(&dev)) {
-		pr_debug("mtd device = %s\n", dev->name);
-	}
-
-	if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev))
-		board_get_mtdparts("nor0", ids, parts);
-
-	mtd_initialized = true;
-	*mtdids = ids;
-	*mtdparts = parts;
-	debug("%s:mtdids=%s & mtdparts=%s\n", __func__, ids, parts);
-}
-#endif
-
 #if defined(CONFIG_OF_BOARD_SETUP)
 int ft_board_setup(void *blob, bd_t *bd)
 {
@@ -666,56 +664,6 @@ int ft_board_setup(void *blob, bd_t *bd)
 }
 #endif
 
-#ifdef CONFIG_SET_DFU_ALT_INFO
-#define DFU_ALT_BUF_LEN SZ_1K
-
-static void board_get_alt_info(const char *dev, char *buff)
-{
-	char var_name[32] = "dfu_alt_info_";
-	int ret;
-
-	ALLOC_CACHE_ALIGN_BUFFER(char, tmp_alt, DFU_ALT_BUF_LEN);
-
-	/* name of env variable to read = dfu_alt_info_<dev> */
-	strcat(var_name, dev);
-	ret = env_get_f(var_name, tmp_alt, DFU_ALT_BUF_LEN);
-	if (ret) {
-		if (buff[0] != '\0')
-			strcat(buff, "&");
-		strncat(buff, tmp_alt, DFU_ALT_BUF_LEN);
-	}
-}
-
-void set_dfu_alt_info(char *interface, char *devstr)
-{
-	struct udevice *dev;
-
-	ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
-
-	if (env_get("dfu_alt_info"))
-		return;
-
-	memset(buf, 0, sizeof(buf));
-
-	/* probe all MTD devices */
-	mtd_probe_devices();
-
-	board_get_alt_info("ram", buf);
-
-	if (!uclass_get_device(UCLASS_MMC, 0, &dev))
-		board_get_alt_info("mmc0", buf);
-
-	if (!uclass_get_device(UCLASS_MMC, 1, &dev))
-		board_get_alt_info("mmc1", buf);
-
-	if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev))
-		board_get_alt_info("nor0", buf);
-
-	env_set("dfu_alt_info", buf);
-	puts("DFU alt info setting: done\n");
-}
-#endif
-
 static void board_copro_image_process(ulong fw_image, size_t fw_size)
 {
 	int ret, id = 0; /* Copro id fixed to 0 as only one coproc on mp1 */

+ 39 - 0
board/dhelectronics/dh_stm32mp1/u-boot-dhcom.its

@@ -0,0 +1,39 @@
+/dts-v1/;
+
+/ {
+	description = "U-Boot mainline";
+	#address-cells = <1>;
+
+	images {
+		uboot {
+			description = "U-Boot (32-bit)";
+			data = /incbin/("u-boot-nodtb.bin");
+			type = "standalone";
+			os = "U-Boot";
+			arch = "arm";
+			compression = "none";
+			load = <0xc0100000>;
+			entry = <0xc0100000>;
+		};
+
+		fdt-1 {
+			description = ".dtb";
+			data = /incbin/("arch/arm/dts/stm32mp15xx-dhcom-pdk2.dtb");
+			type = "flat_dt";
+			arch = "arm";
+			compression = "none";
+		};
+	};
+
+	configurations {
+		default = "config-1";
+
+		config-1 {
+			description = "somrev0_boardrev0"; /* SoM+board model */
+			loadables = "uboot";
+			fdt = "fdt-1";
+		};
+
+		/* Add 587-100..587-400 with fdt-2..fdt-4 here */
+	};
+};

+ 39 - 0
board/dhelectronics/dh_stm32mp1/u-boot-dhcor.its

@@ -0,0 +1,39 @@
+/dts-v1/;
+
+/ {
+	description = "U-Boot mainline";
+	#address-cells = <1>;
+
+	images {
+		uboot {
+			description = "U-Boot (32-bit)";
+			data = /incbin/("u-boot-nodtb.bin");
+			type = "standalone";
+			os = "U-Boot";
+			arch = "arm";
+			compression = "none";
+			load = <0xc0100000>;
+			entry = <0xc0100000>;
+		};
+
+		fdt-1 {
+			description = ".dtb";
+			data = /incbin/("arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtb");
+			type = "flat_dt";
+			arch = "arm";
+			compression = "none";
+		};
+	};
+
+	configurations {
+		default = "config-1";
+
+		config-1 {
+			description = "somrev0_boardrev1"; /* SoM+board model */
+			loadables = "uboot";
+			fdt = "fdt-1";
+		};
+
+		/* Add 586-200..586-400 with fdt-2..fdt-4 here */
+	};
+};

+ 64 - 0
board/st/common/Kconfig

@@ -5,3 +5,67 @@ config CMD_STBOARD
 	help
 	  This compile the stboard command to
 	  read and write the board in the OTP.
+
+config MTDPARTS_NAND0_BOOT
+	string "mtd boot partitions for nand0"
+	default "2m(fsbl),2m(ssbl1),2m(ssbl2)"
+	depends on SYS_MTDPARTS_RUNTIME && ARCH_STM32MP
+	help
+	  This define the partitions of nand0 used to build mtparts dynamically
+	  for boot from nand0.
+	  Each partition need to be aligned with the device erase block size,
+	  512KB is the max size for the NAND supported by stm32mp1 platform.
+
+config MTDPARTS_NAND0_TEE
+	string "mtd tee partitions for nand0"
+	default "512k(teeh),512k(teed),512k(teex)"
+	depends on SYS_MTDPARTS_RUNTIME && ARCH_STM32MP
+	help
+	  This define the tee partitions added in mtparts dynamically
+	  when tee is supported with boot from nand0.
+	  Each partition need to be aligned with the device erase block size,
+	  512KB is the max size for the NAND supported by stm32mp1 platform.
+
+config MTDPARTS_NOR0_BOOT
+	string "mtd boot partitions for nor0"
+	default "256k(fsbl1),256k(fsbl2),2m(ssbl),512k(u-boot-env)"
+	depends on SYS_MTDPARTS_RUNTIME && ARCH_STM32MP
+	help
+	  This define the partitions of nand0 used to build mtparts dynamically
+	  for boot from nor0.
+	  Each partition need to be aligned with the device erase block size,
+	  with 256KB we support all the NOR.
+	  U-Boot env partition (512kB) use 2 erase block for redundancy.
+
+config MTDPARTS_NOR0_TEE
+	string "mtd tee partitions for nor0"
+	default "256k(teeh),256k(teed),256k(teex)"
+	depends on SYS_MTDPARTS_RUNTIME && ARCH_STM32MP
+	help
+	  This define the tee partitions added in mtparts dynamically
+	  when tee is supported with boot from nor0.
+
+config MTDPARTS_SPINAND0_BOOT
+	string "mtd boot partitions for spi-nand0"
+	default "2m(fsbl),2m(ssbl1),2m(ssbl2)"
+	depends on SYS_MTDPARTS_RUNTIME && ARCH_STM32MP
+	help
+	  This define the partitions of nand0 used to build mtparts dynamically
+	  for boot from spi-nand0,
+	  512KB is the max size for the NAND supported by stm32mp1 platform.
+
+config MTDPARTS_SPINAND0_TEE
+	string "mtd tee partitions for spi-nand0"
+	default "512k(teeh),512k(teed),512k(teex)"
+	depends on SYS_MTDPARTS_RUNTIME && ARCH_STM32MP
+	help
+	  This define the tee partitions added in mtparts dynamically
+	  when tee is supported with boot from spi-nand0,
+	  512KB is the max size for the NAND supported by stm32mp1 platform.
+
+config DFU_ALT_RAM0
+	string "dfu for ram0"
+	default "uImage ram 0xc2000000 0x2000000;devicetree.dtb ram 0xc4000000 0x100000;uramdisk.image.gz ram 0xc4400000 0x10000000"
+	depends on ARCH_STM32MP && SET_DFU_ALT_INFO
+	help
+	  This defines the partitions of ram used to build dfu dynamically.

+ 5 - 0
board/st/common/Makefile

@@ -4,3 +4,8 @@
 #
 
 obj-$(CONFIG_CMD_STBOARD) += cmd_stboard.o
+
+ifeq ($(CONFIG_ARCH_STM32MP),y)
+obj-$(CONFIG_SYS_MTDPARTS_RUNTIME) += stm32mp_mtdparts.o
+obj-$(CONFIG_SET_DFU_ALT_INFO) += stm32mp_dfu.o
+endif

+ 245 - 0
board/st/common/stm32mp_dfu.c

@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <dfu.h>
+#include <env.h>
+#include <memalign.h>
+#include <misc.h>
+#include <mtd.h>
+#include <mtd_node.h>
+#include <asm/arch/stm32prog.h>
+
+#define DFU_ALT_BUF_LEN SZ_1K
+
+static void board_get_alt_info_mmc(struct udevice *dev, char *buf)
+{
+	disk_partition_t info;
+	int p, len, devnum;
+	bool first = true;
+	const char *name;
+	struct mmc *mmc;
+	struct blk_desc *desc;
+
+	mmc = mmc_get_mmc_dev(dev);
+	if (!mmc)
+		return;
+
+	if (mmc_init(mmc))
+		return;
+
+	desc = mmc_get_blk_desc(mmc);
+	if (!desc)
+		return;
+
+	name = blk_get_if_type_name(desc->if_type);
+	devnum = desc->devnum;
+	len = strlen(buf);
+
+	if (buf[0] != '\0')
+		len += snprintf(buf + len,
+				DFU_ALT_BUF_LEN - len, "&");
+	len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
+			 "%s %d=", name, devnum);
+
+	if (IS_MMC(mmc) && mmc->capacity_boot) {
+		len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
+				"%s%d_boot1 raw 0x0 0x%llx mmcpart 1;",
+				name, devnum, mmc->capacity_boot);
+		len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
+				"%s%d_boot2 raw 0x0 0x%llx mmcpart 2",
+				name, devnum, mmc->capacity_boot);
+		first = false;
+	}
+
+	for (p = 1; p < MAX_SEARCH_PARTITIONS; p++) {
+		if (part_get_info(desc, p, &info))
+			continue;
+		if (!first)
+			len += snprintf(buf + len, DFU_ALT_BUF_LEN - len, ";");
+		first = false;
+		len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
+				"%s%d_%s part %d %d",
+				name, devnum, info.name, devnum, p);
+	}
+}
+
+static void board_get_alt_info_mtd(struct mtd_info *mtd, char *buf)
+{
+	struct mtd_info *part;
+	bool first = true;
+	const char *name;
+	int len, partnum = 0;
+
+	name = mtd->name;
+	len = strlen(buf);
+
+	if (buf[0] != '\0')
+		len += snprintf(buf + len, DFU_ALT_BUF_LEN - len, "&");
+	len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
+			"mtd %s=", name);
+
+	len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
+			"%s raw 0x0 0x%llx ",
+			name, mtd->size);
+
+	list_for_each_entry(part, &mtd->partitions, node) {
+		partnum++;
+		if (!first)
+			len += snprintf(buf + len, DFU_ALT_BUF_LEN - len, ";");
+		first = false;
+
+		len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
+				"%s_%s part %d",
+				name, part->name, partnum);
+	}
+}
+
+void set_dfu_alt_info(char *interface, char *devstr)
+{
+	struct udevice *dev;
+	struct mtd_info *mtd;
+
+	ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
+
+	if (env_get("dfu_alt_info"))
+		return;
+
+	memset(buf, 0, sizeof(buf));
+
+	snprintf(buf, DFU_ALT_BUF_LEN,
+		 "ram 0=%s", CONFIG_DFU_ALT_RAM0);
+
+	if (!uclass_get_device(UCLASS_MMC, 0, &dev))
+		board_get_alt_info_mmc(dev, buf);
+
+	if (!uclass_get_device(UCLASS_MMC, 1, &dev))
+		board_get_alt_info_mmc(dev, buf);
+
+	if (CONFIG_IS_ENABLED(MTD)) {
+		/* probe all MTD devices */
+		mtd_probe_devices();
+
+		/* probe SPI flash device on a bus */
+		if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev)) {
+			mtd = get_mtd_device_nm("nor0");
+			if (!IS_ERR_OR_NULL(mtd))
+				board_get_alt_info_mtd(mtd, buf);
+		}
+
+		mtd = get_mtd_device_nm("nand0");
+		if (!IS_ERR_OR_NULL(mtd))
+			board_get_alt_info_mtd(mtd, buf);
+
+		mtd = get_mtd_device_nm("spi-nand0");
+		if (!IS_ERR_OR_NULL(mtd))
+			board_get_alt_info_mtd(mtd, buf);
+	}
+
+#ifdef CONFIG_DFU_VIRT
+	strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN);
+
+	if (IS_ENABLED(CONFIG_PMIC_STPMIC1))
+		strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN);
+#endif
+
+	env_set("dfu_alt_info", buf);
+	puts("DFU alt info setting: done\n");
+}
+
+#if CONFIG_IS_ENABLED(DFU_VIRT)
+#include <dfu.h>
+#include <power/stpmic1.h>
+
+static int dfu_otp_read(u64 offset, u8 *buffer, long *size)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+					  DM_GET_DRIVER(stm32mp_bsec),
+					  &dev);
+	if (ret)
+		return ret;
+
+	ret = misc_read(dev, offset + STM32_BSEC_OTP_OFFSET, buffer, *size);
+	if (ret >= 0) {
+		*size = ret;
+		ret = 0;
+	}
+
+	return 0;
+}
+
+static int dfu_pmic_read(u64 offset, u8 *buffer, long *size)
+{
+	int ret;
+#ifdef CONFIG_PMIC_STPMIC1
+	struct udevice *dev;
+
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+					  DM_GET_DRIVER(stpmic1_nvm),
+					  &dev);
+	if (ret)
+		return ret;
+
+	ret = misc_read(dev, 0xF8 + offset, buffer, *size);
+	if (ret >= 0) {
+		*size = ret;
+		ret = 0;
+	}
+	if (ret == -EACCES) {
+		*size = 0;
+		ret = 0;
+	}
+#else
+	pr_err("PMIC update not supported");
+	ret = -EOPNOTSUPP;
+#endif
+
+	return ret;
+}
+
+int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset,
+			 void *buf, long *len)
+{
+	switch (dfu->data.virt.dev_num) {
+	case 0x0:
+		return dfu_otp_read(offset, buf, len);
+	case 0x1:
+		return dfu_pmic_read(offset, buf, len);
+	}
+
+	if (CONFIG_IS_ENABLED(CMD_STM32PROG) &&
+	    dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
+		return stm32prog_read_medium_virt(dfu, offset, buf, len);
+
+	*len = 0;
+	return 0;
+}
+
+int dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset,
+			  void *buf, long *len)
+{
+	if (CONFIG_IS_ENABLED(CMD_STM32PROG) &&
+	    dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
+		return stm32prog_write_medium_virt(dfu, offset, buf, len);
+
+	return -EOPNOTSUPP;
+}
+
+int __weak dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size)
+{
+	if (CONFIG_IS_ENABLED(CMD_STM32PROG) &&
+	    dfu->data.virt.dev_num >= STM32PROG_VIRT_FIRST_DEV_NUM)
+		return stm32prog_get_medium_size_virt(dfu, size);
+
+	*size = SZ_1K;
+
+	return 0;
+}
+
+#endif

+ 167 - 0
board/st/common/stm32mp_mtdparts.c

@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <dfu.h>
+#include <dm.h>
+#include <env.h>
+#include <env_internal.h>
+#include <mtd.h>
+#include <mtd_node.h>
+#include <tee.h>
+#include <asm/arch/stm32prog.h>
+#include <asm/arch/sys_proto.h>
+
+#define MTDPARTS_LEN		256
+#define MTDIDS_LEN		128
+
+/*
+ * Get a global data pointer
+ */
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * update the variables "mtdids" and "mtdparts" with boot, tee and user strings
+ */
+static void board_set_mtdparts(const char *dev,
+			       char *mtdids,
+			       char *mtdparts,
+			       const char *boot,
+			       const char *tee,
+			       const char *user)
+{
+	/* mtdids: "<dev>=<dev>, ...." */
+	if (mtdids[0] != '\0')
+		strcat(mtdids, ",");
+	strcat(mtdids, dev);
+	strcat(mtdids, "=");
+	strcat(mtdids, dev);
+
+	/* mtdparts: "mtdparts=<dev>:<mtdparts_<dev>>;..." */
+	if (mtdparts[0] != '\0')
+		strncat(mtdparts, ";", MTDPARTS_LEN);
+	else
+		strcat(mtdparts, "mtdparts=");
+
+	strncat(mtdparts, dev, MTDPARTS_LEN);
+	strncat(mtdparts, ":", MTDPARTS_LEN);
+
+	if (boot) {
+		strncat(mtdparts, boot, MTDPARTS_LEN);
+		strncat(mtdparts, ",", MTDPARTS_LEN);
+	}
+
+	if (tee) {
+		strncat(mtdparts, tee, MTDPARTS_LEN);
+		strncat(mtdparts, ",", MTDPARTS_LEN);
+	}
+
+	strncat(mtdparts, user, MTDPARTS_LEN);
+}
+
+void board_mtdparts_default(const char **mtdids, const char **mtdparts)
+{
+	struct mtd_info *mtd;
+	struct udevice *dev;
+	static char parts[3 * MTDPARTS_LEN + 1];
+	static char ids[MTDIDS_LEN + 1];
+	static bool mtd_initialized;
+	bool tee, nor, nand, spinand, serial;
+
+	if (mtd_initialized) {
+		*mtdids = ids;
+		*mtdparts = parts;
+		return;
+	}
+
+	tee = false;
+	nor = false;
+	nand = false;
+	spinand = false;
+	serial = false;
+
+	switch (get_bootmode() & TAMP_BOOT_DEVICE_MASK) {
+	case BOOT_SERIAL_UART:
+	case BOOT_SERIAL_USB:
+		serial = true;
+		if (CONFIG_IS_ENABLED(CMD_STM32PROG)) {
+			tee = stm32prog_get_tee_partitions();
+			nor = stm32prog_get_fsbl_nor();
+		}
+		nand = true;
+		spinand = true;
+		break;
+	case BOOT_FLASH_NAND:
+		nand = true;
+		break;
+	case BOOT_FLASH_SPINAND:
+		spinand = true;
+		break;
+	case BOOT_FLASH_NOR:
+		nor = true;
+		break;
+	default:
+		break;
+	}
+
+	if (!serial && CONFIG_IS_ENABLED(OPTEE) &&
+	    tee_find_device(NULL, NULL, NULL, NULL))
+		tee = true;
+
+	memset(parts, 0, sizeof(parts));
+	memset(ids, 0, sizeof(ids));
+
+	/* probe all MTD devices */
+	for (uclass_first_device(UCLASS_MTD, &dev);
+	     dev;
+	     uclass_next_device(&dev)) {
+		pr_debug("mtd device = %s\n", dev->name);
+	}
+
+	if (nor || nand) {
+		mtd = get_mtd_device_nm("nand0");
+		if (!IS_ERR_OR_NULL(mtd)) {
+			const char *mtd_boot = CONFIG_MTDPARTS_NAND0_BOOT;
+			const char *mtd_tee = CONFIG_MTDPARTS_NAND0_TEE;
+
+			board_set_mtdparts("nand0", ids, parts,
+					   !nor ? mtd_boot : NULL,
+					   !nor && tee ? mtd_tee : NULL,
+					   "-(UBI)");
+			put_mtd_device(mtd);
+		}
+	}
+
+	if (nor || spinand) {
+		mtd = get_mtd_device_nm("spi-nand0");
+		if (!IS_ERR_OR_NULL(mtd)) {
+			const char *mtd_boot = CONFIG_MTDPARTS_SPINAND0_BOOT;
+			const char *mtd_tee = CONFIG_MTDPARTS_SPINAND0_TEE;
+
+			board_set_mtdparts("spi-nand0", ids, parts,
+					   !nor ? mtd_boot : NULL,
+					   !nor && tee ? mtd_tee : NULL,
+					   "-(UBI)");
+			put_mtd_device(mtd);
+		}
+	}
+
+	if (nor) {
+		if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev)) {
+			const char *mtd_boot = CONFIG_MTDPARTS_NOR0_BOOT;
+			const char *mtd_tee = CONFIG_MTDPARTS_NOR0_TEE;
+
+			board_set_mtdparts("nor0", ids, parts,
+					   mtd_boot,
+					   tee ? mtd_tee : NULL,
+					   "-(nor_user)");
+		}
+	}
+
+	mtd_initialized = true;
+	*mtdids = ids;
+	*mtdparts = parts;
+	debug("%s:mtdids=%s & mtdparts=%s\n", __func__, ids, parts);
+}

+ 0 - 1
board/st/stm32mp1/MAINTAINERS

@@ -6,6 +6,5 @@ S:	Maintained
 F:	arch/arm/dts/stm32mp15*
 F:	board/st/stm32mp1/
 F:	configs/stm32mp15_basic_defconfig
-F:	configs/stm32mp15_optee_defconfig
 F:	configs/stm32mp15_trusted_defconfig
 F:	include/configs/stm32mp1.h

+ 78 - 279
board/st/stm32mp1/stm32mp1.c

@@ -7,7 +7,6 @@
 #include <bootm.h>
 #include <clk.h>
 #include <config.h>
-#include <dfu.h>
 #include <dm.h>
 #include <env.h>
 #include <env_internal.h>
@@ -18,9 +17,7 @@
 #include <init.h>
 #include <led.h>
 #include <malloc.h>
-#include <memalign.h>
 #include <misc.h>
-#include <mtd.h>
 #include <mtd_node.h>
 #include <netdev.h>
 #include <phy.h>
@@ -35,6 +32,7 @@
 #include <asm/arch/sys_proto.h>
 #include <jffs2/load_kernel.h>
 #include <linux/err.h>
+#include <linux/iopoll.h>
 #include <power/regulator.h>
 #include <usb/dwc2_udc.h>
 
@@ -90,9 +88,7 @@ int checkboard(void)
 	const char *fdt_compat;
 	int fdt_compat_len;
 
-	if (IS_ENABLED(CONFIG_STM32MP1_OPTEE))
-		mode = "trusted with OP-TEE";
-	else if (IS_ENABLED(TFABOOT))
+	if (IS_ENABLED(CONFIG_TFABOOT))
 		mode = "trusted";
 	else
 		mode = "basic";
@@ -260,7 +256,6 @@ int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
 
 #endif /* CONFIG_USB_GADGET */
 
-#ifdef CONFIG_LED
 static int get_led(struct udevice **dev, char *led_string)
 {
 	char *led_name;
@@ -286,6 +281,9 @@ static int setup_led(enum led_state_t cmd)
 	struct udevice *dev;
 	int ret;
 
+	if (!CONFIG_IS_ENABLED(LED))
+		return 0;
+
 	ret = get_led(&dev, "u-boot,boot-led");
 	if (ret)
 		return ret;
@@ -293,31 +291,29 @@ static int setup_led(enum led_state_t cmd)
 	ret = led_set_state(dev, cmd);
 	return ret;
 }
-#endif
 
 static void __maybe_unused led_error_blink(u32 nb_blink)
 {
-#ifdef CONFIG_LED
 	int ret;
 	struct udevice *led;
 	u32 i;
-#endif
 
 	if (!nb_blink)
 		return;
 
-#ifdef CONFIG_LED
-	ret = get_led(&led, "u-boot,error-led");
-	if (!ret) {
-		/* make u-boot,error-led blinking */
-		/* if U32_MAX and 125ms interval, for 17.02 years */
-		for (i = 0; i < 2 * nb_blink; i++) {
-			led_set_state(led, LEDST_TOGGLE);
-			mdelay(125);
-			WATCHDOG_RESET();
+	if (CONFIG_IS_ENABLED(LED)) {
+		ret = get_led(&led, "u-boot,error-led");
+		if (!ret) {
+			/* make u-boot,error-led blinking */
+			/* if U32_MAX and 125ms interval, for 17.02 years */
+			for (i = 0; i < 2 * nb_blink; i++) {
+				led_set_state(led, LEDST_TOGGLE);
+				mdelay(125);
+				WATCHDOG_RESET();
+			}
+			led_set_state(led, LEDST_ON);
 		}
 	}
-#endif
 
 	/* infinite: the boot process must be stopped */
 	if (nb_blink == U32_MAX)
@@ -435,7 +431,7 @@ static int board_check_usb_power(void)
 	if (max_uV > USB_WARNING_LOW_THRESHOLD_UV &&
 	    max_uV <= USB_START_LOW_THRESHOLD_UV &&
 	    min_uV <= USB_LOW_THRESHOLD_UV) {
-		pr_err("*       WARNING 1.5mA power supply detected        *\n");
+		pr_err("*       WARNING 1.5A power supply detected        *\n");
 		nb_blink = 3;
 	}
 
@@ -468,10 +464,10 @@ static void sysconf_init(void)
 	struct udevice *pwr_dev;
 	struct udevice *pwr_reg;
 	struct udevice *dev;
-	int ret;
 	u32 otp = 0;
 #endif
-	u32 bootr;
+	int ret;
+	u32 bootr, val;
 
 	syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
 
@@ -548,8 +544,15 @@ static void sysconf_init(void)
 	 */
 	writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR);
 
-	while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY))
-		;
+	/* poll until ready (1s timeout) */
+	ret = readl_poll_timeout(syscfg + SYSCFG_CMPCR, val,
+				 val & SYSCFG_CMPCR_READY,
+				 1000000);
+	if (ret) {
+		pr_err("SYSCFG: I/O compensation failed, timeout.\n");
+		led_error_blink(10);
+	}
+
 	clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
 #endif
 }
@@ -621,6 +624,38 @@ static bool board_is_dk2(void)
 }
 #endif
 
+static bool board_is_ev1(void)
+{
+	if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
+	    (of_machine_is_compatible("st,stm32mp157a-ev1") ||
+	     of_machine_is_compatible("st,stm32mp157c-ev1") ||
+	     of_machine_is_compatible("st,stm32mp157d-ev1") ||
+	     of_machine_is_compatible("st,stm32mp157f-ev1")))
+		return true;
+
+	return false;
+}
+
+/* touchscreen driver: only used for pincontrol configuration */
+static const struct udevice_id goodix_ids[] = {
+	{ .compatible = "goodix,gt9147", },
+	{ }
+};
+
+U_BOOT_DRIVER(goodix) = {
+	.name		= "goodix",
+	.id		= UCLASS_NOP,
+	.of_match	= goodix_ids,
+};
+
+static void board_ev1_init(void)
+{
+	struct udevice *dev;
+
+	/* configure IRQ line on EV1 for touchscreen before LCD reset */
+	uclass_get_device_by_driver(UCLASS_NOP, DM_GET_DRIVER(goodix), &dev);
+}
+
 /* board dependent setup after realloc */
 int board_init(void)
 {
@@ -638,6 +673,9 @@ int board_init(void)
 
 	board_key_check();
 
+	if (board_is_ev1())
+		board_ev1_init();
+
 #ifdef CONFIG_DM_REGULATOR
 	if (board_is_dk2())
 		dk2_i2c1_fix();
@@ -650,12 +688,13 @@ int board_init(void)
 	if (CONFIG_IS_ENABLED(LED))
 		led_default_state();
 
+	setup_led(LEDST_ON);
+
 	return 0;
 }
 
 int board_late_init(void)
 {
-	char *boot_device;
 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
 	const void *fdt_compat;
 	int fdt_compat_len;
@@ -667,10 +706,19 @@ int board_late_init(void)
 	fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
 				 &fdt_compat_len);
 	if (fdt_compat && fdt_compat_len) {
-		if (strncmp(fdt_compat, "st,", 3) != 0)
+		if (strncmp(fdt_compat, "st,", 3) != 0) {
 			env_set("board_name", fdt_compat);
-		else
+		} else {
+			char dtb_name[256];
+			int buf_len = sizeof(dtb_name);
+
 			env_set("board_name", fdt_compat + 3);
+
+			strncpy(dtb_name, fdt_compat + 3, buf_len);
+			buf_len -= strlen(fdt_compat + 3);
+			strncat(dtb_name, ".dtb", buf_len);
+			env_set("fdtfile", dtb_name);
+		}
 	}
 	ret = uclass_get_device_by_driver(UCLASS_MISC,
 					  DM_GET_DRIVER(stm32mp_bsec),
@@ -694,19 +742,12 @@ int board_late_init(void)
 	board_check_usb_power();
 #endif /* CONFIG_ADC */
 
-	/* Check the boot-source to disable bootdelay */
-	boot_device = env_get("boot_device");
-	if (!strcmp(boot_device, "serial") || !strcmp(boot_device, "usb"))
-		env_set("bootdelay", "0");
-
 	return 0;
 }
 
 void board_quiesce_devices(void)
 {
-#ifdef CONFIG_LED
 	setup_led(LEDST_OFF);
-#endif
 }
 
 /* eth init function : weak called in eqos driver */
@@ -794,6 +835,7 @@ enum env_location env_get_location(enum env_operation op, int prio)
 #endif
 #ifdef CONFIG_ENV_IS_IN_UBI
 	case BOOT_FLASH_NAND:
+	case BOOT_FLASH_SPINAND:
 		return ENVL_UBI;
 #endif
 #ifdef CONFIG_ENV_IS_IN_SPI_FLASH
@@ -828,114 +870,13 @@ const char *env_ext4_get_dev_part(void)
 }
 #endif
 
-#ifdef CONFIG_SYS_MTDPARTS_RUNTIME
-
-#define MTDPARTS_LEN		256
-#define MTDIDS_LEN		128
-
-/**
- * The mtdparts_nand0 and mtdparts_nor0 variable tends to be long.
- * If we need to access it before the env is relocated, then we need
- * to use our own stack buffer. gd->env_buf will be too small.
- *
- * @param buf temporary buffer pointer MTDPARTS_LEN long
- * @return mtdparts variable string, NULL if not found
- */
-static const char *env_get_mtdparts(const char *str, char *buf)
-{
-	if (gd->flags & GD_FLG_ENV_READY)
-		return env_get(str);
-	if (env_get_f(str, buf, MTDPARTS_LEN) != -1)
-		return buf;
-
-	return NULL;
-}
-
-/**
- * update the variables "mtdids" and "mtdparts" with content of mtdparts_<dev>
- */
-static void board_get_mtdparts(const char *dev,
-			       char *mtdids,
-			       char *mtdparts)
-{
-	char env_name[32] = "mtdparts_";
-	char tmp_mtdparts[MTDPARTS_LEN];
-	const char *tmp;
-
-	/* name of env variable to read = mtdparts_<dev> */
-	strcat(env_name, dev);
-	tmp = env_get_mtdparts(env_name, tmp_mtdparts);
-	if (tmp) {
-		/* mtdids: "<dev>=<dev>, ...." */
-		if (mtdids[0] != '\0')
-			strcat(mtdids, ",");
-		strcat(mtdids, dev);
-		strcat(mtdids, "=");
-		strcat(mtdids, dev);
-
-		/* mtdparts: "mtdparts=<dev>:<mtdparts_<dev>>;..." */
-		if (mtdparts[0] != '\0')
-			strncat(mtdparts, ";", MTDPARTS_LEN);
-		else
-			strcat(mtdparts, "mtdparts=");
-		strncat(mtdparts, dev, MTDPARTS_LEN);
-		strncat(mtdparts, ":", MTDPARTS_LEN);
-		strncat(mtdparts, tmp, MTDPARTS_LEN);
-	}
-}
-
-void board_mtdparts_default(const char **mtdids, const char **mtdparts)
-{
-	struct mtd_info *mtd;
-	struct udevice *dev;
-	static char parts[3 * MTDPARTS_LEN + 1];
-	static char ids[MTDIDS_LEN + 1];
-	static bool mtd_initialized;
-
-	if (mtd_initialized) {
-		*mtdids = ids;
-		*mtdparts = parts;
-		return;
-	}
-
-	memset(parts, 0, sizeof(parts));
-	memset(ids, 0, sizeof(ids));
-
-	/* probe all MTD devices */
-	for (uclass_first_device(UCLASS_MTD, &dev);
-	     dev;
-	     uclass_next_device(&dev)) {
-		pr_debug("mtd device = %s\n", dev->name);
-	}
-
-	mtd = get_mtd_device_nm("nand0");
-	if (!IS_ERR_OR_NULL(mtd)) {
-		board_get_mtdparts("nand0", ids, parts);
-		put_mtd_device(mtd);
-	}
-
-	mtd = get_mtd_device_nm("spi-nand0");
-	if (!IS_ERR_OR_NULL(mtd)) {
-		board_get_mtdparts("spi-nand0", ids, parts);
-		put_mtd_device(mtd);
-	}
-
-	if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev))
-		board_get_mtdparts("nor0", ids, parts);
-
-	mtd_initialized = true;
-	*mtdids = ids;
-	*mtdparts = parts;
-	debug("%s:mtdids=%s & mtdparts=%s\n", __func__, ids, parts);
-}
-#endif
-
 #if defined(CONFIG_OF_BOARD_SETUP)
 int ft_board_setup(void *blob, bd_t *bd)
 {
 #ifdef CONFIG_FDT_FIXUP_PARTITIONS
 	struct node_info nodes[] = {
 		{ "st,stm32f469-qspi",		MTD_DEV_TYPE_NOR,  },
+		{ "st,stm32f469-qspi",		MTD_DEV_TYPE_SPINAND},
 		{ "st,stm32mp15-fmc2",		MTD_DEV_TYPE_NAND, },
 	};
 	fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
@@ -945,148 +886,6 @@ int ft_board_setup(void *blob, bd_t *bd)
 }
 #endif
 
-#ifdef CONFIG_SET_DFU_ALT_INFO
-#define DFU_ALT_BUF_LEN SZ_1K
-
-static void board_get_alt_info(const char *dev, char *buff)
-{
-	char var_name[32] = "dfu_alt_info_";
-	int ret;
-
-	ALLOC_CACHE_ALIGN_BUFFER(char, tmp_alt, DFU_ALT_BUF_LEN);
-
-	/* name of env variable to read = dfu_alt_info_<dev> */
-	strcat(var_name, dev);
-	ret = env_get_f(var_name, tmp_alt, DFU_ALT_BUF_LEN);
-	if (ret) {
-		if (buff[0] != '\0')
-			strcat(buff, "&");
-		strncat(buff, tmp_alt, DFU_ALT_BUF_LEN);
-	}
-}
-
-void set_dfu_alt_info(char *interface, char *devstr)
-{
-	struct udevice *dev;
-	struct mtd_info *mtd;
-
-	ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
-
-	if (env_get("dfu_alt_info"))
-		return;
-
-	memset(buf, 0, sizeof(buf));
-
-	/* probe all MTD devices */
-	mtd_probe_devices();
-
-	board_get_alt_info("ram", buf);
-
-	if (!uclass_get_device(UCLASS_MMC, 0, &dev))
-		board_get_alt_info("mmc0", buf);
-
-	if (!uclass_get_device(UCLASS_MMC, 1, &dev))
-		board_get_alt_info("mmc1", buf);
-
-	if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev))
-		board_get_alt_info("nor0", buf);
-
-	mtd = get_mtd_device_nm("nand0");
-	if (!IS_ERR_OR_NULL(mtd))
-		board_get_alt_info("nand0", buf);
-
-	mtd = get_mtd_device_nm("spi-nand0");
-	if (!IS_ERR_OR_NULL(mtd))
-		board_get_alt_info("spi-nand0", buf);
-
-#ifdef CONFIG_DFU_VIRT
-	strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN);
-
-	if (IS_ENABLED(CONFIG_PMIC_STPMIC1))
-		strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN);
-#endif
-
-	env_set("dfu_alt_info", buf);
-	puts("DFU alt info setting: done\n");
-}
-
-#if CONFIG_IS_ENABLED(DFU_VIRT)
-#include <dfu.h>
-#include <power/stpmic1.h>
-
-static int dfu_otp_read(u64 offset, u8 *buffer, long *size)
-{
-	struct udevice *dev;
-	int ret;
-
-	ret = uclass_get_device_by_driver(UCLASS_MISC,
-					  DM_GET_DRIVER(stm32mp_bsec),
-					  &dev);
-	if (ret)
-		return ret;
-
-	ret = misc_read(dev, offset + STM32_BSEC_OTP_OFFSET, buffer, *size);
-	if (ret >= 0) {
-		*size = ret;
-		ret = 0;
-	}
-
-	return 0;
-}
-
-static int dfu_pmic_read(u64 offset, u8 *buffer, long *size)
-{
-	int ret;
-#ifdef CONFIG_PMIC_STPMIC1
-	struct udevice *dev;
-
-	ret = uclass_get_device_by_driver(UCLASS_MISC,
-					  DM_GET_DRIVER(stpmic1_nvm),
-					  &dev);
-	if (ret)
-		return ret;
-
-	ret = misc_read(dev, 0xF8 + offset, buffer, *size);
-	if (ret >= 0) {
-		*size = ret;
-		ret = 0;
-	}
-	if (ret == -EACCES) {
-		*size = 0;
-		ret = 0;
-	}
-#else
-	pr_err("PMIC update not supported");
-	ret = -EOPNOTSUPP;
-#endif
-
-	return ret;
-}
-
-int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset,
-			 void *buf, long *len)
-{
-	switch (dfu->data.virt.dev_num) {
-	case 0x0:
-		return dfu_otp_read(offset, buf, len);
-	case 0x1:
-		return dfu_pmic_read(offset, buf, len);
-	}
-	*len = 0;
-	return 0;
-}
-
-int __weak dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size)
-{
-	*size = SZ_1K;
-
-	return 0;
-}
-
-#endif
-
-#endif
-
 static void board_copro_image_process(ulong fw_image, size_t fw_size)
 {
 	int ret, id = 0; /* Copro id fixed to 0 as only one coproc on mp1 */

+ 3 - 6
configs/stm32mp15_basic_defconfig

@@ -7,6 +7,7 @@ CONFIG_SYS_SPI_U_BOOT_OFFS=0x80000
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL=y
 CONFIG_TARGET_ST_STM32MP15x=y
+CONFIG_CMD_STM32PROG=y
 CONFIG_ENV_OFFSET_REDUND=0x2C0000
 CONFIG_SPL_SPI_FLASH_SUPPORT=y
 CONFIG_SPL_SPI_SUPPORT=y
@@ -33,10 +34,8 @@ CONFIG_CMD_CLK=y
 CONFIG_CMD_DFU=y
 CONFIG_CMD_FUSE=y
 CONFIG_CMD_GPIO=y
-CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
-CONFIG_CMD_MTD=y
 CONFIG_CMD_REMOTEPROC=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
@@ -66,10 +65,6 @@ CONFIG_ENV_UBI_VOLUME="uboot_config"
 CONFIG_ENV_UBI_VOLUME_REDUND="uboot_config_r"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_STM32_ADC=y
-CONFIG_DFU_MMC=y
-CONFIG_DFU_RAM=y
-CONFIG_DFU_MTD=y
-CONFIG_DFU_VIRT=y
 CONFIG_SET_DFU_ALT_INFO=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
@@ -102,6 +97,7 @@ CONFIG_SPI_FLASH_WINBOND=y
 # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
 CONFIG_SPI_FLASH_MTD=y
 CONFIG_SPL_SPI_FLASH_MTD=y
+CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
 CONFIG_DWC_ETH_QOS=y
 CONFIG_PHY=y
@@ -144,4 +140,5 @@ CONFIG_VIDEO_STM32=y
 CONFIG_VIDEO_STM32_DSI=y
 CONFIG_VIDEO_STM32_MAX_XRES=1280
 CONFIG_VIDEO_STM32_MAX_YRES=800
+CONFIG_ERRNO_STR=y
 CONFIG_FDT_FIXUP_PARTITIONS=y

+ 7 - 0
configs/stm32mp15_dhcom_basic_defconfig

@@ -12,7 +12,11 @@ CONFIG_SPL_SPI_SUPPORT=y
 CONFIG_SPL_TEXT_BASE=0x2FFC2500
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_FIT=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_FIT_SOURCE="board/dhelectronics/dh_stm32mp1/u-boot-dhcom.its"
 CONFIG_BOOTCOMMAND="run bootcmd_stm32mp"
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SPL_LEGACY_IMAGE_SUPPORT=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
@@ -70,6 +74,7 @@ CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
 CONFIG_DFU_VIRT=y
 CONFIG_SET_DFU_ALT_INFO=y
+CONFIG_GPIO_HOG=y
 CONFIG_DM_HWSPINLOCK=y
 CONFIG_HWSPINLOCK_STM32=y
 CONFIG_DM_I2C=y
@@ -79,6 +84,8 @@ CONFIG_LED_GPIO=y
 CONFIG_DM_MAILBOX=y
 CONFIG_STM32_IPCC=y
 CONFIG_I2C_EEPROM=y
+CONFIG_SYS_I2C_EEPROM_ADDR=0x50
+CONFIG_SYS_I2C_EEPROM_BUS=3
 CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_STM32_SDMMC2=y

+ 46 - 39
configs/stm32mp15_optee_defconfig → configs/stm32mp15_dhcor_basic_defconfig

@@ -1,26 +1,33 @@
 CONFIG_ARM=y
 CONFIG_ARCH_STM32MP=y
-CONFIG_TFABOOT=y
 CONFIG_SYS_MALLOC_F_LEN=0x3000
-CONFIG_ENV_OFFSET=0x280000
-CONFIG_ENV_SECT_SIZE=0x40000
-CONFIG_TARGET_ST_STM32MP15x=y
-CONFIG_STM32MP1_OPTEE=y
-CONFIG_ENV_OFFSET_REDUND=0x2C0000
+CONFIG_ENV_SIZE=0x4000
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x80000
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL=y
+CONFIG_TARGET_DH_STM32MP1_PDK2=y
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI_SUPPORT=y
+# CONFIG_ARMV7_VIRT is not set
+CONFIG_SPL_TEXT_BASE=0x2FFC2500
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_FIT=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_SPL_FIT_SOURCE="board/dhelectronics/dh_stm32mp1/u-boot-dhcor.its"
 CONFIG_BOOTCOMMAND="run bootcmd_stm32mp"
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SPL_LEGACY_IMAGE_SUPPORT=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
+CONFIG_SPL_MTD_SUPPORT=y
+CONFIG_SPL_POWER_SUPPORT=y
 CONFIG_SYS_PROMPT="STM32MP> "
-# CONFIG_CMD_BOOTD is not set
 # CONFIG_CMD_ELF is not set
-# CONFIG_CMD_IMI is not set
-# CONFIG_CMD_XIMG is not set
 # CONFIG_CMD_EXPORTENV is not set
-# CONFIG_CMD_IMPORTENV is not set
+CONFIG_CMD_EEPROM=y
 CONFIG_CMD_MEMINFO=y
 CONFIG_CMD_MEMTEST=y
-CONFIG_SYS_MEMTEST_START=0xc0000000
-CONFIG_SYS_MEMTEST_END=0xc4000000
 CONFIG_CMD_ADC=y
 CONFIG_CMD_CLK=y
 CONFIG_CMD_DFU=y
@@ -42,32 +49,28 @@ CONFIG_CMD_PMIC=y
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_MTDPARTS=y
-CONFIG_CMD_UBI=y
-CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
-CONFIG_ENV_IS_NOWHERE=y
-CONFIG_ENV_IS_IN_EXT4=y
+# CONFIG_SPL_DOS_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="stm32mp15xx-dhcor-avenger96"
+CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-names interrupts-extended interrupt-controller \\\#interrupt-cells interrupt-parent dmas dma-names assigned-clocks assigned-clock-rates assigned-clock-parents hwlocks"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_ENV_IS_IN_UBI=y
+CONFIG_USE_ENV_SPI_BUS=y
+CONFIG_ENV_SPI_BUS=0
+CONFIG_USE_ENV_SPI_CS=y
+CONFIG_ENV_SPI_CS=0
+CONFIG_USE_ENV_SPI_MAX_HZ=y
+CONFIG_ENV_SPI_MAX_HZ=10000000
+CONFIG_USE_ENV_SPI_MODE=y
+CONFIG_ENV_SPI_MODE=0x0
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
-CONFIG_ENV_EXT4_INTERFACE="mmc"
-CONFIG_ENV_EXT4_DEVICE_AND_PART="0:auto"
-CONFIG_ENV_EXT4_FILE="/uboot.env"
-CONFIG_ENV_UBI_PART="UBI"
-CONFIG_ENV_UBI_VOLUME="uboot_config"
-CONFIG_ENV_UBI_VOLUME_REDUND="uboot_config_r"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_IP_DEFRAG=y
+CONFIG_TFTP_BLOCKSIZE=1536
 CONFIG_STM32_ADC=y
+CONFIG_SPL_BLOCK_CACHE=y
 CONFIG_DFU_MMC=y
 CONFIG_DFU_RAM=y
-CONFIG_DFU_MTD=y
 CONFIG_DFU_VIRT=y
-CONFIG_SET_DFU_ALT_INFO=y
-CONFIG_USB_FUNCTION_FASTBOOT=y
-CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
-CONFIG_FASTBOOT_BUF_SIZE=0x02000000
-CONFIG_FASTBOOT_USB_DEV=1
-CONFIG_FASTBOOT_FLASH=y
-CONFIG_FASTBOOT_FLASH_MMC_DEV=1
 CONFIG_DM_HWSPINLOCK=y
 CONFIG_HWSPINLOCK_STM32=y
 CONFIG_DM_I2C=y
@@ -76,15 +79,13 @@ CONFIG_LED=y
 CONFIG_LED_GPIO=y
 CONFIG_DM_MAILBOX=y
 CONFIG_STM32_IPCC=y
+CONFIG_I2C_EEPROM=y
+CONFIG_SYS_I2C_EEPROM_ADDR=0x53
+CONFIG_SYS_I2C_EEPROM_BUS=2
 CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_STM32_SDMMC2=y
 CONFIG_MTD=y
-CONFIG_DM_MTD=y
-CONFIG_SYS_MTDPARTS_RUNTIME=y
-CONFIG_MTD_RAW_NAND=y
-CONFIG_NAND_STM32_FMC2=y
-CONFIG_MTD_SPI_NAND=y
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_SPANSION=y
@@ -92,21 +93,23 @@ CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
 # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_SPL_SPI_FLASH_MTD=y
 CONFIG_DM_ETH=y
 CONFIG_DWC_ETH_QOS=y
+CONFIG_KS8851_MLL=y
 CONFIG_PHY=y
 CONFIG_PHY_STM32_USBPHYC=y
 CONFIG_PINCONF=y
+# CONFIG_SPL_PINCTRL_FULL is not set
 CONFIG_PINCTRL_STMFX=y
 CONFIG_DM_PMIC=y
+# CONFIG_SPL_PMIC_CHILDREN is not set
 CONFIG_PMIC_STPMIC1=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_REGULATOR_GPIO=y
 CONFIG_DM_REGULATOR_STM32_VREFBUF=y
 CONFIG_DM_REGULATOR_STPMIC1=y
 CONFIG_REMOTEPROC_STM32_COPRO=y
-CONFIG_DM_RNG=y
-CONFIG_RNG_STM32MP1=y
 CONFIG_DM_RTC=y
 CONFIG_RTC_STM32=y
 CONFIG_SERIAL_RX_BUFFER=y
@@ -120,10 +123,13 @@ CONFIG_DM_USB_GADGET=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_GENERIC=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
+CONFIG_USB_GADGET_MANUFACTURER="dh"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0483
 CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
 CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
 CONFIG_DM_VIDEO=y
 CONFIG_BACKLIGHT_GPIO=y
 CONFIG_VIDEO_LCD_ORISETECH_OTM8009A=y
@@ -132,4 +138,5 @@ CONFIG_VIDEO_STM32=y
 CONFIG_VIDEO_STM32_DSI=y
 CONFIG_VIDEO_STM32_MAX_XRES=1280
 CONFIG_VIDEO_STM32_MAX_YRES=800
+CONFIG_LZO=y
 CONFIG_FDT_FIXUP_PARTITIONS=y

+ 6 - 6
configs/stm32mp15_trusted_defconfig

@@ -5,6 +5,7 @@ CONFIG_SYS_MALLOC_F_LEN=0x3000
 CONFIG_ENV_OFFSET=0x280000
 CONFIG_ENV_SECT_SIZE=0x40000
 CONFIG_TARGET_ST_STM32MP15x=y
+CONFIG_CMD_STM32PROG=y
 CONFIG_ENV_OFFSET_REDUND=0x2C0000
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_FIT=y
@@ -22,10 +23,8 @@ CONFIG_CMD_CLK=y
 CONFIG_CMD_DFU=y
 CONFIG_CMD_FUSE=y
 CONFIG_CMD_GPIO=y
-CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
-CONFIG_CMD_MTD=y
 CONFIG_CMD_REMOTEPROC=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
@@ -53,10 +52,6 @@ CONFIG_ENV_UBI_VOLUME="uboot_config"
 CONFIG_ENV_UBI_VOLUME_REDUND="uboot_config_r"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_STM32_ADC=y
-CONFIG_DFU_MMC=y
-CONFIG_DFU_RAM=y
-CONFIG_DFU_MTD=y
-CONFIG_DFU_VIRT=y
 CONFIG_SET_DFU_ALT_INFO=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
@@ -88,6 +83,7 @@ CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
 # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
 CONFIG_DWC_ETH_QOS=y
 CONFIG_PHY=y
@@ -110,6 +106,9 @@ CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_STM32_QSPI=y
 CONFIG_STM32_SPI=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+# CONFIG_OPTEE_TA_AVB is not set
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB_GADGET=y
@@ -128,4 +127,5 @@ CONFIG_VIDEO_STM32=y
 CONFIG_VIDEO_STM32_DSI=y
 CONFIG_VIDEO_STM32_MAX_XRES=1280
 CONFIG_VIDEO_STM32_MAX_YRES=800
+CONFIG_ERRNO_STR=y
 CONFIG_FDT_FIXUP_PARTITIONS=y

+ 61 - 86
doc/board/st/stm32mp1.rst

@@ -80,32 +80,16 @@ defconfig_file : stm32mp15_trusted_defconfig
     +             +-------------------------+------------+-------+
     |             |Trusted Firmware-A (TF-A)| U-Boot     | Linux |
     +-------------+-------------------------+------------+-------+
-    | TrustZone   |TF-A secure monitor                           |
+    | TrustZone   |secure monitor                                |
     +-------------+-------------------------+------------+-------+
 
 TF-A performs a full initialization of Secure peripherals and installs a
-secure monitor (BL32=SPMin).
+secure monitor, BL32:
 
-U-Boot is running in normal world and uses TF-A monitor to access
-to secure resources.
-
-The **Trusted** boot chain with **OP-TEE**
-``````````````````````````````````````````
-
-defconfig_file : stm32mp15_optee_defconfig
-
-    +-------------+-------------------------+------------+-------+
-    |  ROM code   | FSBL                    | SSBL       | OS    |
-    +             +-------------------------+------------+-------+
-    |             |Trusted Firmware-A (TF-A)| U-Boot     | Linux |
-    +-------------+-------------------------+------------+-------+
-    | TrustZone   |OP-TEE                                        |
-    +-------------+-------------------------+------------+-------+
+  * SPMin provided by TF-A or
+  * OP-TEE from specific partitions (teeh, teed, teex).
 
-TF-A performs a full initialization of Secure peripherals and installs OP-TEE
-from specific partitions (teeh, teed, teex).
-
-U-Boot is running in normal world and uses OP-TEE monitor to access
+U-Boot is running in normal world and uses the secure monitor to access
 to secure resources.
 
 The **Basic** boot chain
@@ -180,7 +164,6 @@ Build Procedure
    for example: use one output directory for each configuration::
 
    # export KBUILD_OUTPUT=stm32mp15_trusted
-   # export KBUILD_OUTPUT=stm32mp15_optee
    # export KBUILD_OUTPUT=stm32mp15_basic
 
    you can build outside of code directory::
@@ -194,7 +177,6 @@ Build Procedure
    with <defconfig_file>:
 
    - For **trusted** boot mode : **stm32mp15_trusted_defconfig**
-   - For **trusted** with OP-TEE boot mode : **stm32mp15_optee_defconfig**
    - For basic boot mode: stm32mp15_basic_defconfig
 
 5. Configure the device-tree and build the U-Boot image::
@@ -211,8 +193,8 @@ Build Procedure
 
   b) trusted with OP-TEE boot on dk2::
 
-      # export KBUILD_OUTPUT=stm32mp15_optee
-      # make stm32mp15_optee_defconfig
+      # export KBUILD_OUTPUT=stm32mp15_trusted
+      # make stm32mp15_trusted_defconfig
       # make DEVICE_TREE=stm32mp157c-dk2 all
 
   c) basic boot on ev1::
@@ -536,61 +518,49 @@ On EV1 board, booting from SD card, without OP-TEE::
   dev: RAM alt: 0 name: uImage layout: RAM_ADDR
   dev: RAM alt: 1 name: devicetree.dtb layout: RAM_ADDR
   dev: RAM alt: 2 name: uramdisk.image.gz layout: RAM_ADDR
-  dev: eMMC alt: 3 name: sdcard_fsbl1 layout: RAW_ADDR
-  dev: eMMC alt: 4 name: sdcard_fsbl2 layout: RAW_ADDR
-  dev: eMMC alt: 5 name: sdcard_ssbl layout: RAW_ADDR
-  dev: eMMC alt: 6 name: sdcard_bootfs layout: RAW_ADDR
-  dev: eMMC alt: 7 name: sdcard_vendorfs layout: RAW_ADDR
-  dev: eMMC alt: 8 name: sdcard_rootfs layout: RAW_ADDR
-  dev: eMMC alt: 9 name: sdcard_userfs layout: RAW_ADDR
-  dev: eMMC alt: 10 name: emmc_fsbl1 layout: RAW_ADDR
-  dev: eMMC alt: 11 name: emmc_fsbl2 layout: RAW_ADDR
-  dev: eMMC alt: 12 name: emmc_ssbl layout: RAW_ADDR
-  dev: eMMC alt: 13 name: emmc_bootfs layout: RAW_ADDR
-  dev: eMMC alt: 14 name: emmc_vendorfs layout: RAW_ADDR
-  dev: eMMC alt: 15 name: emmc_rootfs layout: RAW_ADDR
-  dev: eMMC alt: 16 name: emmc_userfs layout: RAW_ADDR
-  dev: MTD alt: 17 name: nor_fsbl1 layout: RAW_ADDR
-  dev: MTD alt: 18 name: nor_fsbl2 layout: RAW_ADDR
-  dev: MTD alt: 19 name: nor_ssbl layout: RAW_ADDR
-  dev: MTD alt: 20 name: nor_env layout: RAW_ADDR
-  dev: MTD alt: 21 name: nand_fsbl layout: RAW_ADDR
-  dev: MTD alt: 22 name: nand_ssbl1 layout: RAW_ADDR
-  dev: MTD alt: 23 name: nand_ssbl2 layout: RAW_ADDR
-  dev: MTD alt: 24 name: nand_UBI layout: RAW_ADDR
-  dev: VIRT alt: 25 name: OTP layout: RAW_ADDR
-  dev: VIRT alt: 26 name: PMIC layout: RAW_ADDR
+  dev: eMMC alt: 3 name: mmc0_fsbl1 layout: RAW_ADDR
+  dev: eMMC alt: 4 name: mmc0_fsbl2 layout: RAW_ADDR
+  dev: eMMC alt: 5 name: mmc0_ssbl layout: RAW_ADDR
+  dev: eMMC alt: 6 name: mmc0_bootfs layout: RAW_ADDR
+  dev: eMMC alt: 7 name: mmc0_vendorfs layout: RAW_ADDR
+  dev: eMMC alt: 8 name: mmc0_rootfs layout: RAW_ADDR
+  dev: eMMC alt: 9 name: mmc0_userfs layout: RAW_ADDR
+  dev: eMMC alt: 10 name: mmc1_boot1 layout: RAW_ADDR
+  dev: eMMC alt: 11 name: mmc1_boot2 layout: RAW_ADDR
+  dev: eMMC alt: 12 name: mmc1_ssbl layout: RAW_ADDR
+  dev: eMMC alt: 13 name: mmc1_bootfs layout: RAW_ADDR
+  dev: eMMC alt: 14 name: mmc1_vendorfs layout: RAW_ADDR
+  dev: eMMC alt: 15 name: mmc1_rootfs layout: RAW_ADDR
+  dev: eMMC alt: 16 name: mmc1_userfs layout: RAW_ADDR
+  dev: MTD alt: 17 name: nor0 layout: RAW_ADDR
+  dev: MTD alt: 18 name: nand0 layout: RAW_ADDR
+  dev: VIRT alt: 19 name: OTP layout: RAW_ADDR
+  dev: VIRT alt: 20 name: PMIC layout: RAW_ADDR
 
 All the supported device are exported for dfu-util tool::
 
   $> dfu-util -l
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=26, name="PMIC", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=25, name="OTP", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=24, name="nand_UBI", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=23, name="nand_ssbl2", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=22, name="nand_ssbl1", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=21, name="nand_fsbl", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=20, name="nor_env", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=19, name="nor_ssbl", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=18, name="nor_fsbl2", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=17, name="nor_fsbl1", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=16, name="emmc_userfs", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=15, name="emmc_rootfs", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=14, name="emmc_vendorfs", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=13, name="emmc_bootfs", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=12, name="emmc_ssbl", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=11, name="emmc_fsbl2", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=10, name="emmc_fsbl1", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=9, name="sdcard_userfs", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=8, name="sdcard_rootfs", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=7, name="sdcard_vendorfs", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=6, name="sdcard_bootfs", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=5, name="sdcard_ssbl", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=4, name="sdcard_fsbl2", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=3, name="sdcard_fsbl1", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=2, name="uramdisk.image.gz", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=1, name="devicetree.dtb", serial="002700333338511934383330"
-  Found DFU: [0483:5720] ver=9999, devnum=99, cfg=1, intf=0, alt=0, name="uImage", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=20, name="PMIC", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=19, name="OTP", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=18, name="nand0", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=17, name="nor0", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=16, name="mmc1_userfs", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=15, name="mmc1_rootfs", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=14, name="mmc1_vendorfs", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=13, name="mmc1_bootfs", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=12, name="mmc1_ssbl", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=11, name="mmc1_boot2", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=10, name="mmc1_boot1", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=9, name="mmc0_userfs", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=8, name="mmc0_rootfs", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=7, name="mmc0_vendorfs", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=6, name="mmc0_bootfs", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=5, name="mmc0_ssbl", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=4, name="mmc0_fsbl2", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=3, name="mmc0_fsbl1", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=2, name="uramdisk.image.gz", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=1, name="devicetree.dtb", serial="002700333338511934383330"
+  Found DFU: [0483:df11] ver=9999, devnum=99, cfg=1, intf=0, alt=0, name="uImage", serial="002700333338511934383330"
 
 You can update the boot device:
 
@@ -614,20 +584,25 @@ You can update the boot device:
   $> dfu-util -d 0483:5720 -a 15 -D st-image-weston-openstlinux-weston-stm32mp1.ext4
   $> dfu-util -d 0483:5720 -a 16 -D st-image-userfs-openstlinux-weston-stm32mp1.ext4
 
-- NOR::
+- you can also dump the OTP and the PMIC NVM with::
+
+  $> dfu-util -d 0483:5720 -a 19 -U otp.bin
+  $> dfu-util -d 0483:5720 -a 20 -U pmic.bin
+
 
-  $> dfu-util -d 0483:5720 -a 17 -D tf-a-stm32mp157c-ev1-trusted.stm32
-  $> dfu-util -d 0483:5720 -a 18 -D tf-a-stm32mp157c-ev1-trusted.stm32
-  $> dfu-util -d 0483:5720 -a 19 -D u-boot-stm32mp157c-ev1-trusted.img
+When the board is booting for nor0 or nand0,
+only the MTD partition on the boot devices are available, for example:
 
-- NAND (UBI partition used for NAND only boot or NOR + NAND boot)::
+- NOR (nor0 = alt 20) & NAND (nand0 = alt 26) ::
 
   $> dfu-util -d 0483:5720 -a 21 -D tf-a-stm32mp157c-ev1-trusted.stm32
-  $> dfu-util -d 0483:5720 -a 22 -D u-boot-stm32mp157c-ev1-trusted.img
+  $> dfu-util -d 0483:5720 -a 22 -D tf-a-stm32mp157c-ev1-trusted.stm32
   $> dfu-util -d 0483:5720 -a 23 -D u-boot-stm32mp157c-ev1-trusted.img
-  $> dfu-util -d 0483:5720 -a 24 -D st-image-weston-openstlinux-weston-stm32mp1_nand_4_256_multivolume.ubi
+  $> dfu-util -d 0483:5720 -a 27 -D st-image-weston-openstlinux-weston-stm32mp1_nand_4_256_multivolume.ubi
 
-- you can also dump the OTP and the PMIC NVM with::
+- NAND (nand0 = alt 21)::
 
-  $> dfu-util -d 0483:5720 -a 25 -U otp.bin
-  $> dfu-util -d 0483:5720 -a 26 -U pmic.bin
+  $> dfu-util -d 0483:5720 -a 22 -D tf-a-stm32mp157c-ev1-trusted.stm32
+  $> dfu-util -d 0483:5720 -a 23 -D u-boot-stm32mp157c-ev1-trusted.img
+  $> dfu-util -d 0483:5720 -a 24 -D u-boot-stm32mp157c-ev1-trusted.img
+  $> dfu-util -d 0483:5720 -a 25 -D st-image-weston-openstlinux-weston-stm32mp1_nand_4_256_multivolume.ubi

+ 4 - 3
drivers/clk/clk_stm32mp1.c

@@ -954,10 +954,11 @@ static ulong stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p)
 		case RCC_MPCKSELR_PLL:
 		case RCC_MPCKSELR_PLL_MPUDIV:
 			clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P);
-			if (p == RCC_MPCKSELR_PLL_MPUDIV) {
+			if ((reg & RCC_SELR_SRC_MASK) ==
+			    RCC_MPCKSELR_PLL_MPUDIV) {
 				reg = readl(priv->base + RCC_MPCKDIVR);
-				clock /= stm32mp1_mpu_div[reg &
-							  RCC_MPUDIV_MASK];
+				clock >>= stm32mp1_mpu_div[reg &
+					RCC_MPUDIV_MASK];
 			}
 			break;
 		}

+ 1 - 6
drivers/gpio/stm32_gpio.c

@@ -20,7 +20,6 @@
 #define MODE_BITS_MASK			3
 #define BSRR_BIT(gpio_pin, value)	BIT(gpio_pin + (value ? 0 : 16))
 
-#ifndef CONFIG_SPL_BUILD
 /*
  * convert gpio offset to gpio index taking into account gpio holes
  * into gpio bank
@@ -147,7 +146,6 @@ static const struct dm_gpio_ops gpio_stm32_ops = {
 	.set_value		= stm32_gpio_set_value,
 	.get_function		= stm32_gpio_get_function,
 };
-#endif
 
 static int gpio_stm32_probe(struct udevice *dev)
 {
@@ -162,7 +160,6 @@ static int gpio_stm32_probe(struct udevice *dev)
 
 	priv->regs = (struct stm32_gpio_regs *)addr;
 
-#ifndef CONFIG_SPL_BUILD
 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct ofnode_phandle_args args;
 	const char *name;
@@ -195,7 +192,7 @@ static int gpio_stm32_probe(struct udevice *dev)
 	dev_dbg(dev, "addr = 0x%p bank_name = %s gpio_count = %d gpio_range = 0x%x\n",
 		(u32 *)priv->regs, uc_priv->bank_name, uc_priv->gpio_count,
 		priv->gpio_range);
-#endif
+
 	ret = clk_get_by_index(dev, 0, &clk);
 	if (ret < 0)
 		return ret;
@@ -215,9 +212,7 @@ U_BOOT_DRIVER(gpio_stm32) = {
 	.name	= "gpio_stm32",
 	.id	= UCLASS_GPIO,
 	.probe	= gpio_stm32_probe,
-#ifndef CONFIG_SPL_BUILD
 	.ops	= &gpio_stm32_ops,
-#endif
 	.flags	= DM_UC_FLAG_SEQ_ALIAS,
 	.priv_auto_alloc_size	= sizeof(struct stm32_gpio_priv),
 };

+ 1 - 1
drivers/mmc/stm32_sdmmc2.c

@@ -674,7 +674,7 @@ static int stm32_sdmmc2_probe(struct udevice *dev)
 	cfg->f_max = dev_read_u32_default(dev, "max-frequency", 52000000);
 	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
-	cfg->name = "STM32 SDMMC2";
+	cfg->name = "STM32 SD/MMC";
 
 	cfg->host_caps = 0;
 	if (cfg->f_max > 25000000)

+ 28 - 5
drivers/ram/stm32mp1/stm32mp1_ram.c

@@ -57,6 +57,27 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed)
 	return 0;
 }
 
+__weak int board_stm32mp1_ddr_config_name_match(struct udevice *dev,
+						const char *name)
+{
+	return 0;	/* Always match */
+}
+
+static ofnode stm32mp1_ddr_get_ofnode(struct udevice *dev)
+{
+	const char *name;
+	ofnode node;
+
+	dev_for_each_subnode(node, dev) {
+		name = ofnode_get_property(node, "compatible", NULL);
+
+		if (!board_stm32mp1_ddr_config_name_match(dev, name))
+			return node;
+	}
+
+	return dev_ofnode(dev);
+}
+
 static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
 {
 	struct ddr_info *priv = dev_get_priv(dev);
@@ -64,6 +85,7 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
 	unsigned int idx;
 	struct clk axidcg;
 	struct stm32mp1_ddr_config config;
+	ofnode node = stm32mp1_ddr_get_ofnode(dev);
 
 #define PARAM(x, y, z)							\
 	{	.name = x,						\
@@ -91,9 +113,9 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
 		PHY_PARAM_OPT(cal)
 	};
 
-	config.info.speed = dev_read_u32_default(dev, "st,mem-speed", 0);
-	config.info.size = dev_read_u32_default(dev, "st,mem-size", 0);
-	config.info.name = dev_read_string(dev, "st,mem-name");
+	config.info.speed = ofnode_read_u32_default(node, "st,mem-speed", 0);
+	config.info.size = ofnode_read_u32_default(node, "st,mem-size", 0);
+	config.info.name = ofnode_read_string(node, "st,mem-name");
 	if (!config.info.name) {
 		debug("%s: no st,mem-name\n", __func__);
 		return -EINVAL;
@@ -101,7 +123,7 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
 	printf("RAM: %s\n", config.info.name);
 
 	for (idx = 0; idx < ARRAY_SIZE(param); idx++) {
-		ret = dev_read_u32_array(dev, param[idx].name,
+		ret = ofnode_read_u32_array(node, param[idx].name,
 					 (void *)((u32)&config +
 						  param[idx].offset),
 					 param[idx].size);
@@ -182,7 +204,8 @@ static int stm32mp1_ddr_probe(struct udevice *dev)
 	priv->info.size = 0;
 	return stm32mp1_ddr_setup(dev);
 #else
-	priv->info.size = dev_read_u32_default(dev, "st,mem-size", 0);
+	ofnode node = stm32mp1_ddr_get_ofnode(dev);
+	priv->info.size = ofnode_read_u32_default(node, "st,mem-size", 0);
 	return 0;
 #endif
 }

+ 8 - 0
drivers/usb/gadget/g_dnl.c

@@ -89,6 +89,14 @@ static struct usb_gadget_strings *g_dnl_composite_strings[] = {
 	NULL,
 };
 
+void g_dnl_set_product(const char *s)
+{
+	if (s)
+		g_dnl_string_defs[1].s = s;
+	else
+		g_dnl_string_defs[1].s = product;
+}
+
 static int g_dnl_unbind(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget *gadget = cdev->gadget;

+ 15 - 0
include/configs/dh_stm32mp1.h

@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2020 Marek Vasut <marex@denx.de>
+ *
+ * Configuration settings for the DH STM32MP15x SoMs
+ */
+
+#ifndef __CONFIG_DH_STM32MP1_H__
+#define __CONFIG_DH_STM32MP1_H__
+
+#include <configs/stm32mp1.h>
+
+#define CONFIG_SPL_TARGET		"u-boot.itb"
+
+#endif

+ 3 - 61
include/configs/stm32mp1.h

@@ -23,10 +23,6 @@
 #define CONFIG_SYS_SDRAM_BASE			STM32_DDR_BASE
 #define CONFIG_SYS_INIT_SP_ADDR			CONFIG_SYS_TEXT_BASE
 
-#ifdef CONFIG_STM32MP1_OPTEE
-#define CONFIG_SYS_MEM_TOP_HIDE			SZ_32M
-#endif /* CONFIG_STM32MP1_OPTEE */
-
 /*
  * Console I/O buffer size
  */
@@ -126,7 +122,7 @@
  * bootcmd for stm32mp1:
  * for serial/usb: execute the stm32prog command
  * for mmc boot (eMMC, SD card), boot only on the same device
- * for nand boot, boot with on ubifs partition on nand
+ * for nand or spi-nand boot, boot with on ubifs partition on UBI partition
  * for nor boot, use the default order
  */
 #define STM32MP_BOOTCMD "bootcmd_stm32mp=" \
@@ -137,65 +133,14 @@
 		"run env_check;" \
 		"if test ${boot_device} = mmc;" \
 		"then env set boot_targets \"mmc${boot_instance}\"; fi;" \
-		"if test ${boot_device} = nand;" \
+		"if test ${boot_device} = nand ||" \
+		  " test ${boot_device} = spi-nand ;" \
 		"then env set boot_targets ubifs0; fi;" \
 		"run distro_bootcmd;" \
 	"fi;\0"
 
 #include <config_distro_bootcmd.h>
 
-#ifdef CONFIG_STM32MP1_OPTEE
-/* with OPTEE: define specific MTD partitions = teeh, teed, teex */
-#define STM32MP_MTDPARTS \
-	"mtdparts_nor0=256k(fsbl1),256k(fsbl2),2m(ssbl),256k(u-boot-env),256k(teeh),256k(teed),256k(teex),-(nor_user)\0" \
-	"mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),512k(teeh),512k(teed),512k(teex),-(UBI)\0" \
-	"mtdparts_spi-nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),"\
-		"512k(teeh),512k(teed),512k(teex),-(UBI)\0"
-
-#else /* CONFIG_STM32MP1_OPTEE */
-#define STM32MP_MTDPARTS \
-	"mtdparts_nor0=256k(fsbl1),256k(fsbl2),2m(ssbl),256k(u-boot-env),-(nor_user)\0" \
-	"mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),-(UBI)\0" \
-	"mtdparts_spi-nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),-(UBI)\0"
-
-#endif /* CONFIG_STM32MP1_OPTEE */
-
-#ifndef CONFIG_SYS_MTDPARTS_RUNTIME
-#undef STM32MP_MTDPARTS
-#define STM32MP_MTDPARTS
-#endif
-
-#define STM32MP_DFU_ALT_RAM \
-	"dfu_alt_info_ram=ram 0=" \
-		"uImage ram ${kernel_addr_r} 0x2000000;" \
-		"devicetree.dtb ram ${fdt_addr_r} 0x100000;" \
-		"uramdisk.image.gz ram ${ramdisk_addr_r} 0x10000000\0"
-
-#ifdef CONFIG_SET_DFU_ALT_INFO
-#define STM32MP_DFU_ALT_INFO \
-	"dfu_alt_info_nor0=mtd nor0=" \
-		"nor_fsbl1 part 1;nor_fsbl2 part 2;" \
-		"nor_ssbl part 3;nor_env part 4\0" \
-	"dfu_alt_info_nand0=mtd nand0="\
-		"nand_fsbl part 1;nand_ssbl1 part 2;" \
-		"nand_ssbl2 part 3;nand_UBI partubi 4\0" \
-	"dfu_alt_info_spi-nand0=mtd spi-nand0="\
-		"spi-nand_fsbl part 1;spi-nand_ssbl1 part 2;" \
-		"spi-nand_ssbl2 part 3;spi-nand_UBI partubi 4\0" \
-	"dfu_alt_info_mmc0=mmc 0=" \
-		"sdcard_fsbl1 part 0 1;sdcard_fsbl2 part 0 2;" \
-		"sdcard_ssbl part 0 3;sdcard_bootfs part 0 4;" \
-		"sdcard_vendorfs part 0 5;sdcard_rootfs part 0 6;" \
-		"sdcard_userfs part 0 7\0" \
-	"dfu_alt_info_mmc1=mmc 1=" \
-		"emmc_fsbl1 raw 0x0 0x200 mmcpart 1;" \
-		"emmc_fsbl2 raw 0x0 0x200 mmcpart 2;emmc_ssbl part 1 1;" \
-		"emmc_bootfs part 1 2;emmc_vendorfs part 1 3;" \
-		"emmc_rootfs part 1 4;emmc_userfs part 1 5\0"
-#else
-#define STM32MP_DFU_ALT_INFO
-#endif
-
 /*
  * memory layout for 32M uncompressed/compressed kernel,
  * 1M fdt, 1M script, 1M pxe and 1M for splashimage
@@ -214,9 +159,6 @@
 	"env_check=if test $env_default -eq 1;"\
 		" then env set env_default 0;env save;fi\0" \
 	STM32MP_BOOTCMD \
-	STM32MP_MTDPARTS \
-	STM32MP_DFU_ALT_RAM \
-	STM32MP_DFU_ALT_INFO \
 	BOOTENV \
 	"boot_net_usb_start=true\0"
 

+ 3 - 0
include/dfu.h

@@ -209,6 +209,9 @@ void dfu_initiated_callback(struct dfu_entity *dfu);
  */
 void dfu_flush_callback(struct dfu_entity *dfu);
 
+int dfu_transaction_initiate(struct dfu_entity *dfu, bool read);
+void dfu_transaction_cleanup(struct dfu_entity *dfu);
+
 /*
  * dfu_defer_flush - pointer to store dfu_entity for deferred flashing.
  *		     It should be NULL when not used.

+ 1 - 0
include/g_dnl.h

@@ -38,6 +38,7 @@ int g_dnl_board_usb_cable_connected(void);
 int g_dnl_register(const char *s);
 void g_dnl_unregister(void);
 void g_dnl_set_serialnumber(char *);
+void g_dnl_set_product(const char *s);
 
 bool g_dnl_detach(void);
 void g_dnl_trigger_detach(void);