diff --git a/arch/arm/dts/stm32mp15-ddr.dtsi b/arch/arm/dts/stm32mp15-ddr.dtsi index 8b20b5e173..2a139c54e9 100644 --- a/arch/arm/dts/stm32mp15-ddr.dtsi +++ b/arch/arm/dts/stm32mp15-ddr.dtsi @@ -2,156 +2,240 @@ /* * Copyright : STMicroelectronics 2018 */ +#include -/ { - 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 = ; + st,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 = ; - st,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 diff --git a/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi index 11e8f2bef6..b4787c4735 100644 --- a/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi +++ b/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 - * - * 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 */ -#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.45" -#define DDR_MEM_SPEED 533000 -#define DDR_MEM_SIZE 0x20000000 + +/* + * 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 + * + * Save Date: 2020.02.20, save Time: 18:45:20 + */ +#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 diff --git a/arch/arm/dts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/arch/arm/dts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi index 4b70b60554..dc2875ca08 100644 --- a/arch/arm/dts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi +++ b/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 - * - * 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 */ -#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.45" -#define DDR_MEM_SPEED 533000 -#define DDR_MEM_SIZE 0x40000000 + +/* + * 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 + * + * Save Date: 2020.02.20, save Time: 18:49:33 + */ +#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 diff --git a/arch/arm/dts/stm32mp15-ddr3-dhsom-2x1Gb-1066-binG.dtsi b/arch/arm/dts/stm32mp15-ddr3-dhsom-2x1Gb-1066-binG.dtsi new file mode 100644 index 0000000000..b3eb280f96 --- /dev/null +++ b/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" diff --git a/arch/arm/dts/stm32mp15-ddr3-dhsom-2x2Gb-1066-binG.dtsi b/arch/arm/dts/stm32mp15-ddr3-dhsom-2x2Gb-1066-binG.dtsi new file mode 100644 index 0000000000..ed3a5248f8 --- /dev/null +++ b/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" diff --git a/arch/arm/dts/stm32mp15-ddr3-dhsom-2x4Gb-1066-binG.dtsi b/arch/arm/dts/stm32mp15-ddr3-dhsom-2x4Gb-1066-binG.dtsi new file mode 100644 index 0000000000..d5813d64b0 --- /dev/null +++ b/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" diff --git a/arch/arm/dts/stm32mp15-pinctrl.dtsi b/arch/arm/dts/stm32mp15-pinctrl.dtsi index 29acdc4afd..8d00391978 100644 --- a/arch/arm/dts/stm32mp15-pinctrl.dtsi +++ b/arch/arm/dts/stm32mp15-pinctrl.dtsi @@ -213,6 +213,40 @@ }; }; + ethernet0_rmii_pins_a: rmii-0 { + pins1 { + pinmux = , /* ETH1_RMII_TXD0 */ + , /* ETH1_RMII_TXD1 */ + , /* ETH1_RMII_TX_EN */ + , /* ETH1_RMII_REF_CLK */ + , /* ETH1_MDIO */ + ; /* ETH1_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + pins2 { + pinmux = , /* ETH1_RMII_RXD0 */ + , /* ETH1_RMII_RXD1 */ + ; /* ETH1_RMII_CRS_DV */ + bias-disable; + }; + }; + + ethernet0_rmii_pins_sleep_a: rmii-sleep-0 { + pins1 { + pinmux = , /* ETH1_RMII_TXD0 */ + , /* ETH1_RMII_TXD1 */ + , /* ETH1_RMII_TX_EN */ + , /* ETH1_MDIO */ + , /* ETH1_MDC */ + , /* ETH1_RMII_RXD0 */ + , /* ETH1_RMII_RXD1 */ + , /* ETH1_RMII_REF_CLK */ + ; /* ETH1_RMII_CRS_DV */ + }; + }; + fmc_pins_a: fmc-0 { pins1 { pinmux = , /* FMC_NOE */ @@ -736,6 +770,25 @@ }; }; + sai2a_pins_b: sai2a-2 { + pins1 { + pinmux = , /* SAI2_SD_A */ + , /* SAI2_FS_A */ + ; /* SAI2_SCK_A */ + slew-rate = <0>; + drive-push-pull; + bias-disable; + }; + }; + + sai2a_sleep_pins_b: sai2a-sleep-3 { + pins { + pinmux = , /* SAI2_SD_A */ + , /* SAI2_FS_A */ + ; /* SAI2_SCK_A */ + }; + }; + sai2b_pins_a: sai2b-0 { pins1 { pinmux = , /* SAI2_SCK_B */ @@ -1118,6 +1171,19 @@ }; }; + usart3_pins_a: usart3-0 { + pins1 { + pinmux = ; /* USART3_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* USART3_RX */ + bias-disable; + }; + }; + uart4_pins_a: uart4-0 { pins1 { pinmux = ; /* UART4_TX */ @@ -1158,6 +1224,32 @@ bias-disable; }; }; + + uart8_pins_a: uart8-0 { + pins1 { + pinmux = ; /* UART8_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART8_RX */ + bias-disable; + }; + }; + + usbotg_hs_pins_a: usbotg-hs-0 { + pins { + pinmux = ; /* OTG_ID */ + }; + }; + + usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 { + pins { + pinmux = , /* OTG_FS_DM */ + ; /* OTG_FS_DP */ + }; + }; }; &pinctrl_z { diff --git a/arch/arm/dts/stm32mp15-u-boot.dtsi b/arch/arm/dts/stm32mp15-u-boot.dtsi index 8f9535a4db..1279589a56 100644 --- a/arch/arm/dts/stm32mp15-u-boot.dtsi +++ b/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"; + }; }; }; diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi index f185639a46..75d2c0d296 100644 --- a/arch/arm/dts/stm32mp151.dtsi +++ b/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 @@ , ; clocks = <&rcc DMA1>; + resets = <&rcc DMA1_R>; #dma-cells = <4>; st,mem2mem; dma-requests = <8>; @@ -983,6 +989,7 @@ , ; 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 = ; 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"; }; diff --git a/arch/arm/dts/stm32mp153.dtsi b/arch/arm/dts/stm32mp153.dtsi index 2d759fc601..6d9ab08667 100644 --- a/arch/arm/dts/stm32mp153.dtsi +++ b/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>; }; diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index 5844d41c53..c52abeb1e7 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -27,10 +27,6 @@ default-state = "off"; status = "okay"; }; - - blue { - default-state = "on"; - }; }; }; diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi index ed2f024be9..84af7fa47b 100644 --- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi @@ -28,10 +28,6 @@ default-state = "off"; status = "okay"; }; - - blue { - default-state = "on"; - }; }; }; diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts index 54af7c97b3..4fb71100f5 100644 --- a/arch/arm/dts/stm32mp157c-ed1.dts +++ b/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 = ; }; @@ -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"; }; diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts index 228e35e168..8a4c7ff31a 100644 --- a/arch/arm/dts/stm32mp157c-ev1.dts +++ b/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"; diff --git a/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi b/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi index b57f3d520c..75d75266e8 100644 --- a/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi +++ b/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi @@ -5,7 +5,9 @@ #include #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; }; diff --git a/arch/arm/dts/stm32mp15xx-dhcom.dtsi b/arch/arm/dts/stm32mp15xx-dhcom.dtsi index d8a255b9c6..b3f4cb4515 100644 --- a/arch/arm/dts/stm32mp15xx-dhcom.dtsi +++ b/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; diff --git a/arch/arm/dts/stm32mp15xx-dhcor-avenger96-u-boot.dtsi b/arch/arm/dts/stm32mp15xx-dhcor-avenger96-u-boot.dtsi index 3f82f20705..cb92fc9c14 100644 --- a/arch/arm/dts/stm32mp15xx-dhcor-avenger96-u-boot.dtsi +++ b/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>; }; }; diff --git a/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dts b/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dts index a600677563..1b0579c8ab 100644 --- a/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dts +++ b/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" / { diff --git a/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi b/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi new file mode 100644 index 0000000000..75435424d6 --- /dev/null +++ b/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 + */ + +#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>; +}; diff --git a/arch/arm/dts/stm32mp15xx-dhcor.dtsi b/arch/arm/dts/stm32mp15xx-dhcor-io3v3.dtsi similarity index 89% rename from arch/arm/dts/stm32mp15xx-dhcor.dtsi rename to arch/arm/dts/stm32mp15xx-dhcor-io3v3.dtsi index 97d370e119..64299df816 100644 --- a/arch/arm/dts/stm32mp15xx-dhcor.dtsi +++ b/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 = ; 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>; }; diff --git a/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi b/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi index 5de7b87b9a..ef730a8322 100644 --- a/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi +++ b/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi @@ -9,7 +9,17 @@ #include #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; diff --git a/arch/arm/dts/stm32mp15xx-dkx.dtsi b/arch/arm/dts/stm32mp15xx-dkx.dtsi index 42d3f0cb2d..812e370ee4 100644 --- a/arch/arm/dts/stm32mp15xx-dkx.dtsi +++ b/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 = ; }; @@ -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>; diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig index ba965e7b3b..6c995ed8d8 100644 --- a/arch/arm/mach-stm32mp/Kconfig +++ b/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 diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile index eee39c27c3..66bb8cf92f 100644 --- a/arch/arm/mach-stm32mp/Makefile +++ b/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 diff --git a/arch/arm/mach-stm32mp/boot_params.c b/arch/arm/mach-stm32mp/boot_params.c new file mode 100644 index 0000000000..e4351de939 --- /dev/null +++ b/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 +#include +#include + +/* + * 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; +} diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/Makefile b/arch/arm/mach-stm32mp/cmd_stm32prog/Makefile new file mode 100644 index 0000000000..548a378921 --- /dev/null +++ b/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 diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c new file mode 100644 index 0000000000..6bebea7ad5 --- /dev/null +++ b/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 +#include +#include +#include +#include +#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, + " [] []\n" + "start communication with tools STM32Cubeprogrammer on with Flashlayout at ", + " = serial|usb\n" + " = device instance\n" + " = address of flashlayout\n" + " = 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; +} diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c new file mode 100644 index 0000000000..cc303214cf --- /dev/null +++ b/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); + } +} diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h new file mode 100644 index 0000000000..bae4e91c01 --- /dev/null +++ b/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 diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_serial.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_serial.c new file mode 100644 index 0000000000..5a16979adc --- /dev/null +++ b/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 +#include +#include +#include +#include +#include +#include +#include +#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 */ +} diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c new file mode 100644 index 0000000000..969245e199 --- /dev/null +++ b/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 +#include +#include +#include +#include +#include +#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; +} diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index 74d03fa7dd..5a10808a44 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/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"); diff --git a/arch/arm/mach-stm32mp/dram_init.c b/arch/arm/mach-stm32mp/dram_init.c index 7688b3e315..3233415eff 100644 --- a/arch/arm/mach-stm32mp/dram_init.c +++ b/arch/arm/mach-stm32mp/dram_init.c @@ -5,6 +5,7 @@ #include #include +#include #include 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; +} diff --git a/arch/arm/mach-stm32mp/fdt.c b/arch/arm/mach-stm32mp/fdt.c index 3ee7d6a833..21b5f09728 100644 --- a/arch/arm/mach-stm32mp/fdt.c +++ b/arch/arm/mach-stm32mp/fdt.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -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; } diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index 76d593d785..242bacc50b 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/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 */ diff --git a/arch/arm/mach-stm32mp/include/mach/stm32prog.h b/arch/arm/mach-stm32mp/include/mach/stm32prog.h new file mode 100644 index 0000000000..c080b9cc42 --- /dev/null +++ b/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); diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h index 1617126bea..4b6c7b8bdd 100644 --- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h +++ b/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 diff --git a/arch/arm/mach-stm32mp/spl.c b/arch/arm/mach-stm32mp/spl.c index f85391c6af..b7e7e92ef6 100644 --- a/arch/arm/mach-stm32mp/spl.c +++ b/arch/arm/mach-stm32mp/spl.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -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(); } diff --git a/board/dhelectronics/dh_stm32mp1/Kconfig b/board/dhelectronics/dh_stm32mp1/Kconfig index 8eab986640..1fc792c9d1 100644 --- a/board/dhelectronics/dh_stm32mp1/Kconfig +++ b/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 diff --git a/board/dhelectronics/dh_stm32mp1/MAINTAINERS b/board/dhelectronics/dh_stm32mp1/MAINTAINERS index 1511ecb65d..fd70131f9e 100644 --- a/board/dhelectronics/dh_stm32mp1/MAINTAINERS +++ b/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 diff --git a/board/dhelectronics/dh_stm32mp1/Makefile b/board/dhelectronics/dh_stm32mp1/Makefile index b42c4e4c04..e8f218da08 100644 --- a/board/dhelectronics/dh_stm32mp1/Makefile +++ b/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 diff --git a/board/dhelectronics/dh_stm32mp1/board.c b/board/dhelectronics/dh_stm32mp1/board.c index 322558157e..85d56f6082 100644 --- a/board/dhelectronics/dh_stm32mp1/board.c +++ b/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_ - */ -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_ */ - strcat(env_name, dev); - tmp = env_get_mtdparts(env_name, tmp_mtdparts); - if (tmp) { - /* mtdids: "=, ...." */ - if (mtdids[0] != '\0') - strcat(mtdids, ","); - strcat(mtdids, dev); - strcat(mtdids, "="); - strcat(mtdids, dev); - - /* mtdparts: "mtdparts=:>;..." */ - 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_ */ - 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 */ diff --git a/board/dhelectronics/dh_stm32mp1/u-boot-dhcom.its b/board/dhelectronics/dh_stm32mp1/u-boot-dhcom.its new file mode 100644 index 0000000000..2776c41af1 --- /dev/null +++ b/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 */ + }; +}; diff --git a/board/dhelectronics/dh_stm32mp1/u-boot-dhcor.its b/board/dhelectronics/dh_stm32mp1/u-boot-dhcor.its new file mode 100644 index 0000000000..8844508f1a --- /dev/null +++ b/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 */ + }; +}; diff --git a/board/st/common/Kconfig b/board/st/common/Kconfig index af01ca4891..015ba40939 100644 --- a/board/st/common/Kconfig +++ b/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. diff --git a/board/st/common/Makefile b/board/st/common/Makefile index 8553606b90..aa030bacd8 100644 --- a/board/st/common/Makefile +++ b/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 diff --git a/board/st/common/stm32mp_dfu.c b/board/st/common/stm32mp_dfu.c new file mode 100644 index 0000000000..3bd005bb04 --- /dev/null +++ b/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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include + +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 diff --git a/board/st/common/stm32mp_mtdparts.c b/board/st/common/stm32mp_mtdparts.c new file mode 100644 index 0000000000..9f5897f8c8 --- /dev/null +++ b/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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: "=, ...." */ + if (mtdids[0] != '\0') + strcat(mtdids, ","); + strcat(mtdids, dev); + strcat(mtdids, "="); + strcat(mtdids, dev); + + /* mtdparts: "mtdparts=:>;..." */ + 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); +} diff --git a/board/st/stm32mp1/MAINTAINERS b/board/st/stm32mp1/MAINTAINERS index 2930947716..96c4559033 100644 --- a/board/st/stm32mp1/MAINTAINERS +++ b/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 diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 45068b1cd9..33cb7f6c4d 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -18,9 +17,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -35,6 +32,7 @@ #include #include #include +#include #include #include @@ -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_ - */ -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_ */ - strcat(env_name, dev); - tmp = env_get_mtdparts(env_name, tmp_mtdparts); - if (tmp) { - /* mtdids: "=, ...." */ - if (mtdids[0] != '\0') - strcat(mtdids, ","); - strcat(mtdids, dev); - strcat(mtdids, "="); - strcat(mtdids, dev); - - /* mtdparts: "mtdparts=:>;..." */ - 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_ */ - 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 -#include - -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 */ diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index c9289934ac..c7dd2926c9 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/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 diff --git a/configs/stm32mp15_dhcom_basic_defconfig b/configs/stm32mp15_dhcom_basic_defconfig index c2f3a5ebc1..c1c83eb4fc 100644 --- a/configs/stm32mp15_dhcom_basic_defconfig +++ b/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 diff --git a/configs/stm32mp15_optee_defconfig b/configs/stm32mp15_dhcor_basic_defconfig similarity index 58% rename from configs/stm32mp15_optee_defconfig rename to configs/stm32mp15_dhcor_basic_defconfig index 443e2c40b7..770fa47872 100644 --- a/configs/stm32mp15_optee_defconfig +++ b/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 diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index 33f6926fa9..ca4a10813b 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/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 diff --git a/doc/board/st/stm32mp1.rst b/doc/board/st/stm32mp1.rst index b3856be9a1..e74f7afdae 100644 --- a/doc/board/st/stm32mp1.rst +++ b/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. + * SPMin provided by TF-A or + * OP-TEE from specific partitions (teeh, teed, teex). -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 | - +-------------+-------------------------+------------+-------+ - -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 : - 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:: - - $> 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 - -- NAND (UBI partition used for NAND only boot or NOR + NAND boot):: - - $> 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 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 - - you can also dump the OTP and the PMIC NVM with:: - $> 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 19 -U otp.bin + $> dfu-util -d 0483:5720 -a 20 -U pmic.bin + + +When the board is booting for nor0 or nand0, +only the MTD partition on the boot devices are available, for example: + +- 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 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 27 -D st-image-weston-openstlinux-weston-stm32mp1_nand_4_256_multivolume.ubi + +- NAND (nand0 = alt 21):: + + $> 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 diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index 50df8425bf..0d0ea43fd2 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/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; } diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c index f55f834e7d..37a8cfa47a 100644 --- a/drivers/gpio/stm32_gpio.c +++ b/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), }; diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c index 6f3b2ad653..fa6fc94ad9 100644 --- a/drivers/mmc/stm32_sdmmc2.c +++ b/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) diff --git a/drivers/ram/stm32mp1/stm32mp1_ram.c b/drivers/ram/stm32mp1/stm32mp1_ram.c index 7b1adc5b24..8bcd861261 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ram.c +++ b/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 } diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c index e9e1600a1a..7a51b53f24 100644 --- a/drivers/usb/gadget/g_dnl.c +++ b/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; diff --git a/include/configs/dh_stm32mp1.h b/include/configs/dh_stm32mp1.h new file mode 100644 index 0000000000..89d317ba2b --- /dev/null +++ b/include/configs/dh_stm32mp1.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2020 Marek Vasut + * + * Configuration settings for the DH STM32MP15x SoMs + */ + +#ifndef __CONFIG_DH_STM32MP1_H__ +#define __CONFIG_DH_STM32MP1_H__ + +#include + +#define CONFIG_SPL_TARGET "u-boot.itb" + +#endif diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h index be5afe9c6f..f271b84a59 100644 --- a/include/configs/stm32mp1.h +++ b/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 -#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" diff --git a/include/dfu.h b/include/dfu.h index fb5260d903..2f0e335ec0 100644 --- a/include/dfu.h +++ b/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. diff --git a/include/g_dnl.h b/include/g_dnl.h index 6d461c73d3..836ee602c8 100644 --- a/include/g_dnl.h +++ b/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);