]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
Merge tag 'u-boot-stm32-20190606' of https://github.com/pchotard/u-boot
authorTom Rini <trini@konsulko.com>
Tue, 11 Jun 2019 21:22:22 +0000 (17:22 -0400)
committerTom Rini <trini@konsulko.com>
Tue, 11 Jun 2019 21:22:22 +0000 (17:22 -0400)
- Add Ethernet support for STM32MP1
- Add saveenv support for STM32MP1
- Add STM32MP1 Avenger96 board support
- Add SPI driver suport for STM32MP1
- Add watchdog support for STM32MP1
- Update power supply check via USB TYPE-C for STM32MP1 discovery board

27 files changed:
MAINTAINERS
arch/arm/dts/Makefile
arch/arm/dts/stm32mp157-pinctrl.dtsi
arch/arm/dts/stm32mp157-u-boot.dtsi
arch/arm/dts/stm32mp157a-avenger96-u-boot.dtsi [new file with mode: 0644]
arch/arm/dts/stm32mp157a-avenger96.dts [new file with mode: 0644]
arch/arm/dts/stm32mp157c-ev1.dts
arch/arm/dts/stm32mp157c.dtsi
arch/arm/mach-stm32mp/Kconfig
arch/arm/mach-stm32mp/cpu.c
board/st/stm32mp1/README
board/st/stm32mp1/stm32mp1.c
cmd/nvedit.c
configs/stm32mp15_basic_defconfig
configs/stm32mp15_trusted_defconfig
drivers/clk/clk_stm32mp1.c
drivers/mtd/mtd_uboot.c
drivers/net/dwc_eth_qos.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/stm32_spi.c [new file with mode: 0644]
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/stm32mp_wdt.c [new file with mode: 0644]
env/Kconfig
env/ext4.c
include/configs/stm32mp1.h

index 190050c99cd0562e810940f49f9336ac6f85a420..56bc543cdac2485ba7e83f2c299551b3cb38d7d9 100644 (file)
@@ -313,6 +313,8 @@ F:  drivers/ram/stm32mp1/
 F:     drivers/misc/stm32_rcc.c
 F:     drivers/reset/stm32-reset.c
 F:     drivers/spi/stm32_qspi.c
+F:     drivers/spi/stm32_spi.c
+F:     drivers/watchdog/stm32mp_wdt.c
 
 ARM STM STV0991
 M:     Vikas Manocha <vikas.manocha@st.com>
index 3d319663800a43eba5086b89418dcdb96c0f26da..528fb909d5b0980b0c999350e2752c0852d2cec3 100644 (file)
@@ -757,6 +757,7 @@ dtb-$(CONFIG_ARCH_STI) += stih410-b2260.dtb
 
 dtb-$(CONFIG_TARGET_STM32MP1) += \
        stm32mp157a-dk1.dtb \
+       stm32mp157a-avenger96.dtb \
        stm32mp157c-dk2.dtb \
        stm32mp157c-ed1.dtb \
        stm32mp157c-ev1.dtb
index 0aae69b0a04818a8e94075dfdf7ba3d8d88bc9d6..4c424c488d3d9ac758d1a9e1cf83da66101f6c7e 100644 (file)
                                                 <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */
                                                 <STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */
                                                 <STM32_PINMUX('B', 11, AF11)>, /* ETH_RGMII_TX_CTL */
-                                                <STM32_PINMUX('A', 2, AF11)>, /* ETH_MDIO */
                                                 <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */
                                        bias-disable;
                                        drive-push-pull;
-                                       slew-rate = <3>;
+                                       slew-rate = <2>;
                                };
                                pins2 {
+                                       pinmux = <STM32_PINMUX('A', 2, AF11)>; /* ETH_MDIO */
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <0>;
+                               };
+                               pins3 {
                                        pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
                                                 <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */
                                                 <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */
                                };
                        };
 
+                       fmc_pins_a: fmc-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('D', 4, AF12)>, /* FMC_NOE */
+                                                <STM32_PINMUX('D', 5, AF12)>, /* FMC_NWE */
+                                                <STM32_PINMUX('D', 11, AF12)>, /* FMC_A16_FMC_CLE */
+                                                <STM32_PINMUX('D', 12, AF12)>, /* FMC_A17_FMC_ALE */
+                                                <STM32_PINMUX('D', 14, AF12)>, /* FMC_D0 */
+                                                <STM32_PINMUX('D', 15, AF12)>, /* FMC_D1 */
+                                                <STM32_PINMUX('D', 0, AF12)>, /* FMC_D2 */
+                                                <STM32_PINMUX('D', 1, AF12)>, /* FMC_D3 */
+                                                <STM32_PINMUX('E', 7, AF12)>, /* FMC_D4 */
+                                                <STM32_PINMUX('E', 8, AF12)>, /* FMC_D5 */
+                                                <STM32_PINMUX('E', 9, AF12)>, /* FMC_D6 */
+                                                <STM32_PINMUX('E', 10, AF12)>, /* FMC_D7 */
+                                                <STM32_PINMUX('G', 9, AF12)>; /* FMC_NE2_FMC_NCE */
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <1>;
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('D', 6, AF12)>; /* FMC_NWAIT */
+                                       bias-pull-up;
+                               };
+                       };
+
+                       fmc_sleep_pins_a: fmc-sleep-0 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('D', 4, ANALOG)>, /* FMC_NOE */
+                                                <STM32_PINMUX('D', 5, ANALOG)>, /* FMC_NWE */
+                                                <STM32_PINMUX('D', 11, ANALOG)>, /* FMC_A16_FMC_CLE */
+                                                <STM32_PINMUX('D', 12, ANALOG)>, /* FMC_A17_FMC_ALE */
+                                                <STM32_PINMUX('D', 14, ANALOG)>, /* FMC_D0 */
+                                                <STM32_PINMUX('D', 15, ANALOG)>, /* FMC_D1 */
+                                                <STM32_PINMUX('D', 0, ANALOG)>, /* FMC_D2 */
+                                                <STM32_PINMUX('D', 1, ANALOG)>, /* FMC_D3 */
+                                                <STM32_PINMUX('E', 7, ANALOG)>, /* FMC_D4 */
+                                                <STM32_PINMUX('E', 8, ANALOG)>, /* FMC_D5 */
+                                                <STM32_PINMUX('E', 9, ANALOG)>, /* FMC_D6 */
+                                                <STM32_PINMUX('E', 10, ANALOG)>, /* FMC_D7 */
+                                                <STM32_PINMUX('D', 6, ANALOG)>, /* FMC_NWAIT */
+                                                <STM32_PINMUX('G', 9, ANALOG)>; /* FMC_NE2_FMC_NCE */
+                               };
+                       };
+
                        i2c1_pins_a: i2c1-0 {
                                pins {
                                        pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
                                };
                        };
 
+                       i2c1_pins_b: i2c1-1 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('F', 14, AF5)>, /* I2C1_SCL */
+                                                <STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */
+                                       bias-disable;
+                                       drive-open-drain;
+                                       slew-rate = <0>;
+                               };
+                       };
+
                        i2c2_pins_a: i2c2-0 {
                                pins {
                                        pinmux = <STM32_PINMUX('H', 4, AF4)>, /* I2C2_SCL */
                                };
                        };
 
+                       i2c2_pins_b: i2c2-1 {
+                               pins {
+                                       pinmux = <STM32_PINMUX('Z', 0, AF3)>, /* I2C2_SCL */
+                                                <STM32_PINMUX('H', 5, AF4)>; /* I2C2_SDA */
+                                       bias-disable;
+                                       drive-open-drain;
+                                       slew-rate = <0>;
+                               };
+                       };
+
                        i2c5_pins_a: i2c5-0 {
                                pins {
                                        pinmux = <STM32_PINMUX('A', 11, AF4)>, /* I2C5_SCL */
                                };
                        };
 
+                       spi2_pins_a: spi2-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('B', 10, AF5)>, /* SPI2_SCK */
+                                                <STM32_PINMUX('I', 0, AF5)>, /* SPI2_NSS */
+                                                <STM32_PINMUX('I', 3, AF5)>; /* SPI2_MOSI */
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <3>;
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('I', 2, AF5)>; /* SPI2_MISO */
+                                       bias-disable;
+                               };
+                       };
+
                        stusb1600_pins_a: stusb1600-0 {
                                pins {
                                        pinmux = <STM32_PINMUX('I', 11, ANALOG)>;
                                };
                        };
 
+                       uart4_pins_b: uart4-1 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('D', 1, AF8)>; /* UART4_TX */
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <0>;
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+                                       bias-disable;
+                               };
+                       };
+
+                       uart7_pins_a: uart7-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART4_TX */
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <0>;
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('E', 7, AF7)>, /* UART4_RX */
+                                                <STM32_PINMUX('E', 10, AF7)>, /* UART4_CTS */
+                                                <STM32_PINMUX('E', 9, AF7)>; /* UART4_RTS */
+                                       bias-disable;
+                               };
+                       };
+
                        usbotg_hs_pins_a: usbotg_hs-0 {
                                pins {
                                        pinmux = <STM32_PINMUX('A', 10, ANALOG)>; /* OTG_ID */
index ab6f673ea24c78885550618e9e9f1a32102e8cd1..09560e2d915474e890500039558912c2fe6bd092 100644 (file)
        compatible = "st,stm32-gpio";
        u-boot,dm-pre-reloc;
 };
+
+&iwdg2 {
+       u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/stm32mp157a-avenger96-u-boot.dtsi b/arch/arm/dts/stm32mp157a-avenger96-u-boot.dtsi
new file mode 100644 (file)
index 0000000..1ff681a
--- /dev/null
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Copyright : STMicroelectronics 2018
+ *
+ * Copyright (C) Linaro Ltd 2019 - All Rights Reserved
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ */
+
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include "stm32mp157-u-boot.dtsi"
+#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi"
+
+/ {
+       aliases {
+               mmc0 = &sdmmc1;
+               mmc1 = &sdmmc2;
+               usb0 = &usbotg_hs;
+       };
+
+       config {
+               u-boot,boot-led = "led1";
+               u-boot,error-led = "led4";
+       };
+};
+
+&i2c4 {
+       u-boot,dm-pre-reloc;
+};
+
+&i2c4_pins_a {
+       u-boot,dm-pre-reloc;
+       pins {
+               u-boot,dm-pre-reloc;
+       };
+};
+
+&pmic {
+       u-boot,dm-pre-reloc;
+};
+
+&rcc {
+       st,clksrc = <
+               CLK_MPU_PLL1P
+               CLK_AXI_PLL2P
+               CLK_MCU_PLL3P
+               CLK_PLL12_HSE
+               CLK_PLL3_HSE
+               CLK_PLL4_HSE
+               CLK_RTC_LSE
+               CLK_MCO1_DISABLED
+               CLK_MCO2_DISABLED
+       >;
+
+       st,clkdiv = <
+               1 /*MPU*/
+               0 /*AXI*/
+               0 /*MCU*/
+               1 /*APB1*/
+               1 /*APB2*/
+               1 /*APB3*/
+               1 /*APB4*/
+               2 /*APB5*/
+               23 /*RTC*/
+               0 /*MCO1*/
+               0 /*MCO2*/
+       >;
+
+       st,pkcs = <
+               CLK_CKPER_HSE
+               CLK_FMC_ACLK
+               CLK_QSPI_ACLK
+               CLK_ETH_DISABLED
+               CLK_SDMMC12_PLL4P
+               CLK_DSI_DSIPLL
+               CLK_STGEN_HSE
+               CLK_USBPHY_HSE
+               CLK_SPI2S1_PLL3Q
+               CLK_SPI2S23_PLL3Q
+               CLK_SPI45_HSI
+               CLK_SPI6_HSI
+               CLK_I2C46_HSI
+               CLK_SDMMC3_PLL4P
+               CLK_USBO_USBPHY
+               CLK_ADC_CKPER
+               CLK_CEC_LSE
+               CLK_I2C12_HSI
+               CLK_I2C35_HSI
+               CLK_UART1_HSI
+               CLK_UART24_HSI
+               CLK_UART35_HSI
+               CLK_UART6_HSI
+               CLK_UART78_HSI
+               CLK_SPDIF_PLL4P
+               CLK_FDCAN_PLL4Q
+               CLK_SAI1_PLL3Q
+               CLK_SAI2_PLL3Q
+               CLK_SAI3_PLL3Q
+               CLK_SAI4_PLL3Q
+               CLK_RNG1_LSI
+               CLK_RNG2_LSI
+               CLK_LPTIM1_PCLK1
+               CLK_LPTIM23_PCLK3
+               CLK_LPTIM45_LSE
+       >;
+
+       /* VCO = 1300.0 MHz => P = 650 (CPU) */
+       pll1: st,pll@0 {
+               cfg = < 2 80 0 0 0 PQR(1,0,0) >;
+               frac = < 0x800 >;
+               u-boot,dm-pre-reloc;
+       };
+
+       /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
+       pll2: st,pll@1 {
+               cfg = < 2 65 1 0 0 PQR(1,1,1) >;
+               frac = < 0x1400 >;
+               u-boot,dm-pre-reloc;
+       };
+
+       /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
+       pll3: st,pll@2 {
+               cfg = < 1 33 1 16 36 PQR(1,1,1) >;
+               frac = < 0x1a04 >;
+               u-boot,dm-pre-reloc;
+       };
+
+       /* VCO = 480.0 MHz => P = 120, Q = 40, R = 96 */
+       pll4: st,pll@3 {
+               cfg = < 1 39 3 11 4 PQR(1,1,1) >;
+               u-boot,dm-pre-reloc;
+       };
+};
+
+&sdmmc1 {
+       u-boot,dm-spl;
+};
+
+&sdmmc1_b4_pins_a {
+       u-boot,dm-spl;
+       pins {
+               u-boot,dm-spl;
+       };
+};
+
+&sdmmc1_dir_pins_a {
+       u-boot,dm-spl;
+       pins {
+               u-boot,dm-spl;
+       };
+};
+
+&sdmmc2 {
+       u-boot,dm-spl;
+};
+
+&sdmmc2_b4_pins_a {
+       u-boot,dm-spl;
+       pins {
+               u-boot,dm-spl;
+       };
+};
+
+&sdmmc2_d47_pins_a {
+       u-boot,dm-spl;
+       pins {
+               u-boot,dm-spl;
+       };
+};
+
+&uart4 {
+       u-boot,dm-pre-reloc;
+};
+
+&uart4_pins_b {
+       u-boot,dm-pre-reloc;
+       pins1 {
+               u-boot,dm-pre-reloc;
+       };
+       pins2 {
+               u-boot,dm-pre-reloc;
+       };
+};
+
+&usbotg_hs {
+       u-boot,force-b-session-valid;
+       hnp-srp-disable;
+};
+
+&v3v3 {
+       regulator-always-on;
+};
diff --git a/arch/arm/dts/stm32mp157a-avenger96.dts b/arch/arm/dts/stm32mp157a-avenger96.dts
new file mode 100644 (file)
index 0000000..dd08597
--- /dev/null
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
+ *
+ * Copyright (C) Linaro Ltd 2019 - All Rights Reserved
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ */
+
+/dts-v1/;
+
+#include "stm32mp157c.dtsi"
+#include "stm32mp157-pinctrl.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
+
+/ {
+       model = "Arrow Electronics STM32MP157A Avenger96 board";
+       compatible = "st,stm32mp157a-avenger96", "st,stm32mp157";
+
+       aliases {
+               ethernet0 = &ethernet0;
+               serial0 = &uart4;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory@c0000000 {
+               reg = <0xc0000000 0x40000000>;
+       };
+
+       led {
+               compatible = "gpio-leds";
+               led1 {
+                       label = "green:user1";
+                       gpios = <&gpioz 7 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+                       default-state = "off";
+               };
+
+               led2 {
+                       label = "green:user2";
+                       gpios = <&gpiof 3 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "mmc0";
+                       default-state = "off";
+               };
+
+               led3 {
+                       label = "green:user3";
+                       gpios = <&gpiog 0 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "mmc1";
+                       default-state = "off";
+               };
+
+               led4 {
+                       label = "green:user3";
+                       gpios = <&gpiog 1 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "none";
+                       default-state = "off";
+                       panic-indicator;
+               };
+
+               led5 {
+                       label = "yellow:wifi";
+                       gpios = <&gpioz 3 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "phy0tx";
+                       default-state = "off";
+               };
+
+               led6 {
+                       label = "blue:bt";
+                       gpios = <&gpioz 6 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "bluetooth-power";
+                       default-state = "off";
+               };
+       };
+};
+
+&ethernet0 {
+       status = "okay";
+       pinctrl-0 = <&ethernet0_rgmii_pins_a>;
+       pinctrl-1 = <&ethernet0_rgmii_pins_sleep_a>;
+       pinctrl-names = "default", "sleep";
+       phy-mode = "rgmii";
+       max-speed = <1000>;
+       phy-handle = <&phy0>;
+
+       mdio0 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "snps,dwmac-mdio";
+               phy0: ethernet-phy@7 {
+                       reg = <7>;
+               };
+       };
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins_b>;
+       i2c-scl-rising-time-ns = <185>;
+       i2c-scl-falling-time-ns = <20>;
+       status = "okay";
+       /delete-property/dmas;
+       /delete-property/dma-names;
+};
+
+&i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c2_pins_b>;
+       i2c-scl-rising-time-ns = <185>;
+       i2c-scl-falling-time-ns = <20>;
+       status = "okay";
+       /delete-property/dmas;
+       /delete-property/dma-names;
+};
+
+&i2c4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c4_pins_a>;
+       i2c-scl-rising-time-ns = <185>;
+       i2c-scl-falling-time-ns = <20>;
+       status = "okay";
+       /delete-property/dmas;
+       /delete-property/dma-names;
+
+       pmic: stpmic@33 {
+               compatible = "st,stpmic1";
+               reg = <0x33>;
+               interrupts-extended = <&exti 55 IRQ_TYPE_EDGE_FALLING>;
+               interrupt-controller;
+               #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";
+
+                       ldo1-supply = <&v3v3>;
+                       ldo2-supply = <&v3v3>;
+                       ldo3-supply = <&vdd_ddr>;
+                       ldo5-supply = <&v3v3>;
+                       ldo6-supply = <&v3v3>;
+                       pwr_sw1-supply = <&bst_out>;
+                       pwr_sw2-supply = <&bst_out>;
+
+                       vddcore: buck1 {
+                               regulator-name = "vddcore";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-initial-mode = <2>;
+                               regulator-over-current-protection;
+                       };
+
+                       vdd_ddr: buck2 {
+                               regulator-name = "vdd_ddr";
+                               regulator-min-microvolt = <1350000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-initial-mode = <2>;
+                               regulator-over-current-protection;
+                       };
+
+                       vdd: buck3 {
+                               regulator-name = "vdd";
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-always-on;
+                               st,mask_reset;
+                               regulator-initial-mode = <8>;
+                               regulator-over-current-protection;
+                       };
+
+                       v3v3: buck4 {
+                               regulator-name = "v3v3";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                               regulator-over-current-protection;
+                               regulator-initial-mode = <8>;
+                       };
+
+                       vdda: ldo1 {
+                               regulator-name = "vdda";
+                               regulator-min-microvolt = <2900000>;
+                               regulator-max-microvolt = <2900000>;
+                               interrupts = <IT_CURLIM_LDO1 0>;
+                               interrupt-parent = <&pmic>;
+                       };
+
+                       v2v8: ldo2 {
+                               regulator-name = "v2v8";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               interrupts = <IT_CURLIM_LDO2 0>;
+                               interrupt-parent = <&pmic>;
+                       };
+
+                       vtt_ddr: ldo3 {
+                               regulator-name = "vtt_ddr";
+                               regulator-min-microvolt = <0000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               regulator-over-current-protection;
+                       };
+
+                       vdd_usb: ldo4 {
+                               regulator-name = "vdd_usb";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               interrupts = <IT_CURLIM_LDO4 0>;
+                               interrupt-parent = <&pmic>;
+                       };
+
+                       vdd_sd: ldo5 {
+                               regulator-name = "vdd_sd";
+                               regulator-min-microvolt = <2900000>;
+                               regulator-max-microvolt = <2900000>;
+                               interrupts = <IT_CURLIM_LDO5 0>;
+                               interrupt-parent = <&pmic>;
+                               regulator-boot-on;
+                       };
+
+                       v1v8: ldo6 {
+                               regulator-name = "v1v8";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               interrupts = <IT_CURLIM_LDO6 0>;
+                               interrupt-parent = <&pmic>;
+                       };
+
+                       vref_ddr: vref_ddr {
+                               regulator-name = "vref_ddr";
+                               regulator-always-on;
+                               regulator-over-current-protection;
+                       };
+
+                       bst_out: boost {
+                               regulator-name = "bst_out";
+                               interrupts = <IT_OCP_BOOST 0>;
+                               interrupt-parent = <&pmic>;
+                       };
+
+                       vbus_otg: pwr_sw1 {
+                               regulator-name = "vbus_otg";
+                               interrupts = <IT_OCP_OTG 0>;
+                               interrupt-parent = <&pmic>;
+                               regulator-active-discharge;
+                       };
+
+                       vbus_sw: pwr_sw2 {
+                               regulator-name = "vbus_sw";
+                               interrupts = <IT_OCP_SWOUT 0>;
+                               interrupt-parent = <&pmic>;
+                               regulator-active-discharge;
+                       };
+               };
+
+               onkey {
+                       compatible = "st,stpmic1-onkey";
+                       interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 1>;
+                       interrupt-names = "onkey-falling", "onkey-rising";
+                       status = "okay";
+               };
+
+               watchdog {
+                       compatible = "st,stpmic1-wdt";
+                       status = "disabled";
+               };
+       };
+};
+
+&iwdg2 {
+       timeout-sec = <32>;
+       status = "okay";
+};
+
+&pwr {
+       pwr-supply = <&vdd>;
+};
+
+&rng1 {
+       status = "okay";
+};
+
+&rtc {
+       status = "okay";
+};
+
+&sdmmc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
+       broken-cd;
+       st,sig-dir;
+       st,neg-edge;
+       st,use-ckin;
+       bus-width = <4>;
+       vmmc-supply = <&vdd_sd>;
+       status = "okay";
+};
+
+&sdmmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
+       non-removable;
+       no-sd;
+       no-sdio;
+       st,neg-edge;
+       bus-width = <8>;
+       vmmc-supply = <&v3v3>;
+       mmc-ddr-3_3v;
+       status = "okay";
+};
+
+&spi2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi2_pins_a>;
+       status = "okay";
+};
+
+&uart4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart4_pins_b>;
+       status = "okay";
+};
+
+&uart7 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart7_pins_a>;
+       status = "okay";
+};
+
+&usbh_ehci {
+       phys = <&usbphyc_port0>;
+       phy-names = "usb";
+       status = "okay";
+};
+
+&usbotg_hs {
+       dr_mode = "peripheral";
+       phys = <&usbphyc_port1 0>;
+       phy-names = "usb2-phy";
+       status = "okay";
+};
+
+&usbphyc {
+       status = "okay";
+};
+
+&usbphyc_port0 {
+       phy-supply = <&vdd_usb>;
+};
+
+&usbphyc_port1 {
+       phy-supply = <&vdd_usb>;
+};
index a6ee37924fe18fe574add7271b21358dfd678376..663e52aa3142e229a124411f1891cd070c3ec11b 100644 (file)
@@ -78,7 +78,7 @@
        pinctrl-0 = <&ethernet0_rgmii_pins_a>;
        pinctrl-1 = <&ethernet0_rgmii_pins_sleep_a>;
        pinctrl-names = "default", "sleep";
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        max-speed = <1000>;
        phy-handle = <&phy0>;
 
        };
 };
 
+&fmc {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&fmc_pins_a>;
+       pinctrl-1 = <&fmc_sleep_pins_a>;
+       status = "okay";
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       nand: nand@0 {
+               reg = <0>;
+               nand-on-flash-bbt;
+               #address-cells = <1>;
+               #size-cells = <1>;
+       };
+};
+
 &i2c2 {
        pinctrl-names = "default";
        pinctrl-0 = <&i2c2_pins_a>;
index 94634336a5e17eb5dadfd4dcfdadedb8363a00be..73215855ccd2659d5e3a2ef4d42a2678be317957 100644 (file)
                        dma-requests = <48>;
                };
 
+               fmc: nand-controller@58002000 {
+                       compatible = "st,stm32mp15-fmc2";
+                       reg = <0x58002000 0x1000>,
+                             <0x80000000 0x1000>,
+                             <0x88010000 0x1000>,
+                             <0x88020000 0x1000>,
+                             <0x81000000 0x1000>,
+                             <0x89010000 0x1000>,
+                             <0x89020000 0x1000>;
+                       interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&rcc FMC_K>;
+                       resets = <&rcc FMC_R>;
+                       status = "disabled";
+               };
+
                qspi: spi@58003000 {
                        compatible = "st,stm32f469-qspi";
                        reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
                        compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
                        reg = <0x5800a000 0x2000>;
                        reg-names = "stmmaceth";
-                       interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-names = "macirq";
+                       interrupts-extended =
+                               <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+                               <&intc GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
+                               <&exti 70 1>;
+                       interrupt-names = "macirq",
+                                         "eth_wake_irq",
+                                         "stm32_pwr_wakeup";
                        clock-names = "stmmaceth",
                                      "mac-clk-tx",
                                      "mac-clk-rx",
-                                     "ethstp",
-                                     "syscfg-clk";
+                                     "ethstp";
                        clocks = <&rcc ETHMAC>,
                                 <&rcc ETHTX>,
                                 <&rcc ETHRX>,
-                                <&rcc ETHSTP>,
-                                <&rcc SYSCFG>;
+                                <&rcc ETHSTP>;
                        st,syscon = <&syscfg 0x4>;
                        snps,mixed-burst;
                        snps,pbl = <2>;
+                       snps,en-tx-lpi-clockgating;
                        snps,axi-config = <&stmmac_axi_config_0>;
                        snps,tso;
                        status = "disabled";
index 77f66c65c03ecbbce3c55b2df38b50b5351027b6..d9ad6b423b0dba6eb098558ef321d429149d4c6b 100644 (file)
@@ -17,6 +17,7 @@ config SPL
        select SPL_DM_RESET
        select SPL_SERIAL_SUPPORT
        select SPL_SYSCON
+       select SPL_WATCHDOG_SUPPORT
        imply BOOTSTAGE_STASH if SPL_BOOTSTAGE
        imply SPL_BOOTSTAGE if BOOTSTAGE
        imply SPL_DISPLAY_PRINT
@@ -29,7 +30,7 @@ config SYS_MALLOC_LEN
        default 0x2000000
 
 config ENV_SIZE
-       default 0x1000
+       default 0x2000
 
 config TARGET_STM32MP1
        bool "Support stm32mp1xx"
index 7b4431c9c75cf3035a6fc7d0bb189907f259ecfb..e1a0a136809c0aa9e9ef61f469ff6b60a54108da 100644 (file)
@@ -481,7 +481,7 @@ static int setup_mac_address(void)
                enetaddr[i] = ((uint8_t *)&otp)[i];
 
        if (!is_valid_ethaddr(enetaddr)) {
-               pr_err("invalid MAC address in OTP %pM", enetaddr);
+               pr_err("invalid MAC address in OTP %pM\n", enetaddr);
                return -EINVAL;
        }
        pr_debug("OTP MAC address = %pM\n", enetaddr);
index 1cd3534ae4e7289a6dfaf4f8b9a15fc052f7a6a7..b0c83250612d316de0b3be2a8b48afddab1398e5 100644 (file)
@@ -37,6 +37,7 @@ Currently the following boards are supported:
 + stm32mp157c-ed1
 + stm32mp157a-dk1
 + stm32mp157c-dk2
++ stm32mp157a-avenger96
 
 3. Boot Sequences
 =================
@@ -84,6 +85,9 @@ the supported device trees for stm32mp157 are:
 + dk2: Discovery board = dk1 with a BT/WiFI combo and a DSI panel
   dts: stm32mp157c-dk2
 
++ avenger96: Avenger96 board from Arrow Electronics
+  dts: stm32mp157a-avenger96
+
 5. Build Procedure
 ==================
 
@@ -140,6 +144,11 @@ the supported device trees for stm32mp157 are:
        # make stm32mp15_basic_defconfig
        # make DEVICE_TREE=stm32mp157c-dk2 all
 
+  d) basic boot on avenger96
+       # export KBUILD_OUTPUT=stm32mp15_basic
+       # make stm32mp15_basic_defconfig
+       # make DEVICE_TREE=stm32mp157a-avenger96 all
+
 6. Output files
 
   BootRom and TF-A expect binaries with STM32 image header
@@ -182,6 +191,20 @@ You can select the boot mode, on the board ed1 with the switch SW1
   SD-Card      1      1
   Recovery     0      0
 
+- Boot mode of Avenger96 can be selected using switch S3
+
+ -----------------------------------
+  Boot Mode   BOOT2   BOOT1   BOOT0
+ -----------------------------------
+  Recovery     0       0       0
+  NOR          0       0       1
+  SD-Card      1       0       1
+  eMMC         0       1       0
+  NAND         0       1       1
+  Reserved     1       0       0
+  Recovery     1       1       0
+  SD-Card      1       1       1
+
 Recovery is a boot from serial link (UART/USB) and it is used with
 STM32CubeProgrammer tool to load executable in RAM and to update the flash
 devices available on the board (NOR/NAND/eMMC/SDCARD).
index 76917b022ede019176244bdd007b8f3b9b74c8d7..776929350f9b5dca7745307209d5ebb11d392b91 100644 (file)
@@ -7,6 +7,7 @@
 #include <config.h>
 #include <clk.h>
 #include <dm.h>
+#include <environment.h>
 #include <g_dnl.h>
 #include <generic-phy.h>
 #include <i2c.h>
@@ -19,6 +20,7 @@
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <asm/arch/stm32.h>
+#include <asm/arch/sys_proto.h>
 #include <power/regulator.h>
 #include <usb/dwc2_udc.h>
 
 #define SYSCFG_PMCSETR_ETH_SELMII      BIT(20)
 
 #define SYSCFG_PMCSETR_ETH_SEL_MASK    GENMASK(23, 21)
-#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII        (0 << 21)
-#define SYSCFG_PMCSETR_ETH_SEL_RGMII   (1 << 21)
-#define SYSCFG_PMCSETR_ETH_SEL_RMII    (4 << 21)
+#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII        0
+#define SYSCFG_PMCSETR_ETH_SEL_RGMII   BIT(21)
+#define SYSCFG_PMCSETR_ETH_SEL_RMII    BIT(23)
 
 /*
  * Get a global data pointer
  */
 DECLARE_GLOBAL_DATA_PTR;
 
+#define USB_LOW_THRESHOLD_UV           200000
 #define USB_WARNING_LOW_THRESHOLD_UV   660000
 #define USB_START_LOW_THRESHOLD_UV     1230000
-#define USB_START_HIGH_THRESHOLD_UV    2100000
+#define USB_START_HIGH_THRESHOLD_UV    2150000
 
 int checkboard(void)
 {
@@ -263,9 +266,10 @@ static int board_check_usb_power(void)
        ofnode node;
        unsigned int raw;
        int max_uV = 0;
+       int min_uV = USB_START_HIGH_THRESHOLD_UV;
        int ret, uV, adc_count;
-       u8 i, nb_blink;
-
+       u32 nb_blink;
+       u8 i;
        node = ofnode_path("/config");
        if (!ofnode_valid(node)) {
                debug("%s: no /config node?\n", __func__);
@@ -317,6 +321,8 @@ static int board_check_usb_power(void)
                if (!adc_raw_to_uV(adc, raw, &uV)) {
                        if (uV > max_uV)
                                max_uV = uV;
+                       if (uV < min_uV)
+                               min_uV = uV;
                        pr_debug("%s: %s[%02d] = %u, %d uV\n", __func__,
                                 adc->name, adc_args.args[0], raw, uV);
                } else {
@@ -331,27 +337,66 @@ static int board_check_usb_power(void)
         * continue.
         */
        if (max_uV > USB_START_LOW_THRESHOLD_UV &&
-           max_uV < USB_START_HIGH_THRESHOLD_UV)
+           max_uV <= USB_START_HIGH_THRESHOLD_UV &&
+           min_uV <= USB_LOW_THRESHOLD_UV)
                return 0;
 
-       /* Display warning message and make u-boot,error-led blinking */
-       pr_err("\n*******************************************\n");
+       pr_err("****************************************************\n");
+
+       /*
+        * If highest and lowest value are either both below
+        * USB_LOW_THRESHOLD_UV or both above USB_LOW_THRESHOLD_UV, that
+        * means USB TYPE-C is in unattached mode, this is an issue, make
+        * u-boot,error-led blinking and stop boot process.
+        */
+       if ((max_uV > USB_LOW_THRESHOLD_UV &&
+            min_uV > USB_LOW_THRESHOLD_UV) ||
+            (max_uV <= USB_LOW_THRESHOLD_UV &&
+            min_uV <= USB_LOW_THRESHOLD_UV)) {
+               pr_err("* ERROR USB TYPE-C connection in unattached mode   *\n");
+               pr_err("* Check that USB TYPE-C cable is correctly plugged *\n");
+               /* with 125ms interval, led will blink for 17.02 years ....*/
+               nb_blink = U32_MAX;
+       }
 
-       if (max_uV < USB_WARNING_LOW_THRESHOLD_UV) {
-               pr_err("*   WARNING 500mA power supply detected   *\n");
+       if (max_uV > USB_LOW_THRESHOLD_UV &&
+           max_uV <= USB_WARNING_LOW_THRESHOLD_UV &&
+           min_uV <= USB_LOW_THRESHOLD_UV) {
+               pr_err("*        WARNING 500mA power supply detected       *\n");
                nb_blink = 2;
-       } else {
-               pr_err("* WARNING 1.5A power supply detected      *\n");
+       }
+
+       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");
                nb_blink = 3;
        }
 
-       pr_err("* Current too low, use a 3A power supply! *\n");
-       pr_err("*******************************************\n\n");
+       /*
+        * If highest value is above 2.15 Volts that means that the USB TypeC
+        * supplies more than 3 Amp, this is not compliant with TypeC specification
+        */
+       if (max_uV > USB_START_HIGH_THRESHOLD_UV) {
+               pr_err("*      USB TYPE-C charger not compliant with       *\n");
+               pr_err("*                   specification                  *\n");
+               pr_err("****************************************************\n\n");
+               /* with 125ms interval, led will blink for 17.02 years ....*/
+               nb_blink = U32_MAX;
+       } else {
+               pr_err("*     Current too low, use a 3A power supply!      *\n");
+               pr_err("****************************************************\n\n");
+       }
 
        ret = get_led(&led, "u-boot,error-led");
-       if (ret)
+       if (ret) {
+               /* in unattached case, the boot process must be stopped */
+               if (nb_blink == U32_MAX)
+                       hang();
                return ret;
+       }
 
+       /* make u-boot,error-led blinking */
        for (i = 0; i < nb_blink * 2; i++) {
                led_set_state(led, LEDST_TOGGLE);
                mdelay(125);
@@ -504,3 +549,199 @@ void board_quiesce_devices(void)
 {
        setup_led(LEDST_OFF);
 }
+
+/* board interface eth init */
+/* this is a weak define that we are overriding */
+int board_interface_eth_init(phy_interface_t interface_type,
+                            bool eth_clk_sel_reg, bool eth_ref_clk_sel_reg)
+{
+       u8 *syscfg;
+       u32 value;
+
+       syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
+
+       if (!syscfg)
+               return -ENODEV;
+
+       switch (interface_type) {
+       case PHY_INTERFACE_MODE_MII:
+               value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
+                       SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
+               debug("%s: PHY_INTERFACE_MODE_MII\n", __func__);
+               break;
+       case PHY_INTERFACE_MODE_GMII:
+               if (eth_clk_sel_reg)
+                       value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
+                               SYSCFG_PMCSETR_ETH_CLK_SEL;
+               else
+                       value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII;
+               debug("%s: PHY_INTERFACE_MODE_GMII\n", __func__);
+               break;
+       case PHY_INTERFACE_MODE_RMII:
+               if (eth_ref_clk_sel_reg)
+                       value = SYSCFG_PMCSETR_ETH_SEL_RMII |
+                               SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
+               else
+                       value = SYSCFG_PMCSETR_ETH_SEL_RMII;
+               debug("%s: PHY_INTERFACE_MODE_RMII\n", __func__);
+               break;
+       case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+               if (eth_clk_sel_reg)
+                       value = SYSCFG_PMCSETR_ETH_SEL_RGMII |
+                               SYSCFG_PMCSETR_ETH_CLK_SEL;
+               else
+                       value = SYSCFG_PMCSETR_ETH_SEL_RGMII;
+               debug("%s: PHY_INTERFACE_MODE_RGMII\n", __func__);
+               break;
+       default:
+               debug("%s: Do not manage %d interface\n",
+                     __func__, interface_type);
+               /* Do not manage others interfaces */
+               return -EINVAL;
+       }
+
+       /* clear and set ETH configuration bits */
+       writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII |
+              SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL,
+              syscfg + SYSCFG_PMCCLRR);
+       writel(value, syscfg + SYSCFG_PMCSETR);
+
+       return 0;
+}
+
+enum env_location env_get_location(enum env_operation op, int prio)
+{
+       u32 bootmode = get_bootmode();
+
+       if (prio)
+               return ENVL_UNKNOWN;
+
+       switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
+#ifdef CONFIG_ENV_IS_IN_EXT4
+       case BOOT_FLASH_SD:
+       case BOOT_FLASH_EMMC:
+               return ENVL_EXT4;
+#endif
+#ifdef CONFIG_ENV_IS_IN_UBI
+       case BOOT_FLASH_NAND:
+               return ENVL_UBI;
+#endif
+#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
+       case BOOT_FLASH_NOR:
+               return ENVL_SPI_FLASH;
+#endif
+       default:
+               return ENVL_NOWHERE;
+       }
+}
+
+#if defined(CONFIG_ENV_IS_IN_EXT4)
+const char *env_ext4_get_intf(void)
+{
+       u32 bootmode = get_bootmode();
+
+       switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
+       case BOOT_FLASH_SD:
+       case BOOT_FLASH_EMMC:
+               return "mmc";
+       default:
+               return "";
+       }
+}
+
+const char *env_ext4_get_dev_part(void)
+{
+       static char *const dev_part[] = {"0:auto", "1:auto", "2:auto"};
+       u32 bootmode = get_bootmode();
+
+       return dev_part[(bootmode & TAMP_BOOT_INSTANCE_MASK) - 1];
+}
+#endif
+
+#ifdef CONFIG_SYS_MTDPARTS_RUNTIME
+
+#define MTDPARTS_LEN           256
+#define MTDIDS_LEN             128
+
+/**
+ * The mtdparts_nand0 and mtdparts_nor0 variable tends to be long.
+ * If we need to access it before the env is relocated, then we need
+ * to use our own stack buffer. gd->env_buf will be too small.
+ *
+ * @param buf temporary buffer pointer MTDPARTS_LEN long
+ * @return mtdparts variable string, NULL if not found
+ */
+static const char *env_get_mtdparts(const char *str, char *buf)
+{
+       if (gd->flags & GD_FLG_ENV_READY)
+               return env_get(str);
+       if (env_get_f(str, buf, MTDPARTS_LEN) != -1)
+               return buf;
+
+       return NULL;
+}
+
+/**
+ * update the variables "mtdids" and "mtdparts" with content of mtdparts_<dev>
+ */
+static void board_get_mtdparts(const char *dev,
+                              char *mtdids,
+                              char *mtdparts)
+{
+       char env_name[32] = "mtdparts_";
+       char tmp_mtdparts[MTDPARTS_LEN];
+       const char *tmp;
+
+       /* name of env variable to read = mtdparts_<dev> */
+       strcat(env_name, dev);
+       tmp = env_get_mtdparts(env_name, tmp_mtdparts);
+       if (tmp) {
+               /* mtdids: "<dev>=<dev>, ...." */
+               if (mtdids[0] != '\0')
+                       strcat(mtdids, ",");
+               strcat(mtdids, dev);
+               strcat(mtdids, "=");
+               strcat(mtdids, dev);
+
+               /* mtdparts: "mtdparts=<dev>:<mtdparts_<dev>>;..." */
+               if (mtdparts[0] != '\0')
+                       strncat(mtdparts, ";", MTDPARTS_LEN);
+               else
+                       strcat(mtdparts, "mtdparts=");
+               strncat(mtdparts, dev, MTDPARTS_LEN);
+               strncat(mtdparts, ":", MTDPARTS_LEN);
+               strncat(mtdparts, tmp, MTDPARTS_LEN);
+       }
+}
+
+void board_mtdparts_default(const char **mtdids, const char **mtdparts)
+{
+       struct udevice *dev;
+       static char parts[2 * 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));
+
+       if (!uclass_get_device(UCLASS_MTD, 0, &dev))
+               board_get_mtdparts("nand0", ids, parts);
+
+       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
index 52c242b4f62277e8bff19a9536d32179b949f08e..49d3b5bdf466276bea6c33479b0b2139ed3160f5 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if    !defined(CONFIG_ENV_IS_IN_EEPROM)       && \
-       !defined(CONFIG_ENV_IS_IN_FLASH)        && \
-       !defined(CONFIG_ENV_IS_IN_MMC)          && \
-       !defined(CONFIG_ENV_IS_IN_FAT)          && \
-       !defined(CONFIG_ENV_IS_IN_EXT4)         && \
-       !defined(CONFIG_ENV_IS_IN_NAND)         && \
-       !defined(CONFIG_ENV_IS_IN_NVRAM)        && \
-       !defined(CONFIG_ENV_IS_IN_ONENAND)      && \
-       !defined(CONFIG_ENV_IS_IN_SATA)         && \
-       !defined(CONFIG_ENV_IS_IN_SPI_FLASH)    && \
-       !defined(CONFIG_ENV_IS_IN_REMOTE)       && \
-       !defined(CONFIG_ENV_IS_IN_UBI)          && \
+#if    defined(CONFIG_ENV_IS_IN_EEPROM)        || \
+       defined(CONFIG_ENV_IS_IN_FLASH)         || \
+       defined(CONFIG_ENV_IS_IN_MMC)           || \
+       defined(CONFIG_ENV_IS_IN_FAT)           || \
+       defined(CONFIG_ENV_IS_IN_EXT4)          || \
+       defined(CONFIG_ENV_IS_IN_NAND)          || \
+       defined(CONFIG_ENV_IS_IN_NVRAM)         || \
+       defined(CONFIG_ENV_IS_IN_ONENAND)       || \
+       defined(CONFIG_ENV_IS_IN_SATA)          || \
+       defined(CONFIG_ENV_IS_IN_SPI_FLASH)     || \
+       defined(CONFIG_ENV_IS_IN_REMOTE)        || \
+       defined(CONFIG_ENV_IS_IN_UBI)
+
+#define ENV_IS_IN_DEVICE
+
+#endif
+
+#if    !defined(ENV_IS_IN_DEVICE)              && \
        !defined(CONFIG_ENV_IS_NOWHERE)
 # error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|MMC|FAT|EXT4|\
 NAND|NVRAM|ONENAND|SATA|SPI_FLASH|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE
@@ -749,7 +755,7 @@ ulong env_get_ulong(const char *name, int base, ulong default_val)
 }
 
 #ifndef CONFIG_SPL_BUILD
-#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
 static int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc,
                       char * const argv[])
 {
@@ -1205,7 +1211,7 @@ static cmd_tbl_t cmd_env_sub[] = {
 #if defined(CONFIG_CMD_RUN)
        U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""),
 #endif
-#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
        U_BOOT_CMD_MKENT(save, 1, 0, do_env_save, "", ""),
 #endif
        U_BOOT_CMD_MKENT(set, CONFIG_SYS_MAXARGS, 0, do_env_set, "", ""),
@@ -1280,7 +1286,7 @@ static char env_help_text[] =
 #if defined(CONFIG_CMD_RUN)
        "env run var [...] - run commands in an environment variable\n"
 #endif
-#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
        "env save - save environment\n"
 #endif
 #if defined(CONFIG_CMD_NVEDIT_EFI)
index 0ea9dff43ded9c5ad5b802f91938030eb4699ca2..4aa184fb5b51cf0d2ee6c0821add899f0bbb6d6a 100644 (file)
@@ -29,6 +29,8 @@ CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_CACHE=y
@@ -37,8 +39,19 @@ CONFIG_CMD_TIMER=y
 CONFIG_CMD_PMIC=y
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_CMD_UBI=y
 # CONFIG_SPL_DOS_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
+CONFIG_ENV_IS_NOWHERE=y
+CONFIG_ENV_IS_IN_EXT4=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_IS_IN_UBI=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_STM32_ADC=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
@@ -55,6 +68,20 @@ CONFIG_LED_GPIO=y
 CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_STM32_SDMMC2=y
+CONFIG_MTD=y
+CONFIG_NAND=y
+CONFIG_NAND_STM32_FMC2=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+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_DM_ETH=y
+CONFIG_DWC_ETH_QOS=y
 CONFIG_PHY=y
 CONFIG_PHY_STM32_USBPHYC=y
 CONFIG_PINCONF=y
@@ -69,6 +96,10 @@ CONFIG_DM_REGULATOR_STM32_VREFBUF=y
 CONFIG_DM_REGULATOR_STPMIC1=y
 CONFIG_SERIAL_RX_BUFFER=y
 CONFIG_STM32_SERIAL=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_STM32_QSPI=y
+CONFIG_STM32_SPI=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB_GADGET=y
@@ -79,3 +110,5 @@ CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0483
 CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
 CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_WDT=y
+CONFIG_WDT_STM32MP=y
index 3c2bb75564d40546f3749670058872bd88cef7be..66361c87155930bdf9d9318d7faa87370e7ebc66 100644 (file)
@@ -22,6 +22,8 @@ CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_CACHE=y
@@ -30,7 +32,18 @@ CONFIG_CMD_TIMER=y
 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_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_IS_IN_UBI=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_STM32_ADC=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
@@ -47,6 +60,20 @@ CONFIG_LED_GPIO=y
 CONFIG_DM_MMC=y
 CONFIG_SUPPORT_EMMC_BOOT=y
 CONFIG_STM32_SDMMC2=y
+CONFIG_MTD=y
+CONFIG_NAND=y
+CONFIG_NAND_STM32_FMC2=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+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_DM_ETH=y
+CONFIG_ETH_DESIGNWARE=y
 CONFIG_PHY=y
 CONFIG_PHY_STM32_USBPHYC=y
 CONFIG_PINCONF=y
@@ -59,6 +86,10 @@ CONFIG_DM_REGULATOR_STM32_VREFBUF=y
 CONFIG_DM_REGULATOR_STPMIC1=y
 CONFIG_SERIAL_RX_BUFFER=y
 CONFIG_STM32_SERIAL=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_STM32_QSPI=y
+CONFIG_STM32_SPI=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB_GADGET=y
@@ -69,3 +100,5 @@ CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0483
 CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
 CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_WDT=y
+CONFIG_WDT_STM32MP=y
index 6272b00b9efc7b976d2132f7900977937260789b..f295e4864b396a770e2dc91887ad486faafd8681 100644 (file)
@@ -90,6 +90,7 @@
 #define RCC_PLL4CSGR           0x8A4
 #define RCC_I2C12CKSELR                0x8C0
 #define RCC_I2C35CKSELR                0x8C4
+#define RCC_SPI2S1CKSELR       0x8D8
 #define RCC_UART6CKSELR                0x8E4
 #define RCC_UART24CKSELR       0x8E8
 #define RCC_UART35CKSELR       0x8EC
@@ -298,6 +299,7 @@ enum stm32mp1_parent_sel {
        _STGEN_SEL,
        _DSI_SEL,
        _ADC12_SEL,
+       _SPI1_SEL,
        _PARENT_SEL_NB,
        _UNKNOWN_SEL = 0xff,
 };
@@ -519,6 +521,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
        STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL),
        STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
 
+       STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 8, SPI1_K, _SPI1_SEL),
        STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
 
        STM32MP1_CLK_SET_CLR_F(RCC_MP_APB3ENSETR, 13, VREF, _PCLK3),
@@ -555,7 +558,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
 
        STM32MP1_CLK_SET_CLR(RCC_MP_AHB5ENSETR, 0, GPIOZ, _UNKNOWN_SEL),
 
-       STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 7, ETHCK, _ETH_SEL),
+       STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 7, ETHCK_K, _ETH_SEL),
        STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 8, ETHTX, _UNKNOWN_SEL),
        STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 9, ETHRX, _UNKNOWN_SEL),
        STM32MP1_CLK_SET_CLR_F(RCC_MP_AHB6ENSETR, 10, ETHMAC, _ACLK),
@@ -589,6 +592,8 @@ static const u8 usbo_parents[] = {_PLL4_R, _USB_PHY_48};
 static const u8 stgen_parents[] = {_HSI_KER, _HSE_KER};
 static const u8 dsi_parents[] = {_DSI_PHY, _PLL4_P};
 static const u8 adc_parents[] = {_PLL4_R, _CK_PER, _PLL3_Q};
+static const u8 spi_parents[] = {_PLL4_P, _PLL3_Q, _I2S_CKIN, _CK_PER,
+                                _PLL3_R};
 
 static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
        STM32MP1_CLK_PARENT(_I2C12_SEL, RCC_I2C12CKSELR, 0, 0x7, i2c12_parents),
@@ -613,6 +618,7 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
        STM32MP1_CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents),
        STM32MP1_CLK_PARENT(_DSI_SEL, RCC_DSICKSELR, 0, 0x1, dsi_parents),
        STM32MP1_CLK_PARENT(_ADC12_SEL, RCC_ADCCKSELR, 0, 0x1, adc_parents),
+       STM32MP1_CLK_PARENT(_SPI1_SEL, RCC_SPI2S1CKSELR, 0, 0x7, spi_parents),
 };
 
 #ifdef STM32MP1_CLOCK_TREE_INIT
@@ -727,6 +733,7 @@ char * const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] = {
        [_STGEN_SEL] = "STGEN",
        [_DSI_SEL] = "DSI",
        [_ADC12_SEL] = "ADC12",
+       [_SPI1_SEL] = "SPI1",
 };
 
 static const struct stm32mp1_clk_data stm32mp1_data = {
index d638f700d041e32757f1e3dea3a005085cfd2a12..0a41ed477c1db4e0f09a16f8ea7234f754a3505a 100644 (file)
@@ -122,7 +122,6 @@ static const char *get_mtdparts(void)
 {
        __maybe_unused const char *mtdids = NULL;
        static char tmp_parts[MTDPARTS_MAXLEN];
-       static bool use_defaults = true;
        const char *mtdparts = NULL;
 
        if (gd->flags & GD_FLG_ENV_READY)
@@ -130,7 +129,7 @@ static const char *get_mtdparts(void)
        else if (env_get_f("mtdparts", tmp_parts, sizeof(tmp_parts)) != -1)
                mtdparts = tmp_parts;
 
-       if (mtdparts || !use_defaults)
+       if (mtdparts)
                return mtdparts;
 
 #if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
@@ -144,8 +143,6 @@ static const char *get_mtdparts(void)
        if (mtdparts)
                env_set("mtdparts", mtdparts);
 
-       use_defaults = false;
-
        return mtdparts;
 }
 
index 590e756f5c6ba8b265ed5b8b394b24f098c7bd53..07b36675a748ba5a65e63ab7ab84da307d23ab3f 100644 (file)
@@ -26,7 +26,6 @@
  *    supports a single RGMII PHY. This configuration also has SW control over
  *    all clock and reset signals to the HW block.
  */
-
 #include <common.h>
 #include <clk.h>
 #include <dm.h>
@@ -95,6 +94,7 @@ struct eqos_mac_regs {
 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK                 3
 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED          0
 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB          2
+#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV           1
 
 #define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT                 0
 #define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK                  0xff
@@ -108,6 +108,7 @@ struct eqos_mac_regs {
 #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT                        16
 #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT                 8
 #define EQOS_MAC_MDIO_ADDRESS_CR_20_35                 2
+#define EQOS_MAC_MDIO_ADDRESS_CR_250_300               5
 #define EQOS_MAC_MDIO_ADDRESS_SKAP                     BIT(4)
 #define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT                        2
 #define EQOS_MAC_MDIO_ADDRESS_GOC_READ                 3
@@ -260,6 +261,29 @@ struct eqos_desc {
 
 struct eqos_config {
        bool reg_access_always_ok;
+       int mdio_wait;
+       int swr_wait;
+       int config_mac;
+       int config_mac_mdio;
+       phy_interface_t (*interface)(struct udevice *dev);
+       struct eqos_ops *ops;
+};
+
+struct eqos_ops {
+       void (*eqos_inval_desc)(void *desc);
+       void (*eqos_flush_desc)(void *desc);
+       void (*eqos_inval_buffer)(void *buf, size_t size);
+       void (*eqos_flush_buffer)(void *buf, size_t size);
+       int (*eqos_probe_resources)(struct udevice *dev);
+       int (*eqos_remove_resources)(struct udevice *dev);
+       int (*eqos_stop_resets)(struct udevice *dev);
+       int (*eqos_start_resets)(struct udevice *dev);
+       void (*eqos_stop_clks)(struct udevice *dev);
+       int (*eqos_start_clks)(struct udevice *dev);
+       int (*eqos_calibrate_pads)(struct udevice *dev);
+       int (*eqos_disable_calibration)(struct udevice *dev);
+       int (*eqos_set_tx_clk_speed)(struct udevice *dev);
+       ulong (*eqos_get_tick_clk_rate)(struct udevice *dev);
 };
 
 struct eqos_priv {
@@ -276,6 +300,7 @@ struct eqos_priv {
        struct clk clk_rx;
        struct clk clk_ptp_ref;
        struct clk clk_tx;
+       struct clk clk_ck;
        struct clk clk_slave_bus;
        struct mii_dev *mii;
        struct phy_device *phy;
@@ -327,7 +352,7 @@ static void eqos_free_descs(void *descs)
 #endif
 }
 
-static void eqos_inval_desc(void *desc)
+static void eqos_inval_desc_tegra186(void *desc)
 {
 #ifndef CONFIG_SYS_NONCACHED_MEMORY
        unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
@@ -338,14 +363,36 @@ static void eqos_inval_desc(void *desc)
 #endif
 }
 
-static void eqos_flush_desc(void *desc)
+static void eqos_inval_desc_stm32(void *desc)
+{
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
+       unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
+       unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
+                                   ARCH_DMA_MINALIGN);
+
+       invalidate_dcache_range(start, end);
+#endif
+}
+
+static void eqos_flush_desc_tegra186(void *desc)
 {
 #ifndef CONFIG_SYS_NONCACHED_MEMORY
        flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE);
 #endif
 }
 
-static void eqos_inval_buffer(void *buf, size_t size)
+static void eqos_flush_desc_stm32(void *desc)
+{
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
+       unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
+       unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
+                                   ARCH_DMA_MINALIGN);
+
+       flush_dcache_range(start, end);
+#endif
+}
+
+static void eqos_inval_buffer_tegra186(void *buf, size_t size)
 {
        unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1);
        unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN);
@@ -353,11 +400,29 @@ static void eqos_inval_buffer(void *buf, size_t size)
        invalidate_dcache_range(start, end);
 }
 
-static void eqos_flush_buffer(void *buf, size_t size)
+static void eqos_inval_buffer_stm32(void *buf, size_t size)
+{
+       unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
+       unsigned long end = roundup((unsigned long)buf + size,
+                                   ARCH_DMA_MINALIGN);
+
+       invalidate_dcache_range(start, end);
+}
+
+static void eqos_flush_buffer_tegra186(void *buf, size_t size)
 {
        flush_cache((unsigned long)buf, size);
 }
 
+static void eqos_flush_buffer_stm32(void *buf, size_t size)
+{
+       unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
+       unsigned long end = roundup((unsigned long)buf + size,
+                                   ARCH_DMA_MINALIGN);
+
+       flush_dcache_range(start, end);
+}
+
 static int eqos_mdio_wait_idle(struct eqos_priv *eqos)
 {
        return wait_for_bit_le32(&eqos->mac_regs->mdio_address,
@@ -386,14 +451,14 @@ static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
                EQOS_MAC_MDIO_ADDRESS_C45E;
        val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
                (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
-               (EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
+               (eqos->config->config_mac_mdio <<
                 EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
                (EQOS_MAC_MDIO_ADDRESS_GOC_READ <<
                 EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
                EQOS_MAC_MDIO_ADDRESS_GB;
        writel(val, &eqos->mac_regs->mdio_address);
 
-       udelay(10);
+       udelay(eqos->config->mdio_wait);
 
        ret = eqos_mdio_wait_idle(eqos);
        if (ret) {
@@ -432,14 +497,14 @@ static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad,
                EQOS_MAC_MDIO_ADDRESS_C45E;
        val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
                (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
-               (EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
+               (eqos->config->config_mac_mdio <<
                 EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
                (EQOS_MAC_MDIO_ADDRESS_GOC_WRITE <<
                 EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
                EQOS_MAC_MDIO_ADDRESS_GB;
        writel(val, &eqos->mac_regs->mdio_address);
 
-       udelay(10);
+       udelay(eqos->config->mdio_wait);
 
        ret = eqos_mdio_wait_idle(eqos);
        if (ret) {
@@ -509,6 +574,53 @@ err:
        return ret;
 }
 
+static int eqos_start_clks_stm32(struct udevice *dev)
+{
+       struct eqos_priv *eqos = dev_get_priv(dev);
+       int ret;
+
+       debug("%s(dev=%p):\n", __func__, dev);
+
+       ret = clk_enable(&eqos->clk_master_bus);
+       if (ret < 0) {
+               pr_err("clk_enable(clk_master_bus) failed: %d", ret);
+               goto err;
+       }
+
+       ret = clk_enable(&eqos->clk_rx);
+       if (ret < 0) {
+               pr_err("clk_enable(clk_rx) failed: %d", ret);
+               goto err_disable_clk_master_bus;
+       }
+
+       ret = clk_enable(&eqos->clk_tx);
+       if (ret < 0) {
+               pr_err("clk_enable(clk_tx) failed: %d", ret);
+               goto err_disable_clk_rx;
+       }
+
+       if (clk_valid(&eqos->clk_ck)) {
+               ret = clk_enable(&eqos->clk_ck);
+               if (ret < 0) {
+                       pr_err("clk_enable(clk_ck) failed: %d", ret);
+                       goto err_disable_clk_tx;
+               }
+       }
+
+       debug("%s: OK\n", __func__);
+       return 0;
+
+err_disable_clk_tx:
+       clk_disable(&eqos->clk_tx);
+err_disable_clk_rx:
+       clk_disable(&eqos->clk_rx);
+err_disable_clk_master_bus:
+       clk_disable(&eqos->clk_master_bus);
+err:
+       debug("%s: FAILED: %d\n", __func__, ret);
+       return ret;
+}
+
 void eqos_stop_clks_tegra186(struct udevice *dev)
 {
        struct eqos_priv *eqos = dev_get_priv(dev);
@@ -524,6 +636,21 @@ void eqos_stop_clks_tegra186(struct udevice *dev)
        debug("%s: OK\n", __func__);
 }
 
+void eqos_stop_clks_stm32(struct udevice *dev)
+{
+       struct eqos_priv *eqos = dev_get_priv(dev);
+
+       debug("%s(dev=%p):\n", __func__, dev);
+
+       clk_disable(&eqos->clk_tx);
+       clk_disable(&eqos->clk_rx);
+       clk_disable(&eqos->clk_master_bus);
+       if (clk_valid(&eqos->clk_ck))
+               clk_disable(&eqos->clk_ck);
+
+       debug("%s: OK\n", __func__);
+}
+
 static int eqos_start_resets_tegra186(struct udevice *dev)
 {
        struct eqos_priv *eqos = dev_get_priv(dev);
@@ -563,6 +690,11 @@ static int eqos_start_resets_tegra186(struct udevice *dev)
        return 0;
 }
 
+static int eqos_start_resets_stm32(struct udevice *dev)
+{
+       return 0;
+}
+
 static int eqos_stop_resets_tegra186(struct udevice *dev)
 {
        struct eqos_priv *eqos = dev_get_priv(dev);
@@ -573,6 +705,11 @@ static int eqos_stop_resets_tegra186(struct udevice *dev)
        return 0;
 }
 
+static int eqos_stop_resets_stm32(struct udevice *dev)
+{
+       return 0;
+}
+
 static int eqos_calibrate_pads_tegra186(struct udevice *dev)
 {
        struct eqos_priv *eqos = dev_get_priv(dev);
@@ -632,6 +769,23 @@ static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev)
        return clk_get_rate(&eqos->clk_slave_bus);
 }
 
+static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev)
+{
+       struct eqos_priv *eqos = dev_get_priv(dev);
+
+       return clk_get_rate(&eqos->clk_master_bus);
+}
+
+static int eqos_calibrate_pads_stm32(struct udevice *dev)
+{
+       return 0;
+}
+
+static int eqos_disable_calibration_stm32(struct udevice *dev)
+{
+       return 0;
+}
+
 static int eqos_set_full_duplex(struct udevice *dev)
 {
        struct eqos_priv *eqos = dev_get_priv(dev);
@@ -726,6 +880,11 @@ static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev)
        return 0;
 }
 
+static int eqos_set_tx_clk_speed_stm32(struct udevice *dev)
+{
+       return 0;
+}
+
 static int eqos_adjust_link(struct udevice *dev)
 {
        struct eqos_priv *eqos = dev_get_priv(dev);
@@ -766,23 +925,23 @@ static int eqos_adjust_link(struct udevice *dev)
        }
 
        if (en_calibration) {
-               ret = eqos_calibrate_pads_tegra186(dev);
+               ret = eqos->config->ops->eqos_calibrate_pads(dev);
                if (ret < 0) {
-                       pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
+                       pr_err("eqos_calibrate_pads() failed: %d",
+                              ret);
                        return ret;
                }
        } else {
-               ret = eqos_disable_calibration_tegra186(dev);
+               ret = eqos->config->ops->eqos_disable_calibration(dev);
                if (ret < 0) {
-                       pr_err("eqos_disable_calibration_tegra186() failed: %d",
-                             ret);
+                       pr_err("eqos_disable_calibration() failed: %d",
+                              ret);
                        return ret;
                }
        }
-
-       ret = eqos_set_tx_clk_speed_tegra186(dev);
+       ret = eqos->config->ops->eqos_set_tx_clk_speed(dev);
        if (ret < 0) {
-               pr_err("eqos_set_tx_clk_speed_tegra186() failed: %d", ret);
+               pr_err("eqos_set_tx_clk_speed() failed: %d", ret);
                return ret;
        }
 
@@ -846,15 +1005,15 @@ static int eqos_start(struct udevice *dev)
        eqos->tx_desc_idx = 0;
        eqos->rx_desc_idx = 0;
 
-       ret = eqos_start_clks_tegra186(dev);
+       ret = eqos->config->ops->eqos_start_clks(dev);
        if (ret < 0) {
-               pr_err("eqos_start_clks_tegra186() failed: %d", ret);
+               pr_err("eqos_start_clks() failed: %d", ret);
                goto err;
        }
 
-       ret = eqos_start_resets_tegra186(dev);
+       ret = eqos->config->ops->eqos_start_resets(dev);
        if (ret < 0) {
-               pr_err("eqos_start_resets_tegra186() failed: %d", ret);
+               pr_err("eqos_start_resets() failed: %d", ret);
                goto err_stop_clks;
        }
 
@@ -863,32 +1022,41 @@ static int eqos_start(struct udevice *dev)
        eqos->reg_access_ok = true;
 
        ret = wait_for_bit_le32(&eqos->dma_regs->mode,
-                               EQOS_DMA_MODE_SWR, false, 10, false);
+                               EQOS_DMA_MODE_SWR, false,
+                               eqos->config->swr_wait, false);
        if (ret) {
                pr_err("EQOS_DMA_MODE_SWR stuck");
                goto err_stop_resets;
        }
 
-       ret = eqos_calibrate_pads_tegra186(dev);
+       ret = eqos->config->ops->eqos_calibrate_pads(dev);
        if (ret < 0) {
-               pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
+               pr_err("eqos_calibrate_pads() failed: %d", ret);
                goto err_stop_resets;
        }
+       rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
 
-       rate = eqos_get_tick_clk_rate_tegra186(dev);
        val = (rate / 1000000) - 1;
        writel(val, &eqos->mac_regs->us_tic_counter);
 
-       eqos->phy = phy_connect(eqos->mii, 0, dev, 0);
+       /*
+        * if PHY was already connected and configured,
+        * don't need to reconnect/reconfigure again
+        */
        if (!eqos->phy) {
-               pr_err("phy_connect() failed");
-               goto err_stop_resets;
-       }
-       ret = phy_config(eqos->phy);
-       if (ret < 0) {
-               pr_err("phy_config() failed: %d", ret);
-               goto err_shutdown_phy;
+               eqos->phy = phy_connect(eqos->mii, 0, dev,
+                                       eqos->config->interface(dev));
+               if (!eqos->phy) {
+                       pr_err("phy_connect() failed");
+                       goto err_stop_resets;
+               }
+               ret = phy_config(eqos->phy);
+               if (ret < 0) {
+                       pr_err("phy_config() failed: %d", ret);
+                       goto err_shutdown_phy;
+               }
        }
+
        ret = phy_startup(eqos->phy);
        if (ret < 0) {
                pr_err("phy_startup() failed: %d", ret);
@@ -993,7 +1161,7 @@ static int eqos_start(struct udevice *dev)
        clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0,
                        EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK <<
                        EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT,
-                       EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB <<
+                       eqos->config->config_mac <<
                        EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT);
 
        /* Set TX flow control parameters */
@@ -1074,7 +1242,7 @@ static int eqos_start(struct udevice *dev)
                                             (i * EQOS_MAX_PACKET_SIZE));
                rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
        }
-       flush_cache((unsigned long)eqos->descs, EQOS_DESCRIPTORS_SIZE);
+       eqos->config->ops->eqos_flush_desc(eqos->descs);
 
        writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress);
        writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address);
@@ -1113,11 +1281,10 @@ static int eqos_start(struct udevice *dev)
 
 err_shutdown_phy:
        phy_shutdown(eqos->phy);
-       eqos->phy = NULL;
 err_stop_resets:
-       eqos_stop_resets_tegra186(dev);
+       eqos->config->ops->eqos_stop_resets(dev);
 err_stop_clks:
-       eqos_stop_clks_tegra186(dev);
+       eqos->config->ops->eqos_stop_clks(dev);
 err:
        pr_err("FAILED: %d", ret);
        return ret;
@@ -1170,10 +1337,9 @@ void eqos_stop(struct udevice *dev)
 
        if (eqos->phy) {
                phy_shutdown(eqos->phy);
-               eqos->phy = NULL;
        }
-       eqos_stop_resets_tegra186(dev);
-       eqos_stop_clks_tegra186(dev);
+       eqos->config->ops->eqos_stop_resets(dev);
+       eqos->config->ops->eqos_stop_clks(dev);
 
        debug("%s: OK\n", __func__);
 }
@@ -1188,7 +1354,7 @@ int eqos_send(struct udevice *dev, void *packet, int length)
              length);
 
        memcpy(eqos->tx_dma_buf, packet, length);
-       eqos_flush_buffer(eqos->tx_dma_buf, length);
+       eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length);
 
        tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]);
        eqos->tx_desc_idx++;
@@ -1203,12 +1369,12 @@ int eqos_send(struct udevice *dev, void *packet, int length)
         */
        mb();
        tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length;
-       eqos_flush_desc(tx_desc);
+       eqos->config->ops->eqos_flush_desc(tx_desc);
 
        writel((ulong)(tx_desc + 1), &eqos->dma_regs->ch0_txdesc_tail_pointer);
 
        for (i = 0; i < 1000000; i++) {
-               eqos_inval_desc(tx_desc);
+               eqos->config->ops->eqos_inval_desc(tx_desc);
                if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN))
                        return 0;
                udelay(1);
@@ -1238,7 +1404,7 @@ int eqos_recv(struct udevice *dev, int flags, uchar **packetp)
        length = rx_desc->des3 & 0x7fff;
        debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length);
 
-       eqos_inval_buffer(*packetp, length);
+       eqos->config->ops->eqos_inval_buffer(*packetp, length);
 
        return length;
 }
@@ -1269,7 +1435,7 @@ int eqos_free_pkt(struct udevice *dev, uchar *packet, int length)
         */
        mb();
        rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
-       eqos_flush_desc(rx_desc);
+       eqos->config->ops->eqos_flush_desc(rx_desc);
 
        writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
 
@@ -1304,7 +1470,7 @@ static int eqos_probe_resources_core(struct udevice *dev)
                ret = -ENOMEM;
                goto err_free_descs;
        }
-       debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
+       debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
 
        eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE);
        if (!eqos->rx_dma_buf) {
@@ -1312,7 +1478,7 @@ static int eqos_probe_resources_core(struct udevice *dev)
                ret = -ENOMEM;
                goto err_free_tx_dma_buf;
        }
-       debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
+       debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
 
        eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE);
        if (!eqos->rx_pkt) {
@@ -1424,6 +1590,98 @@ err_free_reset_eqos:
        return ret;
 }
 
+/* board-specific Ethernet Interface initializations. */
+__weak int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg,
+                                   bool eth_ref_clk_sel_reg)
+{
+       return 0;
+}
+
+static int eqos_probe_resources_stm32(struct udevice *dev)
+{
+       struct eqos_priv *eqos = dev_get_priv(dev);
+       int ret;
+       phy_interface_t interface;
+       bool eth_clk_sel_reg = false;
+       bool eth_ref_clk_sel_reg = false;
+
+       debug("%s(dev=%p):\n", __func__, dev);
+
+       interface = eqos->config->interface(dev);
+
+       if (interface == PHY_INTERFACE_MODE_NONE) {
+               pr_err("Invalid PHY interface\n");
+               return -EINVAL;
+       }
+
+       /* Gigabit Ethernet 125MHz clock selection. */
+       eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
+
+       /* Ethernet 50Mhz RMII clock selection */
+       eth_ref_clk_sel_reg =
+               dev_read_bool(dev, "st,eth_ref_clk_sel");
+
+       ret = board_interface_eth_init(interface, eth_clk_sel_reg,
+                                      eth_ref_clk_sel_reg);
+       if (ret)
+               return -EINVAL;
+
+       ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
+       if (ret) {
+               pr_err("clk_get_by_name(master_bus) failed: %d", ret);
+               goto err_probe;
+       }
+
+       ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx);
+       if (ret) {
+               pr_err("clk_get_by_name(rx) failed: %d", ret);
+               goto err_free_clk_master_bus;
+       }
+
+       ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx);
+       if (ret) {
+               pr_err("clk_get_by_name(tx) failed: %d", ret);
+               goto err_free_clk_rx;
+       }
+
+       /*  Get ETH_CLK clocks (optional) */
+       ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck);
+       if (ret)
+               pr_warn("No phy clock provided %d", ret);
+
+       debug("%s: OK\n", __func__);
+       return 0;
+
+err_free_clk_rx:
+       clk_free(&eqos->clk_rx);
+err_free_clk_master_bus:
+       clk_free(&eqos->clk_master_bus);
+err_probe:
+
+       debug("%s: returns %d\n", __func__, ret);
+       return ret;
+}
+
+static phy_interface_t eqos_get_interface_stm32(struct udevice *dev)
+{
+       const char *phy_mode;
+       phy_interface_t interface = PHY_INTERFACE_MODE_NONE;
+
+       debug("%s(dev=%p):\n", __func__, dev);
+
+       phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
+                              NULL);
+       if (phy_mode)
+               interface = phy_get_interface_by_name(phy_mode);
+
+       return interface;
+}
+
+static phy_interface_t eqos_get_interface_tegra186(struct udevice *dev)
+{
+       return PHY_INTERFACE_MODE_MII;
+}
+
 static int eqos_remove_resources_tegra186(struct udevice *dev)
 {
        struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1442,6 +1700,22 @@ static int eqos_remove_resources_tegra186(struct udevice *dev)
        return 0;
 }
 
+static int eqos_remove_resources_stm32(struct udevice *dev)
+{
+       struct eqos_priv *eqos = dev_get_priv(dev);
+
+       debug("%s(dev=%p):\n", __func__, dev);
+
+       clk_free(&eqos->clk_tx);
+       clk_free(&eqos->clk_rx);
+       clk_free(&eqos->clk_master_bus);
+       if (clk_valid(&eqos->clk_ck))
+               clk_free(&eqos->clk_ck);
+
+       debug("%s: OK\n", __func__);
+       return 0;
+}
+
 static int eqos_probe(struct udevice *dev)
 {
        struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1468,15 +1742,16 @@ static int eqos_probe(struct udevice *dev)
                return ret;
        }
 
-       ret = eqos_probe_resources_tegra186(dev);
+       ret = eqos->config->ops->eqos_probe_resources(dev);
        if (ret < 0) {
-               pr_err("eqos_probe_resources_tegra186() failed: %d", ret);
+               pr_err("eqos_probe_resources() failed: %d", ret);
                goto err_remove_resources_core;
        }
 
        eqos->mii = mdio_alloc();
        if (!eqos->mii) {
                pr_err("mdio_alloc() failed");
+               ret = -ENOMEM;
                goto err_remove_resources_tegra;
        }
        eqos->mii->read = eqos_mdio_read;
@@ -1496,7 +1771,7 @@ static int eqos_probe(struct udevice *dev)
 err_free_mdio:
        mdio_free(eqos->mii);
 err_remove_resources_tegra:
-       eqos_remove_resources_tegra186(dev);
+       eqos->config->ops->eqos_remove_resources(dev);
 err_remove_resources_core:
        eqos_remove_resources_core(dev);
 
@@ -1512,7 +1787,8 @@ static int eqos_remove(struct udevice *dev)
 
        mdio_unregister(eqos->mii);
        mdio_free(eqos->mii);
-       eqos_remove_resources_tegra186(dev);
+       eqos->config->ops->eqos_remove_resources(dev);
+
        eqos_probe_resources_core(dev);
 
        debug("%s: OK\n", __func__);
@@ -1528,8 +1804,58 @@ static const struct eth_ops eqos_ops = {
        .write_hwaddr = eqos_write_hwaddr,
 };
 
+static struct eqos_ops eqos_tegra186_ops = {
+       .eqos_inval_desc = eqos_inval_desc_tegra186,
+       .eqos_flush_desc = eqos_flush_desc_tegra186,
+       .eqos_inval_buffer = eqos_inval_buffer_tegra186,
+       .eqos_flush_buffer = eqos_flush_buffer_tegra186,
+       .eqos_probe_resources = eqos_probe_resources_tegra186,
+       .eqos_remove_resources = eqos_remove_resources_tegra186,
+       .eqos_stop_resets = eqos_stop_resets_tegra186,
+       .eqos_start_resets = eqos_start_resets_tegra186,
+       .eqos_stop_clks = eqos_stop_clks_tegra186,
+       .eqos_start_clks = eqos_start_clks_tegra186,
+       .eqos_calibrate_pads = eqos_calibrate_pads_tegra186,
+       .eqos_disable_calibration = eqos_disable_calibration_tegra186,
+       .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186,
+       .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186
+};
+
 static const struct eqos_config eqos_tegra186_config = {
        .reg_access_always_ok = false,
+       .mdio_wait = 10,
+       .swr_wait = 10,
+       .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
+       .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35,
+       .interface = eqos_get_interface_tegra186,
+       .ops = &eqos_tegra186_ops
+};
+
+static struct eqos_ops eqos_stm32_ops = {
+       .eqos_inval_desc = eqos_inval_desc_stm32,
+       .eqos_flush_desc = eqos_flush_desc_stm32,
+       .eqos_inval_buffer = eqos_inval_buffer_stm32,
+       .eqos_flush_buffer = eqos_flush_buffer_stm32,
+       .eqos_probe_resources = eqos_probe_resources_stm32,
+       .eqos_remove_resources = eqos_remove_resources_stm32,
+       .eqos_stop_resets = eqos_stop_resets_stm32,
+       .eqos_start_resets = eqos_start_resets_stm32,
+       .eqos_stop_clks = eqos_stop_clks_stm32,
+       .eqos_start_clks = eqos_start_clks_stm32,
+       .eqos_calibrate_pads = eqos_calibrate_pads_stm32,
+       .eqos_disable_calibration = eqos_disable_calibration_stm32,
+       .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32,
+       .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32
+};
+
+static const struct eqos_config eqos_stm32_config = {
+       .reg_access_always_ok = false,
+       .mdio_wait = 10000,
+       .swr_wait = 50,
+       .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
+       .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
+       .interface = eqos_get_interface_stm32,
+       .ops = &eqos_stm32_ops
 };
 
 static const struct udevice_id eqos_ids[] = {
@@ -1537,6 +1863,11 @@ static const struct udevice_id eqos_ids[] = {
                .compatible = "nvidia,tegra186-eqos",
                .data = (ulong)&eqos_tegra186_config
        },
+       {
+               .compatible = "snps,dwmac-4.20a",
+               .data = (ulong)&eqos_stm32_config
+       },
+
        { }
 };
 
index eb32f082fe978fddc13bdadd38e3bc0e821134b9..04ddb32a8f313535e6f7450370f33d098baa7947 100644 (file)
@@ -239,6 +239,14 @@ config STM32_QSPI
          used to access the SPI NOR flash chips on platforms embedding
          this ST IP core.
 
+config STM32_SPI
+       bool "STM32 SPI driver"
+       depends on ARCH_STM32MP
+       help
+         Enable the STM32 Serial Peripheral Interface (SPI) driver for STM32MP
+         SoCs. This uses driver model and requires a device tree binding to
+         operate.
+
 config TEGRA114_SPI
        bool "nVidia Tegra114 SPI driver"
        help
index 8be9a4baa2446fc28cd393785f7f767806bf0ace..3f9f2fab2b9f39d849865f547a39a60d76527633 100644 (file)
@@ -53,6 +53,7 @@ obj-$(CONFIG_SPI_SUNXI) += spi-sunxi.o
 obj-$(CONFIG_SH_SPI) += sh_spi.o
 obj-$(CONFIG_SH_QSPI) += sh_qspi.o
 obj-$(CONFIG_STM32_QSPI) += stm32_qspi.o
+obj-$(CONFIG_STM32_SPI) += stm32_spi.o
 obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
 obj-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
 obj-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
diff --git a/drivers/spi/stm32_spi.c b/drivers/spi/stm32_spi.c
new file mode 100644 (file)
index 0000000..34b2175
--- /dev/null
@@ -0,0 +1,615 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ *
+ * Driver for STMicroelectronics Serial peripheral interface (SPI)
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <reset.h>
+#include <spi.h>
+
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <linux/bitfield.h>
+#include <linux/iopoll.h>
+
+/* STM32 SPI registers */
+#define STM32_SPI_CR1          0x00
+#define STM32_SPI_CR2          0x04
+#define STM32_SPI_CFG1         0x08
+#define STM32_SPI_CFG2         0x0C
+#define STM32_SPI_SR           0x14
+#define STM32_SPI_IFCR         0x18
+#define STM32_SPI_TXDR         0x20
+#define STM32_SPI_RXDR         0x30
+#define STM32_SPI_I2SCFGR      0x50
+
+/* STM32_SPI_CR1 bit fields */
+#define SPI_CR1_SPE            BIT(0)
+#define SPI_CR1_MASRX          BIT(8)
+#define SPI_CR1_CSTART         BIT(9)
+#define SPI_CR1_CSUSP          BIT(10)
+#define SPI_CR1_HDDIR          BIT(11)
+#define SPI_CR1_SSI            BIT(12)
+
+/* STM32_SPI_CR2 bit fields */
+#define SPI_CR2_TSIZE          GENMASK(15, 0)
+
+/* STM32_SPI_CFG1 bit fields */
+#define SPI_CFG1_DSIZE         GENMASK(4, 0)
+#define SPI_CFG1_DSIZE_MIN     3
+#define SPI_CFG1_FTHLV_SHIFT   5
+#define SPI_CFG1_FTHLV         GENMASK(8, 5)
+#define SPI_CFG1_MBR_SHIFT     28
+#define SPI_CFG1_MBR           GENMASK(30, 28)
+#define SPI_CFG1_MBR_MIN       0
+#define SPI_CFG1_MBR_MAX       FIELD_GET(SPI_CFG1_MBR, SPI_CFG1_MBR)
+
+/* STM32_SPI_CFG2 bit fields */
+#define SPI_CFG2_COMM_SHIFT    17
+#define SPI_CFG2_COMM          GENMASK(18, 17)
+#define SPI_CFG2_MASTER                BIT(22)
+#define SPI_CFG2_LSBFRST       BIT(23)
+#define SPI_CFG2_CPHA          BIT(24)
+#define SPI_CFG2_CPOL          BIT(25)
+#define SPI_CFG2_SSM           BIT(26)
+#define SPI_CFG2_AFCNTR                BIT(31)
+
+/* STM32_SPI_SR bit fields */
+#define SPI_SR_RXP             BIT(0)
+#define SPI_SR_TXP             BIT(1)
+#define SPI_SR_EOT             BIT(3)
+#define SPI_SR_TXTF            BIT(4)
+#define SPI_SR_OVR             BIT(6)
+#define SPI_SR_SUSP            BIT(11)
+#define SPI_SR_RXPLVL_SHIFT    13
+#define SPI_SR_RXPLVL          GENMASK(14, 13)
+#define SPI_SR_RXWNE           BIT(15)
+
+/* STM32_SPI_IFCR bit fields */
+#define SPI_IFCR_ALL           GENMASK(11, 3)
+
+/* STM32_SPI_I2SCFGR bit fields */
+#define SPI_I2SCFGR_I2SMOD     BIT(0)
+
+#define MAX_CS_COUNT   4
+
+/* SPI Master Baud Rate min/max divisor */
+#define STM32_MBR_DIV_MIN      (2 << SPI_CFG1_MBR_MIN)
+#define STM32_MBR_DIV_MAX      (2 << SPI_CFG1_MBR_MAX)
+
+#define STM32_SPI_TIMEOUT_US   100000
+
+/* SPI Communication mode */
+#define SPI_FULL_DUPLEX                0
+#define SPI_SIMPLEX_TX         1
+#define SPI_SIMPLEX_RX         2
+#define SPI_HALF_DUPLEX                3
+
+struct stm32_spi_priv {
+       void __iomem *base;
+       struct clk clk;
+       struct reset_ctl rst_ctl;
+       struct gpio_desc cs_gpios[MAX_CS_COUNT];
+       ulong bus_clk_rate;
+       unsigned int fifo_size;
+       unsigned int cur_bpw;
+       unsigned int cur_hz;
+       unsigned int cur_xferlen; /* current transfer length in bytes */
+       int tx_len;               /* number of data to be written in bytes */
+       int rx_len;               /* number of data to be read in bytes */
+       const void *tx_buf;       /* data to be written, or NULL */
+       void *rx_buf;             /* data to be read, or NULL */
+       u32 cur_mode;
+       bool cs_high;
+};
+
+static void stm32_spi_write_txfifo(struct stm32_spi_priv *priv)
+{
+       while ((priv->tx_len > 0) &&
+              (readl(priv->base + STM32_SPI_SR) & SPI_SR_TXP)) {
+               u32 offs = priv->cur_xferlen - priv->tx_len;
+
+               if (priv->tx_len >= sizeof(u32) &&
+                   IS_ALIGNED((uintptr_t)(priv->tx_buf + offs), sizeof(u32))) {
+                       const u32 *tx_buf32 = (const u32 *)(priv->tx_buf + offs);
+
+                       writel(*tx_buf32, priv->base + STM32_SPI_TXDR);
+                       priv->tx_len -= sizeof(u32);
+               } else if (priv->tx_len >= sizeof(u16) &&
+                          IS_ALIGNED((uintptr_t)(priv->tx_buf + offs), sizeof(u16))) {
+                       const u16 *tx_buf16 = (const u16 *)(priv->tx_buf + offs);
+
+                       writew(*tx_buf16, priv->base + STM32_SPI_TXDR);
+                       priv->tx_len -= sizeof(u16);
+               } else {
+                       const u8 *tx_buf8 = (const u8 *)(priv->tx_buf + offs);
+
+                       writeb(*tx_buf8, priv->base + STM32_SPI_TXDR);
+                       priv->tx_len -= sizeof(u8);
+               }
+       }
+
+       debug("%s: %d bytes left\n", __func__, priv->tx_len);
+}
+
+static void stm32_spi_read_rxfifo(struct stm32_spi_priv *priv)
+{
+       u32 sr = readl(priv->base + STM32_SPI_SR);
+       u32 rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT;
+
+       while ((priv->rx_len > 0) &&
+              ((sr & SPI_SR_RXP) ||
+              ((sr & SPI_SR_EOT) && ((sr & SPI_SR_RXWNE) || (rxplvl > 0))))) {
+               u32 offs = priv->cur_xferlen - priv->rx_len;
+
+               if (IS_ALIGNED((uintptr_t)(priv->rx_buf + offs), sizeof(u32)) &&
+                   (priv->rx_len >= sizeof(u32) || (sr & SPI_SR_RXWNE))) {
+                       u32 *rx_buf32 = (u32 *)(priv->rx_buf + offs);
+
+                       *rx_buf32 = readl(priv->base + STM32_SPI_RXDR);
+                       priv->rx_len -= sizeof(u32);
+               } else if (IS_ALIGNED((uintptr_t)(priv->rx_buf + offs), sizeof(u16)) &&
+                          (priv->rx_len >= sizeof(u16) ||
+                           (!(sr & SPI_SR_RXWNE) &&
+                           (rxplvl >= 2 || priv->cur_bpw > 8)))) {
+                       u16 *rx_buf16 = (u16 *)(priv->rx_buf + offs);
+
+                       *rx_buf16 = readw(priv->base + STM32_SPI_RXDR);
+                       priv->rx_len -= sizeof(u16);
+               } else {
+                       u8 *rx_buf8 = (u8 *)(priv->rx_buf + offs);
+
+                       *rx_buf8 = readb(priv->base + STM32_SPI_RXDR);
+                       priv->rx_len -= sizeof(u8);
+               }
+
+               sr = readl(priv->base + STM32_SPI_SR);
+               rxplvl = (sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_SHIFT;
+       }
+
+       debug("%s: %d bytes left\n", __func__, priv->rx_len);
+}
+
+static int stm32_spi_enable(struct stm32_spi_priv *priv)
+{
+       debug("%s\n", __func__);
+
+       /* Enable the SPI hardware */
+       setbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_SPE);
+
+       return 0;
+}
+
+static int stm32_spi_disable(struct stm32_spi_priv *priv)
+{
+       debug("%s\n", __func__);
+
+       /* Disable the SPI hardware */
+       clrbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_SPE);
+
+       return 0;
+}
+
+static int stm32_spi_claim_bus(struct udevice *slave)
+{
+       struct udevice *bus = dev_get_parent(slave);
+       struct stm32_spi_priv *priv = dev_get_priv(bus);
+
+       debug("%s\n", __func__);
+
+       /* Enable the SPI hardware */
+       return stm32_spi_enable(priv);
+}
+
+static int stm32_spi_release_bus(struct udevice *slave)
+{
+       struct udevice *bus = dev_get_parent(slave);
+       struct stm32_spi_priv *priv = dev_get_priv(bus);
+
+       debug("%s\n", __func__);
+
+       /* Disable the SPI hardware */
+       return stm32_spi_disable(priv);
+}
+
+static void stm32_spi_stopxfer(struct udevice *dev)
+{
+       struct stm32_spi_priv *priv = dev_get_priv(dev);
+       u32 cr1, sr;
+       int ret;
+
+       debug("%s\n", __func__);
+
+       cr1 = readl(priv->base + STM32_SPI_CR1);
+
+       if (!(cr1 & SPI_CR1_SPE))
+               return;
+
+       /* Wait on EOT or suspend the flow */
+       ret = readl_poll_timeout(priv->base + STM32_SPI_SR, sr,
+                                !(sr & SPI_SR_EOT), 100000);
+       if (ret < 0) {
+               if (cr1 & SPI_CR1_CSTART) {
+                       writel(cr1 | SPI_CR1_CSUSP, priv->base + STM32_SPI_CR1);
+                       if (readl_poll_timeout(priv->base + STM32_SPI_SR,
+                                              sr, !(sr & SPI_SR_SUSP),
+                                              100000) < 0)
+                               dev_err(dev, "Suspend request timeout\n");
+               }
+       }
+
+       /* clear status flags */
+       setbits_le32(priv->base + STM32_SPI_IFCR, SPI_IFCR_ALL);
+}
+
+static int stm32_spi_set_cs(struct udevice *dev, unsigned int cs, bool enable)
+{
+       struct stm32_spi_priv *priv = dev_get_priv(dev);
+
+       debug("%s: cs=%d enable=%d\n", __func__, cs, enable);
+
+       if (cs >= MAX_CS_COUNT)
+               return -ENODEV;
+
+       if (!dm_gpio_is_valid(&priv->cs_gpios[cs]))
+               return -EINVAL;
+
+       if (priv->cs_high)
+               enable = !enable;
+
+       return dm_gpio_set_value(&priv->cs_gpios[cs], enable ? 1 : 0);
+}
+
+static int stm32_spi_set_mode(struct udevice *bus, uint mode)
+{
+       struct stm32_spi_priv *priv = dev_get_priv(bus);
+       u32 cfg2_clrb = 0, cfg2_setb = 0;
+
+       debug("%s: mode=%d\n", __func__, mode);
+
+       if (mode & SPI_CPOL)
+               cfg2_setb |= SPI_CFG2_CPOL;
+       else
+               cfg2_clrb |= SPI_CFG2_CPOL;
+
+       if (mode & SPI_CPHA)
+               cfg2_setb |= SPI_CFG2_CPHA;
+       else
+               cfg2_clrb |= SPI_CFG2_CPHA;
+
+       if (mode & SPI_LSB_FIRST)
+               cfg2_setb |= SPI_CFG2_LSBFRST;
+       else
+               cfg2_clrb |= SPI_CFG2_LSBFRST;
+
+       if (cfg2_clrb || cfg2_setb)
+               clrsetbits_le32(priv->base + STM32_SPI_CFG2,
+                               cfg2_clrb, cfg2_setb);
+
+       if (mode & SPI_CS_HIGH)
+               priv->cs_high = true;
+       else
+               priv->cs_high = false;
+       return 0;
+}
+
+static int stm32_spi_set_fthlv(struct udevice *dev, u32 xfer_len)
+{
+       struct stm32_spi_priv *priv = dev_get_priv(dev);
+       u32 fthlv, half_fifo;
+
+       /* data packet should not exceed 1/2 of fifo space */
+       half_fifo = (priv->fifo_size / 2);
+
+       /* data_packet should not exceed transfer length */
+       fthlv = (half_fifo > xfer_len) ? xfer_len : half_fifo;
+
+       /* align packet size with data registers access */
+       fthlv -= (fthlv % 4);
+
+       if (!fthlv)
+               fthlv = 1;
+       clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_FTHLV,
+                       (fthlv - 1) << SPI_CFG1_FTHLV_SHIFT);
+
+       return 0;
+}
+
+static int stm32_spi_set_speed(struct udevice *bus, uint hz)
+{
+       struct stm32_spi_priv *priv = dev_get_priv(bus);
+       u32 div, mbrdiv;
+
+       debug("%s: hz=%d\n", __func__, hz);
+
+       if (priv->cur_hz == hz)
+               return 0;
+
+       div = DIV_ROUND_UP(priv->bus_clk_rate, hz);
+
+       if (div < STM32_MBR_DIV_MIN ||
+           div > STM32_MBR_DIV_MAX)
+               return -EINVAL;
+
+       /* Determine the first power of 2 greater than or equal to div */
+       if (div & (div - 1))
+               mbrdiv = fls(div);
+       else
+               mbrdiv = fls(div) - 1;
+
+       if ((mbrdiv - 1) < 0)
+               return -EINVAL;
+
+       clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_MBR,
+                       (mbrdiv - 1) << SPI_CFG1_MBR_SHIFT);
+
+       priv->cur_hz = hz;
+
+       return 0;
+}
+
+static int stm32_spi_xfer(struct udevice *slave, unsigned int bitlen,
+                         const void *dout, void *din, unsigned long flags)
+{
+       struct udevice *bus = dev_get_parent(slave);
+       struct dm_spi_slave_platdata *slave_plat;
+       struct stm32_spi_priv *priv = dev_get_priv(bus);
+       u32 sr;
+       u32 ifcr = 0;
+       u32 xferlen;
+       u32 mode;
+       int xfer_status = 0;
+
+       xferlen = bitlen / 8;
+
+       if (xferlen <= SPI_CR2_TSIZE)
+               writel(xferlen, priv->base + STM32_SPI_CR2);
+       else
+               return -EMSGSIZE;
+
+       priv->tx_buf = dout;
+       priv->rx_buf = din;
+       priv->tx_len = priv->tx_buf ? bitlen / 8 : 0;
+       priv->rx_len = priv->rx_buf ? bitlen / 8 : 0;
+
+       mode = SPI_FULL_DUPLEX;
+       if (!priv->tx_buf)
+               mode = SPI_SIMPLEX_RX;
+       else if (!priv->rx_buf)
+               mode = SPI_SIMPLEX_TX;
+
+       if (priv->cur_xferlen != xferlen || priv->cur_mode != mode) {
+               priv->cur_mode = mode;
+               priv->cur_xferlen = xferlen;
+
+               /* Disable the SPI hardware to unlock CFG1/CFG2 registers */
+               stm32_spi_disable(priv);
+
+               clrsetbits_le32(priv->base + STM32_SPI_CFG2, SPI_CFG2_COMM,
+                               mode << SPI_CFG2_COMM_SHIFT);
+
+               stm32_spi_set_fthlv(bus, xferlen);
+
+               /* Enable the SPI hardware */
+               stm32_spi_enable(priv);
+       }
+
+       debug("%s: priv->tx_len=%d priv->rx_len=%d\n", __func__,
+             priv->tx_len, priv->rx_len);
+
+       slave_plat = dev_get_parent_platdata(slave);
+       if (flags & SPI_XFER_BEGIN)
+               stm32_spi_set_cs(bus, slave_plat->cs, false);
+
+       /* Be sure to have data in fifo before starting data transfer */
+       if (priv->tx_buf)
+               stm32_spi_write_txfifo(priv);
+
+       setbits_le32(priv->base + STM32_SPI_CR1, SPI_CR1_CSTART);
+
+       while (1) {
+               sr = readl(priv->base + STM32_SPI_SR);
+
+               if (sr & SPI_SR_OVR) {
+                       dev_err(bus, "Overrun: RX data lost\n");
+                       xfer_status = -EIO;
+                       break;
+               }
+
+               if (sr & SPI_SR_SUSP) {
+                       dev_warn(bus, "System too slow is limiting data throughput\n");
+
+                       if (priv->rx_buf && priv->rx_len > 0)
+                               stm32_spi_read_rxfifo(priv);
+
+                       ifcr |= SPI_SR_SUSP;
+               }
+
+               if (sr & SPI_SR_TXTF)
+                       ifcr |= SPI_SR_TXTF;
+
+               if (sr & SPI_SR_TXP)
+                       if (priv->tx_buf && priv->tx_len > 0)
+                               stm32_spi_write_txfifo(priv);
+
+               if (sr & SPI_SR_RXP)
+                       if (priv->rx_buf && priv->rx_len > 0)
+                               stm32_spi_read_rxfifo(priv);
+
+               if (sr & SPI_SR_EOT) {
+                       if (priv->rx_buf && priv->rx_len > 0)
+                               stm32_spi_read_rxfifo(priv);
+                       break;
+               }
+
+               writel(ifcr, priv->base + STM32_SPI_IFCR);
+       }
+
+       /* clear status flags */
+       setbits_le32(priv->base + STM32_SPI_IFCR, SPI_IFCR_ALL);
+       stm32_spi_stopxfer(bus);
+
+       if (flags & SPI_XFER_END)
+               stm32_spi_set_cs(bus, slave_plat->cs, true);
+
+       return xfer_status;
+}
+
+static int stm32_spi_get_fifo_size(struct udevice *dev)
+{
+       struct stm32_spi_priv *priv = dev_get_priv(dev);
+       u32 count = 0;
+
+       stm32_spi_enable(priv);
+
+       while (readl(priv->base + STM32_SPI_SR) & SPI_SR_TXP)
+               writeb(++count, priv->base + STM32_SPI_TXDR);
+
+       stm32_spi_disable(priv);
+
+       debug("%s %d x 8-bit fifo size\n", __func__, count);
+
+       return count;
+}
+
+static int stm32_spi_probe(struct udevice *dev)
+{
+       struct stm32_spi_priv *priv = dev_get_priv(dev);
+       unsigned long clk_rate;
+       int ret;
+       int i;
+
+       priv->base = dev_remap_addr(dev);
+       if (!priv->base)
+               return -EINVAL;
+
+       /* enable clock */
+       ret = clk_get_by_index(dev, 0, &priv->clk);
+       if (ret < 0)
+               return ret;
+
+       ret = clk_enable(&priv->clk);
+       if (ret < 0)
+               return ret;
+
+       clk_rate = clk_get_rate(&priv->clk);
+       if (!clk_rate) {
+               ret = -EINVAL;
+               goto clk_err;
+       }
+
+       priv->bus_clk_rate = clk_rate;
+
+       /* perform reset */
+       ret = reset_get_by_index(dev, 0, &priv->rst_ctl);
+       if (ret < 0)
+               goto clk_err;
+
+       reset_assert(&priv->rst_ctl);
+       udelay(2);
+       reset_deassert(&priv->rst_ctl);
+
+       ret = gpio_request_list_by_name(dev, "cs-gpios", priv->cs_gpios,
+                                       ARRAY_SIZE(priv->cs_gpios), 0);
+       if (ret < 0) {
+               pr_err("Can't get %s cs gpios: %d", dev->name, ret);
+               goto reset_err;
+       }
+
+       priv->fifo_size = stm32_spi_get_fifo_size(dev);
+
+       priv->cur_mode = SPI_FULL_DUPLEX;
+       priv->cur_xferlen = 0;
+       priv->cur_bpw = SPI_DEFAULT_WORDLEN;
+       clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_DSIZE,
+                       priv->cur_bpw - 1);
+
+       for (i = 0; i < ARRAY_SIZE(priv->cs_gpios); i++) {
+               if (!dm_gpio_is_valid(&priv->cs_gpios[i]))
+                       continue;
+
+               dm_gpio_set_dir_flags(&priv->cs_gpios[i],
+                                     GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+       }
+
+       /* Ensure I2SMOD bit is kept cleared */
+       clrbits_le32(priv->base + STM32_SPI_I2SCFGR, SPI_I2SCFGR_I2SMOD);
+
+       /*
+        * - SS input value high
+        * - transmitter half duplex direction
+        * - automatic communication suspend when RX-Fifo is full
+        */
+       setbits_le32(priv->base + STM32_SPI_CR1,
+                    SPI_CR1_SSI | SPI_CR1_HDDIR | SPI_CR1_MASRX);
+
+       /*
+        * - Set the master mode (default Motorola mode)
+        * - Consider 1 master/n slaves configuration and
+        *   SS input value is determined by the SSI bit
+        * - keep control of all associated GPIOs
+        */
+       setbits_le32(priv->base + STM32_SPI_CFG2,
+                    SPI_CFG2_MASTER | SPI_CFG2_SSM | SPI_CFG2_AFCNTR);
+
+       return 0;
+
+reset_err:
+       reset_free(&priv->rst_ctl);
+
+clk_err:
+       clk_disable(&priv->clk);
+       clk_free(&priv->clk);
+
+       return ret;
+};
+
+static int stm32_spi_remove(struct udevice *dev)
+{
+       struct stm32_spi_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       stm32_spi_stopxfer(dev);
+       stm32_spi_disable(priv);
+
+       ret = reset_assert(&priv->rst_ctl);
+       if (ret < 0)
+               return ret;
+
+       reset_free(&priv->rst_ctl);
+
+       ret = clk_disable(&priv->clk);
+       if (ret < 0)
+               return ret;
+
+       clk_free(&priv->clk);
+
+       return ret;
+};
+
+static const struct dm_spi_ops stm32_spi_ops = {
+       .claim_bus      = stm32_spi_claim_bus,
+       .release_bus    = stm32_spi_release_bus,
+       .set_mode       = stm32_spi_set_mode,
+       .set_speed      = stm32_spi_set_speed,
+       .xfer           = stm32_spi_xfer,
+};
+
+static const struct udevice_id stm32_spi_ids[] = {
+       { .compatible = "st,stm32h7-spi", },
+       { }
+};
+
+U_BOOT_DRIVER(stm32_spi) = {
+       .name                   = "stm32_spi",
+       .id                     = UCLASS_SPI,
+       .of_match               = stm32_spi_ids,
+       .ops                    = &stm32_spi_ops,
+       .priv_auto_alloc_size   = sizeof(struct stm32_spi_priv),
+       .probe                  = stm32_spi_probe,
+       .remove                 = stm32_spi_remove,
+};
index b01dbc446dfa1e351e6b19656efa9c6ed87666a2..dbafb74a34d2a941b147b465aebe00a4de2fbc55 100644 (file)
@@ -26,6 +26,13 @@ config BCM2835_WDT
          This provides basic infrastructure to support BCM2835/2836 watchdog
          hardware, with a max timeout of ~15secs.
 
+config IMX_WATCHDOG
+       bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP"
+       select HW_WATCHDOG
+       help
+          Select this to enable the IMX and LSCH2 of Layerscape watchdog
+          driver.
+
 config OMAP_WATCHDOG
        bool "TI OMAP watchdog driver"
        depends on ARCH_OMAP2PLUS
@@ -59,14 +66,6 @@ config WDT
          What exactly happens when the timer expires is up to a particular
          device/driver.
 
-config WDT_SANDBOX
-       bool "Enable Watchdog Timer support for Sandbox"
-       depends on SANDBOX && WDT
-       help
-         Enable Watchdog Timer support in Sandbox. This is a dummy device that
-         can be probed and supports all of the methods of WDT, but does not
-         really do anything.
-
 config WDT_ARMADA_37XX
        bool "Marvell Armada 37xx watchdog timer support"
        depends on WDT && ARMADA_3700
@@ -87,6 +86,13 @@ config WDT_ASPEED
          It currently does not support Boot Flash Addressing Mode Detection or
          Second Boot.
 
+config WDT_AT91
+       bool "AT91 watchdog timer support"
+       depends on WDT
+       help
+          Select this to enable Microchip watchdog timer, which can be found on
+          some AT91 devices.
+
 config WDT_BCM6345
        bool "BCM6345 watchdog timer support"
        depends on WDT && (ARCH_BMIPS || ARCH_BCM6858 || ARCH_BCM63158)
@@ -95,21 +101,6 @@ config WDT_BCM6345
          The watchdog timer is stopped when initialized.
          It performs full SoC reset.
 
-config WDT_ORION
-       bool "Orion watchdog timer support"
-       depends on WDT
-       select CLK
-       help
-          Select this to enable Orion watchdog timer, which can be found on some
-          Marvell Armada chips.
-
-config WDT_SP805
-       bool "SP805 watchdog timer support"
-       depends on WDT
-       help
-          Select this to enable SP805 watchdog timer, which can be found on some
-          nxp layerscape chips.
-
 config WDT_CDNS
        bool "Cadence watchdog timer support"
        depends on WDT
@@ -118,6 +109,20 @@ config WDT_CDNS
           Select this to enable Cadence watchdog timer, which can be found on some
           Xilinx Microzed Platform.
 
+config WDT_MPC8xx
+       bool "MPC8xx watchdog timer support"
+       depends on WDT && MPC8xx
+       select CONFIG_MPC8xx_WATCHDOG
+       help
+          Select this to enable mpc8xx watchdog timer
+
+config WDT_MT7621
+       bool "MediaTek MT7621 watchdog timer support"
+       depends on WDT && SOC_MT7628
+       help
+          Select this to enable Ralink / Mediatek watchdog timer,
+          which can be found on some MediaTek chips.
+
 config WDT_MTK
        bool "MediaTek watchdog timer support"
        depends on WDT && ARCH_MEDIATEK
@@ -126,39 +131,43 @@ config WDT_MTK
          The watchdog timer is stopped when initialized.
          It performs full SoC reset.
 
-config XILINX_TB_WATCHDOG
-       bool "Xilinx Axi watchdog timer support"
+config WDT_ORION
+       bool "Orion watchdog timer support"
        depends on WDT
-       imply WATCHDOG
+       select CLK
        help
-          Select this to enable Xilinx Axi watchdog timer, which can be found on some
-          Xilinx Microblaze Platforms.
+          Select this to enable Orion watchdog timer, which can be found on some
+          Marvell Armada chips.
 
-config IMX_WATCHDOG
-       bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP"
-       select HW_WATCHDOG
+config WDT_SANDBOX
+       bool "Enable Watchdog Timer support for Sandbox"
+       depends on SANDBOX && WDT
        help
-          Select this to enable the IMX and LSCH2 of Layerscape watchdog
-          driver.
+         Enable Watchdog Timer support in Sandbox. This is a dummy device that
+         can be probed and supports all of the methods of WDT, but does not
+         really do anything.
 
-config WDT_AT91
-       bool "AT91 watchdog timer support"
+config WDT_SP805
+       bool "SP805 watchdog timer support"
        depends on WDT
        help
-          Select this to enable Microchip watchdog timer, which can be found on
-          some AT91 devices.
+          Select this to enable SP805 watchdog timer, which can be found on some
+          nxp layerscape chips.
 
-config WDT_MT7621
-       bool "MediaTek MT7621 watchdog timer support"
-       depends on WDT && SOC_MT7628
+config WDT_STM32MP
+       bool "IWDG watchdog driver for STM32 MP's family"
+       depends on WDT
+       imply WATCHDOG
        help
-          Select this to enable Ralink / Mediatek watchdog timer,
-          which can be found on some MediaTek chips.
+         Enable the STM32 watchdog (IWDG) driver. Enable support to
+         configure STM32's on-SoC watchdog.
 
-config WDT_MPC8xx
-       bool "MPC8xx watchdog timer support"
-       depends on WDT && MPC8xx
+config XILINX_TB_WATCHDOG
+       bool "Xilinx Axi watchdog timer support"
+       depends on WDT
+       imply WATCHDOG
        help
-          Select this to enable mpc8xx watchdog timer
+          Select this to enable Xilinx Axi watchdog timer, which can be found on some
+          Xilinx Microblaze Platforms.
 
 endmenu
index 6f20e73810a273dc5a33cb106793bfc60e787f5c..e3f4fdb406f4619fc1316edbdbb17b3e4031b99b 100644 (file)
@@ -28,3 +28,4 @@ obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o
 obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o
 obj-$(CONFIG_WDT_MTK) += mtk_wdt.o
 obj-$(CONFIG_WDT_SP805) += sp805_wdt.o
+obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o
diff --git a/drivers/watchdog/stm32mp_wdt.c b/drivers/watchdog/stm32mp_wdt.c
new file mode 100644 (file)
index 0000000..8093d0a
--- /dev/null
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <syscon.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <linux/iopoll.h>
+
+/* IWDG registers */
+#define IWDG_KR                0x00    /* Key register */
+#define IWDG_PR                0x04    /* Prescaler Register */
+#define IWDG_RLR       0x08    /* ReLoad Register */
+#define IWDG_SR                0x0C    /* Status Register */
+
+/* IWDG_KR register bit mask */
+#define KR_KEY_RELOAD  0xAAAA  /* Reload counter enable */
+#define KR_KEY_ENABLE  0xCCCC  /* Peripheral enable */
+#define KR_KEY_EWA     0x5555  /* Write access enable */
+
+/* IWDG_PR register bit values */
+#define PR_256         0x06    /* Prescaler set to 256 */
+
+/* IWDG_RLR register values */
+#define RLR_MAX                0xFFF   /* Max value supported by reload register */
+
+/* IWDG_SR register bit values */
+#define SR_PVU         BIT(0)  /* Watchdog prescaler value update */
+#define SR_RVU         BIT(1)  /* Watchdog counter reload value update */
+
+struct stm32mp_wdt_priv {
+       fdt_addr_t base;                /* registers addr in physical memory */
+       unsigned long wdt_clk_rate;     /* Watchdog dedicated clock rate */
+};
+
+static int stm32mp_wdt_reset(struct udevice *dev)
+{
+       struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
+
+       writel(KR_KEY_RELOAD, priv->base + IWDG_KR);
+
+       return 0;
+}
+
+static int stm32mp_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
+{
+       struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
+       int reload;
+       u32 val;
+       int ret;
+
+       /* Prescaler fixed to 256 */
+       reload = timeout_ms * priv->wdt_clk_rate / 256;
+       if (reload > RLR_MAX + 1)
+               /* Force to max watchdog counter reload value */
+               reload = RLR_MAX + 1;
+       else if (!reload)
+               /* Force to min watchdog counter reload value */
+               reload = priv->wdt_clk_rate / 256;
+
+       /* Set prescaler & reload registers */
+       writel(KR_KEY_EWA, priv->base + IWDG_KR);
+       writel(PR_256, priv->base + IWDG_PR);
+       writel(reload - 1, priv->base + IWDG_RLR);
+
+       /* Enable watchdog */
+       writel(KR_KEY_ENABLE, priv->base + IWDG_KR);
+
+       /* Wait for the registers to be updated */
+       ret = readl_poll_timeout(priv->base + IWDG_SR, val,
+                                val & (SR_PVU | SR_RVU), CONFIG_SYS_HZ);
+
+       if (ret < 0) {
+               pr_err("Updating IWDG registers timeout");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int stm32mp_wdt_probe(struct udevice *dev)
+{
+       struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
+       struct clk clk;
+       int ret;
+
+       debug("IWDG init\n");
+
+       priv->base = devfdt_get_addr(dev);
+       if (priv->base == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       /* Enable clock */
+       ret = clk_get_by_name(dev, "pclk", &clk);
+       if (ret)
+               return ret;
+
+       ret = clk_enable(&clk);
+       if (ret)
+               return ret;
+
+       /* Get LSI clock */
+       ret = clk_get_by_name(dev, "lsi", &clk);
+       if (ret)
+               return ret;
+
+       priv->wdt_clk_rate = clk_get_rate(&clk);
+
+       debug("IWDG init done\n");
+
+       return 0;
+}
+
+static const struct wdt_ops stm32mp_wdt_ops = {
+       .start = stm32mp_wdt_start,
+       .reset = stm32mp_wdt_reset,
+};
+
+static const struct udevice_id stm32mp_wdt_match[] = {
+       { .compatible = "st,stm32mp1-iwdg" },
+       { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(stm32mp_wdt) = {
+       .name = "stm32mp-wdt",
+       .id = UCLASS_WDT,
+       .of_match = stm32mp_wdt_match,
+       .priv_auto_alloc_size = sizeof(struct stm32mp_wdt_priv),
+       .probe = stm32mp_wdt_probe,
+       .ops = &stm32mp_wdt_ops,
+};
index 1e10c7a4c46b1ea0370d5d8cb5d33d105e91eb15..5651685c150ba313fc660a5ab13f18b436d846f5 100644 (file)
@@ -2,18 +2,12 @@ menu "Environment"
 
 config ENV_IS_NOWHERE
        bool "Environment is not stored"
-       depends on !ENV_IS_IN_EEPROM
-       depends on !ENV_IS_IN_EXT4
-       depends on !ENV_IS_IN_FAT
-       depends on !ENV_IS_IN_FLASH
-       depends on !ENV_IS_IN_MMC
-       depends on !ENV_IS_IN_NAND
-       depends on !ENV_IS_IN_NVRAM
-       depends on !ENV_IS_IN_ONENAND
-       depends on !ENV_IS_IN_REMOTE
-       depends on !ENV_IS_IN_SPI_FLASH
-       depends on !ENV_IS_IN_UBI
-       default y
+       default y if !ENV_IS_IN_EEPROM && !ENV_IS_IN_EXT4 && \
+                    !ENV_IS_IN_FAT && !ENV_IS_IN_FLASH && \
+                    !ENV_IS_IN_MMC && !ENV_IS_IN_NAND && \
+                    !ENV_IS_IN_NVRAM && !ENV_IS_IN_ONENAND && \
+                    !ENV_IS_IN_REMOTE && !ENV_IS_IN_SPI_FLASH && \
+                    !ENV_IS_IN_UBI
        help
          Define this if you don't want to or can't have an environment stored
          on a storage medium. In this case the environment will still exist
index 388474a11c750070e444609e2676878db71aa4bd..9947381bfdb5858ef393252304f6d1c429d9674e 100644 (file)
 #include <ext4fs.h>
 #include <mmc.h>
 
+__weak const char *env_ext4_get_intf(void)
+{
+       return (const char *)CONFIG_ENV_EXT4_INTERFACE;
+}
+
+__weak const char *env_ext4_get_dev_part(void)
+{
+       return (const char *)CONFIG_ENV_EXT4_DEVICE_AND_PART;
+}
+
 #ifdef CONFIG_CMD_SAVEENV
 static int env_ext4_save(void)
 {
@@ -38,13 +48,14 @@ static int env_ext4_save(void)
        disk_partition_t info;
        int dev, part;
        int err;
+       const char *ifname = env_ext4_get_intf();
+       const char *dev_and_part = env_ext4_get_dev_part();
 
        err = env_export(&env_new);
        if (err)
                return err;
 
-       part = blk_get_device_part_str(CONFIG_ENV_EXT4_INTERFACE,
-                                      CONFIG_ENV_EXT4_DEVICE_AND_PART,
+       part = blk_get_device_part_str(ifname, dev_and_part,
                                       &dev_desc, &info, 1);
        if (part < 0)
                return 1;
@@ -54,8 +65,7 @@ static int env_ext4_save(void)
 
        if (!ext4fs_mount(info.size)) {
                printf("\n** Unable to use %s %s for saveenv **\n",
-                      CONFIG_ENV_EXT4_INTERFACE,
-                      CONFIG_ENV_EXT4_DEVICE_AND_PART);
+                      ifname, dev_and_part);
                return 1;
        }
 
@@ -65,8 +75,7 @@ static int env_ext4_save(void)
 
        if (err == -1) {
                printf("\n** Unable to write \"%s\" from %s%d:%d **\n",
-                       CONFIG_ENV_EXT4_FILE, CONFIG_ENV_EXT4_INTERFACE, dev,
-                       part);
+                       CONFIG_ENV_EXT4_FILE, ifname, dev, part);
                return 1;
        }
 
@@ -83,14 +92,15 @@ static int env_ext4_load(void)
        int dev, part;
        int err;
        loff_t off;
+       const char *ifname = env_ext4_get_intf();
+       const char *dev_and_part = env_ext4_get_dev_part();
 
 #ifdef CONFIG_MMC
-       if (!strcmp(CONFIG_ENV_EXT4_INTERFACE, "mmc"))
+       if (!strcmp(ifname, "mmc"))
                mmc_initialize(NULL);
 #endif
 
-       part = blk_get_device_part_str(CONFIG_ENV_EXT4_INTERFACE,
-                                      CONFIG_ENV_EXT4_DEVICE_AND_PART,
+       part = blk_get_device_part_str(ifname, dev_and_part,
                                       &dev_desc, &info, 1);
        if (part < 0)
                goto err_env_relocate;
@@ -100,8 +110,7 @@ static int env_ext4_load(void)
 
        if (!ext4fs_mount(info.size)) {
                printf("\n** Unable to use %s %s for loading the env **\n",
-                      CONFIG_ENV_EXT4_INTERFACE,
-                      CONFIG_ENV_EXT4_DEVICE_AND_PART);
+                      ifname, dev_and_part);
                goto err_env_relocate;
        }
 
@@ -111,8 +120,7 @@ static int env_ext4_load(void)
 
        if (err == -1) {
                printf("\n** Unable to read \"%s\" from %s%d:%d **\n",
-                       CONFIG_ENV_EXT4_FILE, CONFIG_ENV_EXT4_INTERFACE, dev,
-                       part);
+                       CONFIG_ENV_EXT4_FILE, ifname, dev, part);
                goto err_env_relocate;
        }
 
index e8be51a1559d94c3de2e1f4feb71aa5cf5e7382a..1d385e0985c443c77ba699e234a2920a448570aa 100644 (file)
  */
 #define CONFIG_SYS_LOAD_ADDR                   STM32_DDR_BASE
 
+#if defined(CONFIG_ENV_IS_IN_UBI)
+#define CONFIG_ENV_UBI_VOLUME_REDUND           "uboot_config_r"
+#endif
+
+#if defined(CONFIG_ENV_IS_IN_SPI_FLASH)
+#define        CONFIG_ENV_SECT_SIZE                    SZ_256K
+#define        CONFIG_ENV_OFFSET                       0x00280000
+#endif
+
 /* ATAGs */
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
 /*MMC SD*/
 #define CONFIG_SYS_MMC_MAX_DEVICE      3
 
+/* Ethernet need */
+#ifdef CONFIG_DWC_ETH_QOS
+#define CONFIG_SYS_NONCACHED_MEMORY    (1 * SZ_1M)     /* 1M */
+#define CONFIG_SERVERIP                 192.168.1.1
+#define CONFIG_BOOTP_SERVERIP
+#define CONFIG_SYS_AUTOLOAD            "no"
+#endif
+
 /*****************************************************************************/
 #ifdef CONFIG_DISTRO_DEFAULTS
 /*****************************************************************************/
 
 #if !defined(CONFIG_SPL_BUILD)
 
+/* NAND support */
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+#define CONFIG_SYS_MAX_NAND_DEVICE     1
 #define BOOT_TARGET_DEVICES(func) \
        func(MMC, mmc, 1) \
        func(MMC, mmc, 0) \
-       func(MMC, mmc, 2)
+       func(MMC, mmc, 2) \
+       func(PXE, pxe, na)
+
 /*
  * bootcmd for stm32mp1:
  * for serial/usb: execute the stm32prog command
 
 #include <config_distro_bootcmd.h>
 
+#if defined(CONFIG_STM32_QSPI) || defined(CONFIG_NAND_STM32_FMC)
+#define CONFIG_SYS_MTDPARTS_RUNTIME
+#endif
+
+#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"
+
 /*
  * memory layout for 32M uncompressed/compressed kernel,
  * 1M fdt, 1M script, 1M pxe and 1M for splashimage
        "fdt_high=0xffffffff\0" \
        "initrd_high=0xffffffff\0" \
        STM32MP_BOOTCMD \
+       STM32MP_MTDPARTS \
        BOOTENV
 
 #endif /* ifndef CONFIG_SPL_BUILD */