summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/Kconfig2
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/dts/k3-am65.dtsi2
-rw-r--r--arch/arm/dts/k3-am654-base-board-u-boot.dtsi170
-rw-r--r--arch/arm/dts/stm32429i-eval-u-boot.dtsi11
-rw-r--r--arch/arm/dts/stm32f429-disco-u-boot.dtsi11
-rw-r--r--arch/arm/dts/stm32f469-disco-u-boot.dtsi11
-rw-r--r--arch/arm/dts/stm32f7-u-boot.dtsi17
-rw-r--r--arch/arm/dts/stm32mp15-ddr.dtsi2
-rw-r--r--arch/arm/dts/stm32mp157-pinctrl.dtsi270
-rw-r--r--arch/arm/dts/stm32mp157-u-boot.dtsi79
-rw-r--r--arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi4
-rw-r--r--arch/arm/dts/stm32mp157a-dk1.dts32
-rw-r--r--arch/arm/dts/stm32mp157c-dk2.dts1
-rw-r--r--arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi15
-rw-r--r--arch/arm/dts/stm32mp157c-ed1.dts205
-rw-r--r--arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi3
-rw-r--r--arch/arm/dts/stm32mp157c-ev1.dts12
-rw-r--r--arch/arm/dts/stm32mp157c.dtsi215
-rw-r--r--arch/arm/mach-stm32mp/Kconfig28
-rw-r--r--arch/arm/mach-stm32mp/Makefile2
-rw-r--r--arch/arm/mach-stm32mp/bsec.c14
-rw-r--r--arch/arm/mach-stm32mp/cmd_stm32key.c101
-rw-r--r--arch/arm/mach-stm32mp/cpu.c9
-rw-r--r--arch/arm/mach-stm32mp/fdt.c223
-rw-r--r--arch/arm/mach-stm32mp/include/mach/stm32.h3
-rw-r--r--arch/arm/mach-stm32mp/include/mach/sys_proto.h9
-rw-r--r--arch/arm/mach-stm32mp/syscon.c2
-rw-r--r--arch/sandbox/dts/test.dts4
-rw-r--r--board/st/stm32f429-discovery/led.c2
-rw-r--r--board/st/stm32mp1/Kconfig13
-rw-r--r--board/st/stm32mp1/MAINTAINERS1
-rw-r--r--board/st/stm32mp1/Makefile1
-rw-r--r--board/st/stm32mp1/README46
-rw-r--r--board/st/stm32mp1/cmd_stboard.c145
-rw-r--r--board/st/stm32mp1/spl.c1
-rw-r--r--board/st/stm32mp1/stm32mp1.c27
-rw-r--r--cmd/Kconfig9
-rw-r--r--cmd/Makefile1
-rw-r--r--cmd/mdio.c5
-rw-r--r--cmd/mii.c189
-rw-r--r--cmd/mmc_spi.c88
-rw-r--r--cmd/pinmux.c1
-rw-r--r--configs/am65x_evm_a53_defconfig6
-rw-r--r--configs/stm32mp15_basic_defconfig9
-rw-r--r--configs/stm32mp15_optee_defconfig107
-rw-r--r--configs/stm32mp15_trusted_defconfig5
-rw-r--r--doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt101
-rw-r--r--drivers/adc/stm32-adc-core.c3
-rw-r--r--drivers/adc/stm32-adc.c13
-rw-r--r--drivers/clk/clk_stm32mp1.c10
-rw-r--r--drivers/gpio/Kconfig4
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/stm32_gpio.c (renamed from drivers/gpio/stm32f7_gpio.c)8
-rw-r--r--drivers/i2c/stm32f7_i2c.c12
-rw-r--r--drivers/mailbox/Kconfig7
-rw-r--r--drivers/mailbox/Makefile1
-rw-r--r--drivers/mailbox/stm32-ipcc.c167
-rw-r--r--drivers/misc/stm32mp_fuse.c1
-rw-r--r--drivers/mmc/Kconfig30
-rw-r--r--drivers/mmc/fsl_esdhc_imx.c49
-rw-r--r--drivers/mmc/mmc-uclass.c48
-rw-r--r--drivers/mmc/mmc.c255
-rw-r--r--drivers/mmc/mmc_private.h9
-rw-r--r--drivers/mmc/mmc_spi.c469
-rw-r--r--drivers/mmc/mmc_write.c4
-rw-r--r--drivers/mmc/omap_hsmmc.c26
-rw-r--r--drivers/mmc/rpmb.c4
-rw-r--r--drivers/mmc/sdhci.c38
-rw-r--r--drivers/mmc/stm32_sdmmc2.c3
-rw-r--r--drivers/mtd/nand/raw/stm32_fmc2_nand.c93
-rw-r--r--drivers/net/Kconfig23
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/macb.c8
-rw-r--r--drivers/net/mdio_sandbox.c92
-rw-r--r--drivers/net/mscc_eswitch/Makefile10
-rw-r--r--drivers/net/mscc_eswitch/jr2_switch.c119
-rw-r--r--drivers/net/mscc_eswitch/luton_switch.c101
-rw-r--r--drivers/net/mscc_eswitch/mscc_miim.c28
-rw-r--r--drivers/net/mscc_eswitch/mscc_miim.h14
-rw-r--r--drivers/net/mscc_eswitch/ocelot_switch.c104
-rw-r--r--drivers/net/mscc_eswitch/serval_switch.c103
-rw-r--r--drivers/net/mscc_eswitch/servalt_switch.c102
-rw-r--r--drivers/net/phy/cortina.c5
-rw-r--r--drivers/net/phy/ti.c16
-rw-r--r--drivers/net/ti/Kconfig8
-rw-r--r--drivers/net/ti/Makefile1
-rw-r--r--drivers/net/ti/am65-cpsw-nuss.c792
-rw-r--r--drivers/net/ti/cpsw_mdio.c4
-rw-r--r--drivers/net/ti/cpsw_mdio.h2
-rw-r--r--drivers/pinctrl/pinctrl_stm32.c36
-rw-r--r--drivers/power/pmic/stpmic1.c11
-rw-r--r--drivers/power/regulator/stm32-vrefbuf.c2
-rw-r--r--drivers/power/regulator/stpmic1.c1
-rw-r--r--drivers/ram/stm32mp1/stm32mp1_ram.c5
-rw-r--r--drivers/serial/serial_stm32.c4
-rw-r--r--drivers/spi/stm32_qspi.c24
-rw-r--r--drivers/spi/stm32_spi.c11
-rw-r--r--drivers/sysreset/sysreset_syscon.c6
-rw-r--r--env/Kconfig5
-rw-r--r--include/configs/UCP1020.h1
-rw-r--r--include/configs/stm32mp1.h43
-rw-r--r--include/dm/uclass-id.h1
-rw-r--r--include/dt-bindings/pinctrl/stm32-pinfunc.h6
-rw-r--r--include/miiphy.h49
-rw-r--r--include/mmc.h37
-rw-r--r--include/mvebu_mmc.h4
-rw-r--r--net/Makefile1
-rw-r--r--net/mdio-uclass.c115
-rw-r--r--scripts/config_whitelist.txt6
-rw-r--r--test/dm/Makefile1
-rw-r--r--test/dm/mdio.c53
113 files changed, 3855 insertions, 1573 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index e91684191f..bc67c49965 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -297,10 +297,12 @@ ARM STM STM32MP
M: Patrick Delaunay <patrick.delaunay@st.com>
M: Patrice Chotard <patrice.chotard@st.com>
L: uboot-stm32@st-md-mailman.stormreply.com (moderated for non-subscribers)
+T: git https://gitlab.denx.de/u-boot/custodians/u-boot-stm
S: Maintained
F: arch/arm/mach-stm32mp/
F: drivers/clk/clk_stm32mp1.c
F: drivers/i2c/stm32f7_i2c.c
+F: drivers/mailbox/stm32-ipcc.c
F: drivers/misc/stm32mp_fuse.c
F: drivers/mmc/stm32_sdmmc2.c
F: drivers/phy/phy-stm32-usbphyc.c
diff --git a/arch/Kconfig b/arch/Kconfig
index 355d214522..a946af816f 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -123,6 +123,8 @@ config SANDBOX
imply DM_SOUND
imply PCI_SANDBOX_EP
imply PCH
+ imply PHYLIB
+ imply DM_MDIO
config SH
bool "SuperH architecture"
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 60c4a07a32..05606d9722 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1499,6 +1499,7 @@ config ARCH_STM32MP
select MISC
select OF_CONTROL
select OF_LIBFDT
+ select OF_SYSTEM_SETUP
select PINCTRL
select REGMAP
select SUPPORT_SPL
diff --git a/arch/arm/dts/k3-am65.dtsi b/arch/arm/dts/k3-am65.dtsi
index 3d4bf369d0..9d1ed49753 100644
--- a/arch/arm/dts/k3-am65.dtsi
+++ b/arch/arm/dts/k3-am65.dtsi
@@ -64,6 +64,7 @@
/* MCUSS Range */
<0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>,
<0x00 0x40200000 0x00 0x40200000 0x00 0x00900100>,
+ <0x00 0x40f00000 0x00 0x40f00000 0x00 0x00020000>,
<0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>,
<0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>,
<0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>,
@@ -75,6 +76,7 @@
#size-cells = <2>;
ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>, /* MCU NAVSS*/
<0x00 0x40200000 0x00 0x40200000 0x00 0x00900100>, /* First peripheral window */
+ <0x00 0x40f00000 0x00 0x40f00000 0x00 0x00020000>, /* CTRL_MMR0 */
<0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>, /* WKUP */
<0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, /* MMRs, remaining NAVSS */
<0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, /* CPSW */
diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
index f5c8253831..844a5cd96a 100644
--- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
+++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi
@@ -5,6 +5,7 @@
#include <dt-bindings/pinctrl/k3.h>
#include <dt-bindings/dma/k3-udma.h>
+#include <dt-bindings/net/ti-dp83867.h>
/ {
chosen {
@@ -13,6 +14,7 @@
aliases {
serial2 = &main_uart0;
+ ethernet0 = &cpsw_port1;
};
};
@@ -110,6 +112,116 @@
dma-coherent;
};
};
+
+ mcu_conf: scm_conf@40f00000 {
+ compatible = "syscon";
+ reg = <0x0 0x40f00000 0x0 0x20000>;
+ };
+
+ mcu_cpsw: cpsw_nuss@046000000 {
+ compatible = "ti,am654-cpsw-nuss";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ reg = <0x0 0x46000000 0x0 0x200000>;
+ reg-names = "cpsw_nuss";
+ ranges;
+ dma-coherent;
+ clocks = <&k3_clks 5 10>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 5>;
+ ti,psil-base = <0x7000>;
+
+ dmas = <&mcu_udmap &mcu_cpsw 0 UDMA_DIR_TX>,
+ <&mcu_udmap &mcu_cpsw 1 UDMA_DIR_TX>,
+ <&mcu_udmap &mcu_cpsw 2 UDMA_DIR_TX>,
+ <&mcu_udmap &mcu_cpsw 3 UDMA_DIR_TX>,
+ <&mcu_udmap &mcu_cpsw 4 UDMA_DIR_TX>,
+ <&mcu_udmap &mcu_cpsw 5 UDMA_DIR_TX>,
+ <&mcu_udmap &mcu_cpsw 6 UDMA_DIR_TX>,
+ <&mcu_udmap &mcu_cpsw 7 UDMA_DIR_TX>,
+ <&mcu_udmap &mcu_cpsw 0 UDMA_DIR_RX>;
+ dma-names = "tx0", "tx1", "tx2", "tx3",
+ "tx4", "tx5", "tx6", "tx7",
+ "rx";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ host: host@0 {
+ reg = <0>;
+ ti,label = "host";
+ };
+
+ cpsw_port1: port@1 {
+ reg = <1>;
+ ti,mac-only;
+ ti,label = "port1";
+ ti,syscon-efuse = <&mcu_conf 0x200>;
+ };
+ };
+
+ davinci_mdio: mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ bus_freq = <1000000>;
+ };
+
+ ti,psil-config0 {
+ linux,udma-mode = <UDMA_PKT_MODE>;
+ statictr-type = <PSIL_STATIC_TR_NONE>;
+ ti,needs-epib;
+ ti,psd-size = <16>;
+ };
+
+ ti,psil-config1 {
+ linux,udma-mode = <UDMA_PKT_MODE>;
+ statictr-type = <PSIL_STATIC_TR_NONE>;
+ ti,needs-epib;
+ ti,psd-size = <16>;
+ };
+
+ ti,psil-config2 {
+ linux,udma-mode = <UDMA_PKT_MODE>;
+ statictr-type = <PSIL_STATIC_TR_NONE>;
+ ti,needs-epib;
+ ti,psd-size = <16>;
+ };
+
+ ti,psil-config3 {
+ linux,udma-mode = <UDMA_PKT_MODE>;
+ statictr-type = <PSIL_STATIC_TR_NONE>;
+ ti,needs-epib;
+ ti,psd-size = <16>;
+ };
+
+ ti,psil-config4 {
+ linux,udma-mode = <UDMA_PKT_MODE>;
+ statictr-type = <PSIL_STATIC_TR_NONE>;
+ ti,needs-epib;
+ ti,psd-size = <16>;
+ };
+
+ ti,psil-config5 {
+ linux,udma-mode = <UDMA_PKT_MODE>;
+ statictr-type = <PSIL_STATIC_TR_NONE>;
+ ti,needs-epib;
+ ti,psd-size = <16>;
+ };
+
+ ti,psil-config6 {
+ linux,udma-mode = <UDMA_PKT_MODE>;
+ statictr-type = <PSIL_STATIC_TR_NONE>;
+ ti,needs-epib;
+ ti,psd-size = <16>;
+ };
+
+ ti,psil-config7 {
+ linux,udma-mode = <UDMA_PKT_MODE>;
+ statictr-type = <PSIL_STATIC_TR_NONE>;
+ ti,needs-epib;
+ ti,psd-size = <16>;
+ };
+ };
};
&cbass_wakeup {
@@ -189,6 +301,32 @@
u-boot,dm-spl;
};
+&wkup_pmx0 {
+ mcu_cpsw_pins_default: mcu_cpsw_pins_default {
+ pinctrl-single,pins = <
+ AM65X_WKUP_IOPAD(0x0058, PIN_OUTPUT, 0) /* (N4) MCU_RGMII1_TX_CTL */
+ AM65X_WKUP_IOPAD(0x005c, PIN_INPUT, 0) /* (N5) MCU_RGMII1_RX_CTL */
+ AM65X_WKUP_IOPAD(0x0060, PIN_OUTPUT, 0) /* (M2) MCU_RGMII1_TD3 */
+ AM65X_WKUP_IOPAD(0x0064, PIN_OUTPUT, 0) /* (M3) MCU_RGMII1_TD2 */
+ AM65X_WKUP_IOPAD(0x0068, PIN_OUTPUT, 0) /* (M4) MCU_RGMII1_TD1 */
+ AM65X_WKUP_IOPAD(0x006c, PIN_OUTPUT, 0) /* (M5) MCU_RGMII1_TD0 */
+ AM65X_WKUP_IOPAD(0x0078, PIN_INPUT, 0) /* (L2) MCU_RGMII1_RD3 */
+ AM65X_WKUP_IOPAD(0x007c, PIN_INPUT, 0) /* (L5) MCU_RGMII1_RD2 */
+ AM65X_WKUP_IOPAD(0x0080, PIN_INPUT, 0) /* (M6) MCU_RGMII1_RD1 */
+ AM65X_WKUP_IOPAD(0x0084, PIN_INPUT, 0) /* (L6) MCU_RGMII1_RD0 */
+ AM65X_WKUP_IOPAD(0x0070, PIN_INPUT, 0) /* (N1) MCU_RGMII1_TXC */
+ AM65X_WKUP_IOPAD(0x0074, PIN_INPUT, 0) /* (M1) MCU_RGMII1_RXC */
+ >;
+ };
+
+ mcu_mdio_pins_default: mcu_mdio1_pins_default {
+ pinctrl-single,pins = <
+ AM65X_WKUP_IOPAD(0x008c, PIN_OUTPUT, 0) /* (L1) MCU_MDIO0_MDC */
+ AM65X_WKUP_IOPAD(0x0088, PIN_INPUT, 0) /* (L4) MCU_MDIO0_MDIO */
+ >;
+ };
+};
+
&main_uart0 {
u-boot,dm-spl;
pinctrl-names = "default";
@@ -212,3 +350,35 @@
pinctrl-0 = <&main_mmc1_pins_default>;
sdhci-caps-mask = <0x7 0x0>;
};
+
+&mcu_cpsw {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
+};
+
+&davinci_mdio {
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ /* TODO: phy reset: TCA9555RTWR(i2c:0x21)[p04].GPIO_MCU_RGMII_RSTN */
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+};
+
+&cpsw_port1 {
+ phy-mode = "rgmii-id";
+ phy-handle = <&phy0>;
+};
+
+&mcu_cpsw {
+ reg = <0x0 0x46000000 0x0 0x200000>,
+ <0x0 0x40f00200 0x0 0x2>;
+ reg-names = "cpsw_nuss", "mac_efuse";
+
+ cpsw-phy-sel@40f04040 {
+ compatible = "ti,am654-cpsw-phy-sel";
+ reg= <0x0 0x40f04040 0x0 0x4>;
+ reg-names = "gmii-sel";
+ };
+};
diff --git a/arch/arm/dts/stm32429i-eval-u-boot.dtsi b/arch/arm/dts/stm32429i-eval-u-boot.dtsi
index 6da0a636c1..fe437bbfe2 100644
--- a/arch/arm/dts/stm32429i-eval-u-boot.dtsi
+++ b/arch/arm/dts/stm32429i-eval-u-boot.dtsi
@@ -92,57 +92,46 @@
};
&gpioa {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiob {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioc {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiod {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioe {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiof {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiog {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioh {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioi {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioj {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiok {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
diff --git a/arch/arm/dts/stm32f429-disco-u-boot.dtsi b/arch/arm/dts/stm32f429-disco-u-boot.dtsi
index 0cc3100440..52f80320bc 100644
--- a/arch/arm/dts/stm32f429-disco-u-boot.dtsi
+++ b/arch/arm/dts/stm32f429-disco-u-boot.dtsi
@@ -79,57 +79,46 @@
};
&gpioa {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiob {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioc {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiod {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioe {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiof {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiog {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioh {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioi {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioj {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiok {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
diff --git a/arch/arm/dts/stm32f469-disco-u-boot.dtsi b/arch/arm/dts/stm32f469-disco-u-boot.dtsi
index 3da308e6a4..2409cf746a 100644
--- a/arch/arm/dts/stm32f469-disco-u-boot.dtsi
+++ b/arch/arm/dts/stm32f469-disco-u-boot.dtsi
@@ -94,57 +94,46 @@
};
&gpioa {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiob {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioc {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiod {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioe {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiof {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiog {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioh {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioi {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioj {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiok {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
diff --git a/arch/arm/dts/stm32f7-u-boot.dtsi b/arch/arm/dts/stm32f7-u-boot.dtsi
index 29b157324e..3ba7f8410d 100644
--- a/arch/arm/dts/stm32f7-u-boot.dtsi
+++ b/arch/arm/dts/stm32f7-u-boot.dtsi
@@ -65,58 +65,41 @@
};
&gpioa {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiob {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioc {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiod {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioe {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiof {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiog {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioh {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioi {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
-&gpioj {
- compatible = "st,stm32-gpio";
-};
-
-&gpiok {
- compatible = "st,stm32-gpio";
-};
-
&pinctrl {
u-boot,dm-pre-reloc;
diff --git a/arch/arm/dts/stm32mp15-ddr.dtsi b/arch/arm/dts/stm32mp15-ddr.dtsi
index 4172c02f0a..479b700c86 100644
--- a/arch/arm/dts/stm32mp15-ddr.dtsi
+++ b/arch/arm/dts/stm32mp15-ddr.dtsi
@@ -5,7 +5,7 @@
/ {
soc {
- ddr: ddr@0x5A003000{
+ ddr: ddr@5A003000 {
u-boot,dm-pre-reloc;
compatible = "st,stm32mp1-ddr";
diff --git a/arch/arm/dts/stm32mp157-pinctrl.dtsi b/arch/arm/dts/stm32mp157-pinctrl.dtsi
index 4c424c488d..9bae85045a 100644
--- a/arch/arm/dts/stm32mp157-pinctrl.dtsi
+++ b/arch/arm/dts/stm32mp157-pinctrl.dtsi
@@ -14,6 +14,7 @@
ranges = <0 0x50002000 0xa400>;
interrupt-parent = <&exti>;
st,syscfg = <&exti 0x60 0xff>;
+ hwlocks = <&hwspinlock 0>;
pins-are-numbered;
gpioa: gpio@50002000 {
@@ -164,6 +165,27 @@
};
};
+ cec_pins_sleep_a: cec-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 15, ANALOG)>; /* HDMI_CEC */
+ };
+ };
+
+ cec_pins_b: cec-1 {
+ pins {
+ pinmux = <STM32_PINMUX('B', 6, AF5)>;
+ bias-disable;
+ drive-open-drain;
+ slew-rate = <0>;
+ };
+ };
+
+ cec_pins_sleep_b: cec-sleep-1 {
+ pins {
+ pinmux = <STM32_PINMUX('B', 6, ANALOG)>; /* HDMI_CEC */
+ };
+ };
+
ethernet0_rgmii_pins_a: rgmii-0 {
pins1 {
pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
@@ -269,7 +291,14 @@
};
};
- i2c1_pins_b: i2c1-1 {
+ i2c1_pins_sleep_a: i2c1-1 {
+ pins {
+ pinmux = <STM32_PINMUX('D', 12, ANALOG)>, /* I2C1_SCL */
+ <STM32_PINMUX('F', 15, ANALOG)>; /* I2C1_SDA */
+ };
+ };
+
+ i2c1_pins_b: i2c1-2 {
pins {
pinmux = <STM32_PINMUX('F', 14, AF5)>, /* I2C1_SCL */
<STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */
@@ -289,7 +318,14 @@
};
};
- i2c2_pins_b: i2c2-1 {
+ i2c2_pins_sleep_a: i2c2-1 {
+ pins {
+ pinmux = <STM32_PINMUX('H', 4, ANALOG)>, /* I2C2_SCL */
+ <STM32_PINMUX('H', 5, ANALOG)>; /* I2C2_SDA */
+ };
+ };
+
+ i2c2_pins_b: i2c2-2 {
pins {
pinmux = <STM32_PINMUX('Z', 0, AF3)>, /* I2C2_SCL */
<STM32_PINMUX('H', 5, AF4)>; /* I2C2_SDA */
@@ -309,6 +345,152 @@
};
};
+ i2c5_pins_sleep_a: i2c5-1 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 11, ANALOG)>, /* I2C5_SCL */
+ <STM32_PINMUX('A', 12, ANALOG)>; /* I2C5_SDA */
+
+ };
+ };
+
+ ltdc_pins_a: ltdc-a-0 {
+ pins {
+ pinmux = <STM32_PINMUX('G', 7, AF14)>, /* LCD_CLK */
+ <STM32_PINMUX('I', 10, AF14)>, /* LCD_HSYNC */
+ <STM32_PINMUX('I', 9, AF14)>, /* LCD_VSYNC */
+ <STM32_PINMUX('F', 10, AF14)>, /* LCD_DE */
+ <STM32_PINMUX('H', 2, AF14)>, /* LCD_R0 */
+ <STM32_PINMUX('H', 3, AF14)>, /* LCD_R1 */
+ <STM32_PINMUX('H', 8, AF14)>, /* LCD_R2 */
+ <STM32_PINMUX('H', 9, AF14)>, /* LCD_R3 */
+ <STM32_PINMUX('H', 10, AF14)>, /* LCD_R4 */
+ <STM32_PINMUX('C', 0, AF14)>, /* LCD_R5 */
+ <STM32_PINMUX('H', 12, AF14)>, /* LCD_R6 */
+ <STM32_PINMUX('E', 15, AF14)>, /* LCD_R7 */
+ <STM32_PINMUX('E', 5, AF14)>, /* LCD_G0 */
+ <STM32_PINMUX('E', 6, AF14)>, /* LCD_G1 */
+ <STM32_PINMUX('H', 13, AF14)>, /* LCD_G2 */
+ <STM32_PINMUX('H', 14, AF14)>, /* LCD_G3 */
+ <STM32_PINMUX('H', 15, AF14)>, /* LCD_G4 */
+ <STM32_PINMUX('I', 0, AF14)>, /* LCD_G5 */
+ <STM32_PINMUX('I', 1, AF14)>, /* LCD_G6 */
+ <STM32_PINMUX('I', 2, AF14)>, /* LCD_G7 */
+ <STM32_PINMUX('D', 9, AF14)>, /* LCD_B0 */
+ <STM32_PINMUX('G', 12, AF14)>, /* LCD_B1 */
+ <STM32_PINMUX('G', 10, AF14)>, /* LCD_B2 */
+ <STM32_PINMUX('D', 10, AF14)>, /* LCD_B3 */
+ <STM32_PINMUX('I', 4, AF14)>, /* LCD_B4 */
+ <STM32_PINMUX('A', 3, AF14)>, /* LCD_B5 */
+ <STM32_PINMUX('B', 8, AF14)>, /* LCD_B6 */
+ <STM32_PINMUX('D', 8, AF14)>; /* LCD_B7 */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <1>;
+ };
+ };
+
+ ltdc_pins_sleep_a: ltdc-a-1 {
+ pins {
+ pinmux = <STM32_PINMUX('G', 7, ANALOG)>, /* LCD_CLK */
+ <STM32_PINMUX('I', 10, ANALOG)>, /* LCD_HSYNC */
+ <STM32_PINMUX('I', 9, ANALOG)>, /* LCD_VSYNC */
+ <STM32_PINMUX('F', 10, ANALOG)>, /* LCD_DE */
+ <STM32_PINMUX('H', 2, ANALOG)>, /* LCD_R0 */
+ <STM32_PINMUX('H', 3, ANALOG)>, /* LCD_R1 */
+ <STM32_PINMUX('H', 8, ANALOG)>, /* LCD_R2 */
+ <STM32_PINMUX('H', 9, ANALOG)>, /* LCD_R3 */
+ <STM32_PINMUX('H', 10, ANALOG)>, /* LCD_R4 */
+ <STM32_PINMUX('C', 0, ANALOG)>, /* LCD_R5 */
+ <STM32_PINMUX('H', 12, ANALOG)>, /* LCD_R6 */
+ <STM32_PINMUX('E', 15, ANALOG)>, /* LCD_R7 */
+ <STM32_PINMUX('E', 5, ANALOG)>, /* LCD_G0 */
+ <STM32_PINMUX('E', 6, ANALOG)>, /* LCD_G1 */
+ <STM32_PINMUX('H', 13, ANALOG)>, /* LCD_G2 */
+ <STM32_PINMUX('H', 14, ANALOG)>, /* LCD_G3 */
+ <STM32_PINMUX('H', 15, ANALOG)>, /* LCD_G4 */
+ <STM32_PINMUX('I', 0, ANALOG)>, /* LCD_G5 */
+ <STM32_PINMUX('I', 1, ANALOG)>, /* LCD_G6 */
+ <STM32_PINMUX('I', 2, ANALOG)>, /* LCD_G7 */
+ <STM32_PINMUX('D', 9, ANALOG)>, /* LCD_B0 */
+ <STM32_PINMUX('G', 12, ANALOG)>, /* LCD_B1 */
+ <STM32_PINMUX('G', 10, ANALOG)>, /* LCD_B2 */
+ <STM32_PINMUX('D', 10, ANALOG)>, /* LCD_B3 */
+ <STM32_PINMUX('I', 4, ANALOG)>, /* LCD_B4 */
+ <STM32_PINMUX('A', 3, ANALOG)>, /* LCD_B5 */
+ <STM32_PINMUX('B', 8, ANALOG)>, /* LCD_B6 */
+ <STM32_PINMUX('D', 8, ANALOG)>; /* LCD_B7 */
+ };
+ };
+
+ ltdc_pins_b: ltdc-b-0 {
+ pins {
+ pinmux = <STM32_PINMUX('I', 14, AF14)>, /* LCD_CLK */
+ <STM32_PINMUX('I', 12, AF14)>, /* LCD_HSYNC */
+ <STM32_PINMUX('I', 13, AF14)>, /* LCD_VSYNC */
+ <STM32_PINMUX('K', 7, AF14)>, /* LCD_DE */
+ <STM32_PINMUX('I', 15, AF14)>, /* LCD_R0 */
+ <STM32_PINMUX('J', 0, AF14)>, /* LCD_R1 */
+ <STM32_PINMUX('J', 1, AF14)>, /* LCD_R2 */
+ <STM32_PINMUX('J', 2, AF14)>, /* LCD_R3 */
+ <STM32_PINMUX('J', 3, AF14)>, /* LCD_R4 */
+ <STM32_PINMUX('J', 4, AF14)>, /* LCD_R5 */
+ <STM32_PINMUX('J', 5, AF14)>, /* LCD_R6 */
+ <STM32_PINMUX('J', 6, AF14)>, /* LCD_R7 */
+ <STM32_PINMUX('J', 7, AF14)>, /* LCD_G0 */
+ <STM32_PINMUX('J', 8, AF14)>, /* LCD_G1 */
+ <STM32_PINMUX('J', 9, AF14)>, /* LCD_G2 */
+ <STM32_PINMUX('J', 10, AF14)>, /* LCD_G3 */
+ <STM32_PINMUX('J', 11, AF14)>, /* LCD_G4 */
+ <STM32_PINMUX('K', 0, AF14)>, /* LCD_G5 */
+ <STM32_PINMUX('K', 1, AF14)>, /* LCD_G6 */
+ <STM32_PINMUX('K', 2, AF14)>, /* LCD_G7 */
+ <STM32_PINMUX('J', 12, AF14)>, /* LCD_B0 */
+ <STM32_PINMUX('J', 13, AF14)>, /* LCD_B1 */
+ <STM32_PINMUX('J', 14, AF14)>, /* LCD_B2 */
+ <STM32_PINMUX('J', 15, AF14)>, /* LCD_B3 */
+ <STM32_PINMUX('K', 3, AF14)>, /* LCD_B4 */
+ <STM32_PINMUX('K', 4, AF14)>, /* LCD_B5 */
+ <STM32_PINMUX('K', 5, AF14)>, /* LCD_B6 */
+ <STM32_PINMUX('K', 6, AF14)>; /* LCD_B7 */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <1>;
+ };
+ };
+
+ ltdc_pins_sleep_b: ltdc-b-1 {
+ pins {
+ pinmux = <STM32_PINMUX('I', 14, ANALOG)>, /* LCD_CLK */
+ <STM32_PINMUX('I', 12, ANALOG)>, /* LCD_HSYNC */
+ <STM32_PINMUX('I', 13, ANALOG)>, /* LCD_VSYNC */
+ <STM32_PINMUX('K', 7, ANALOG)>, /* LCD_DE */
+ <STM32_PINMUX('I', 15, ANALOG)>, /* LCD_R0 */
+ <STM32_PINMUX('J', 0, ANALOG)>, /* LCD_R1 */
+ <STM32_PINMUX('J', 1, ANALOG)>, /* LCD_R2 */
+ <STM32_PINMUX('J', 2, ANALOG)>, /* LCD_R3 */
+ <STM32_PINMUX('J', 3, ANALOG)>, /* LCD_R4 */
+ <STM32_PINMUX('J', 4, ANALOG)>, /* LCD_R5 */
+ <STM32_PINMUX('J', 5, ANALOG)>, /* LCD_R6 */
+ <STM32_PINMUX('J', 6, ANALOG)>, /* LCD_R7 */
+ <STM32_PINMUX('J', 7, ANALOG)>, /* LCD_G0 */
+ <STM32_PINMUX('J', 8, ANALOG)>, /* LCD_G1 */
+ <STM32_PINMUX('J', 9, ANALOG)>, /* LCD_G2 */
+ <STM32_PINMUX('J', 10, ANALOG)>, /* LCD_G3 */
+ <STM32_PINMUX('J', 11, ANALOG)>, /* LCD_G4 */
+ <STM32_PINMUX('K', 0, ANALOG)>, /* LCD_G5 */
+ <STM32_PINMUX('K', 1, ANALOG)>, /* LCD_G6 */
+ <STM32_PINMUX('K', 2, ANALOG)>, /* LCD_G7 */
+ <STM32_PINMUX('J', 12, ANALOG)>, /* LCD_B0 */
+ <STM32_PINMUX('J', 13, ANALOG)>, /* LCD_B1 */
+ <STM32_PINMUX('J', 14, ANALOG)>, /* LCD_B2 */
+ <STM32_PINMUX('J', 15, ANALOG)>, /* LCD_B3 */
+ <STM32_PINMUX('K', 3, ANALOG)>, /* LCD_B4 */
+ <STM32_PINMUX('K', 4, ANALOG)>, /* LCD_B5 */
+ <STM32_PINMUX('K', 5, ANALOG)>, /* LCD_B6 */
+ <STM32_PINMUX('K', 6, ANALOG)>; /* LCD_B7 */
+ };
+ };
+
m_can1_pins_a: m-can1-0 {
pins1 {
pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
@@ -322,6 +504,13 @@
};
};
+ m_can1_sleep_pins_a: m_can1-sleep@0 {
+ pins {
+ pinmux = <STM32_PINMUX('H', 13, ANALOG)>, /* CAN1_TX */
+ <STM32_PINMUX('I', 9, ANALOG)>; /* CAN1_RX */
+ };
+ };
+
pwm2_pins_a: pwm2-0 {
pins {
pinmux = <STM32_PINMUX('A', 3, AF1)>; /* TIM2_CH4 */
@@ -393,7 +582,8 @@
slew-rate = <3>;
};
};
- sdmmc1_b4_pins_a: sdmmc1-b4@0 {
+
+ sdmmc1_b4_pins_a: sdmmc1-b4-0 {
pins {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
<STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
@@ -407,18 +597,61 @@
};
};
- sdmmc1_dir_pins_a: sdmmc1-dir@0 {
+ sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
+ <STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
+ <STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
+ <STM32_PINMUX('C', 11, AF12)>, /* SDMMC1_D3 */
+ <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
+ slew-rate = <3>;
+ drive-push-pull;
+ bias-disable;
+ };
+ pins2{
+ pinmux = <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
+ slew-rate = <3>;
+ drive-open-drain;
+ bias-disable;
+ };
+ };
+
+ sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 {
pins {
+ pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1_D0 */
+ <STM32_PINMUX('C', 9, ANALOG)>, /* SDMMC1_D1 */
+ <STM32_PINMUX('C', 10, ANALOG)>, /* SDMMC1_D2 */
+ <STM32_PINMUX('C', 11, ANALOG)>, /* SDMMC1_D3 */
+ <STM32_PINMUX('C', 12, ANALOG)>, /* SDMMC1_CK */
+ <STM32_PINMUX('D', 2, ANALOG)>; /* SDMMC1_CMD */
+ };
+ };
+
+ sdmmc1_dir_pins_a: sdmmc1-dir-0 {
+ pins1 {
pinmux = <STM32_PINMUX('F', 2, AF11)>, /* SDMMC1_D0DIR */
<STM32_PINMUX('C', 7, AF8)>, /* SDMMC1_D123DIR */
- <STM32_PINMUX('B', 9, AF11)>, /* SDMMC1_CDIR */
- <STM32_PINMUX('E', 4, AF8)>; /* SDMMC1_CKIN */
+ <STM32_PINMUX('B', 9, AF11)>; /* SDMMC1_CDIR */
slew-rate = <3>;
drive-push-pull;
bias-pull-up;
};
+ pins2{
+ pinmux = <STM32_PINMUX('E', 4, AF8)>; /* SDMMC1_CKIN */
+ bias-pull-up;
+ };
};
- sdmmc2_b4_pins_a: sdmmc2-b4@0 {
+
+ sdmmc1_dir_sleep_pins_a: sdmmc1-dir-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('F', 2, ANALOG)>, /* SDMMC1_D0DIR */
+ <STM32_PINMUX('C', 7, ANALOG)>, /* SDMMC1_D123DIR */
+ <STM32_PINMUX('B', 9, ANALOG)>, /* SDMMC1_CDIR */
+ <STM32_PINMUX('E', 4, ANALOG)>; /* SDMMC1_CKIN */
+ };
+ };
+
+ sdmmc2_b4_pins_a: sdmmc2-b4-0 {
pins {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
@@ -432,7 +665,7 @@
};
};
- sdmmc2_d47_pins_a: sdmmc2-d47@0 {
+ sdmmc2_d47_pins_a: sdmmc2-d47-0 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
<STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
@@ -444,6 +677,19 @@
};
};
+ spdifrx_pins_a: spdifrx-0 {
+ pins {
+ pinmux = <STM32_PINMUX('G', 12, AF8)>; /* SPDIF_IN1 */
+ bias-disable;
+ };
+ };
+
+ spdifrx_sleep_pins_a: spdifrx-1 {
+ pins {
+ pinmux = <STM32_PINMUX('G', 12, ANALOG)>; /* SPDIF_IN1 */
+ };
+ };
+
spi2_pins_a: spi2-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, AF5)>, /* SPI2_SCK */
@@ -522,6 +768,7 @@
pins-are-numbered;
interrupt-parent = <&exti>;
st,syscfg = <&exti 0x60 0xff>;
+ hwlocks = <&hwspinlock 0>;
gpioz: gpio@54004000 {
gpio-controller;
@@ -546,6 +793,13 @@
};
};
+ i2c4_pins_sleep_a: i2c4-1 {
+ pins {
+ pinmux = <STM32_PINMUX('Z', 4, ANALOG)>, /* I2C4_SCL */
+ <STM32_PINMUX('Z', 5, ANALOG)>; /* I2C4_SDA */
+ };
+ };
+
spi1_pins_a: spi1-0 {
pins1 {
pinmux = <STM32_PINMUX('Z', 0, AF5)>, /* SPI1_SCK */
diff --git a/arch/arm/dts/stm32mp157-u-boot.dtsi b/arch/arm/dts/stm32mp157-u-boot.dtsi
index 09560e2d91..8102ce20d0 100644
--- a/arch/arm/dts/stm32mp157-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157-u-boot.dtsi
@@ -21,126 +21,119 @@
pinctrl1 = &pinctrl_z;
};
- config {
+ clocks {
u-boot,dm-pre-reloc;
};
- clocks {
+ reboot {
u-boot,dm-pre-reloc;
};
soc {
u-boot,dm-pre-reloc;
-
- stgen: stgen@5C008000 {
- compatible = "st,stm32-stgen";
- reg = <0x5C008000 0x1000>;
- status = "okay";
- u-boot,dm-pre-reloc;
- };
};
};
&bsec {
- u-boot,dm-pre-reloc;
-};
-
-&clk_hsi {
- u-boot,dm-pre-reloc;
-};
-
-&clk_hse {
- u-boot,dm-pre-reloc;
-};
-
-&clk_lse {
- u-boot,dm-pre-reloc;
-};
-
-&clk_lsi {
- u-boot,dm-pre-reloc;
+ u-boot,dm-pre-proper;
};
&clk_csi {
u-boot,dm-pre-reloc;
};
-&rcc {
+&clk_hsi {
u-boot,dm-pre-reloc;
};
-&rcc_reboot {
+&clk_hse {
u-boot,dm-pre-reloc;
};
-&pinctrl {
+&clk_lsi {
u-boot,dm-pre-reloc;
};
-&pinctrl_z {
+&clk_lse {
u-boot,dm-pre-reloc;
};
&gpioa {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiob {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioc {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiod {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioe {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiof {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiog {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioh {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioi {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioj {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpiok {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
&gpioz {
- compatible = "st,stm32-gpio";
u-boot,dm-pre-reloc;
};
-&iwdg2 {
+&pinctrl {
+ u-boot,dm-pre-reloc;
+};
+
+&pinctrl_z {
+ u-boot,dm-pre-reloc;
+};
+
+&pwr {
u-boot,dm-pre-reloc;
};
+
+&rcc {
+ u-boot,dm-pre-reloc;
+};
+
+&sdmmc1 {
+ compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
+};
+
+&sdmmc2 {
+ compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
+};
+
+&sdmmc3 {
+ compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
+};
+
+&usbotg_hs {
+ compatible = "st,stm32mp1-hsotg", "snps,dwc2";
+};
diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
index 0f32a38dc9..36c852d28b 100644
--- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
@@ -194,7 +194,3 @@
u-boot,force-b-session-valid;
hnp-srp-disable;
};
-
-&v3v3 {
- regulator-always-on;
-};
diff --git a/arch/arm/dts/stm32mp157a-dk1.dts b/arch/arm/dts/stm32mp157a-dk1.dts
index e36773dde9..adb2464920 100644
--- a/arch/arm/dts/stm32mp157a-dk1.dts
+++ b/arch/arm/dts/stm32mp157a-dk1.dts
@@ -39,12 +39,19 @@
};
};
+&cec {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&cec_pins_b>;
+ pinctrl-1 = <&cec_pins_sleep_b>;
+ status = "okay";
+};
+
&ethernet0 {
status = "okay";
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>;
@@ -58,12 +65,14 @@
};
};
+
&i2c4 {
pinctrl-names = "default";
pinctrl-0 = <&i2c4_pins_a>;
i2c-scl-rising-time-ns = <185>;
i2c-scl-falling-time-ns = <20>;
status = "okay";
+ /* spare dmas for other usage */
/delete-property/dmas;
/delete-property/dma-names;
@@ -88,17 +97,13 @@
pmic: stpmic@33 {
compatible = "st,stpmic1";
reg = <0x33>;
+ interrupts-extended = <&gpioa 0 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 = <0x20>;
-
regulators {
compatible = "st,stpmic1-regulators";
-
ldo1-supply = <&v3v3>;
ldo3-supply = <&vdd_ddr>;
ldo6-supply = <&v3v3>;
@@ -107,7 +112,7 @@
vddcore: buck1 {
regulator-name = "vddcore";
- regulator-min-microvolt = <1200000>;
+ regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-initial-mode = <0>;
@@ -187,7 +192,6 @@
regulator-max-microvolt = <1200000>;
regulator-always-on;
interrupts = <IT_CURLIM_LDO6 0>;
-
};
vref_ddr: vref_ddr {
@@ -204,7 +208,6 @@
vbus_otg: pwr_sw1 {
regulator-name = "vbus_otg";
interrupts = <IT_OCP_OTG 0>;
- regulator-active-discharge;
};
vbus_sw: pwr_sw2 {
@@ -216,8 +219,9 @@
onkey {
compatible = "st,stpmic1-onkey";
- interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 1>;
+ interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 0>;
interrupt-names = "onkey-falling", "onkey-rising";
+ power-off-time-sec = <10>;
status = "okay";
};
@@ -228,6 +232,10 @@
};
};
+&ipcc {
+ status = "okay";
+};
+
&iwdg2 {
timeout-sec = <32>;
status = "okay";
@@ -246,8 +254,10 @@
};
&sdmmc1 {
- pinctrl-names = "default";
+ pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc1_b4_pins_a>;
+ pinctrl-1 = <&sdmmc1_b4_od_pins_a>;
+ pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
broken-cd;
st,neg-edge;
bus-width = <4>;
diff --git a/arch/arm/dts/stm32mp157c-dk2.dts b/arch/arm/dts/stm32mp157c-dk2.dts
index 9a81d2d472..020ea0f0e2 100644
--- a/arch/arm/dts/stm32mp157c-dk2.dts
+++ b/arch/arm/dts/stm32mp157c-dk2.dts
@@ -42,6 +42,7 @@
compatible = "orisetech,otm8009a";
reg = <0>;
reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>;
+ power-supply = <&v3v3>;
status = "okay";
port {
diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi
index 55f99037b2..200601edff 100644
--- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi
@@ -156,6 +156,10 @@
};
};
+&sdmmc1 {
+ u-boot,dm-spl;
+};
+
&sdmmc1_b4_pins_a {
u-boot,dm-spl;
pins {
@@ -165,12 +169,15 @@
&sdmmc1_dir_pins_a {
u-boot,dm-spl;
- pins {
+ pins1 {
+ u-boot,dm-spl;
+ };
+ pins2 {
u-boot,dm-spl;
};
};
-&sdmmc1 {
+&sdmmc2 {
u-boot,dm-spl;
};
@@ -188,10 +195,6 @@
};
};
-&sdmmc2 {
- u-boot,dm-spl;
-};
-
&uart4 {
u-boot,dm-pre-reloc;
};
diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts
index b10208f698..11981d6dd4 100644
--- a/arch/arm/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/dts/stm32mp157c-ed1.dts
@@ -19,6 +19,7 @@
};
memory@c0000000 {
+ device_type = "memory";
reg = <0xC0000000 0x40000000>;
};
@@ -40,7 +41,7 @@
};
};
-&hwspinlock {
+&dts {
status = "okay";
};
@@ -50,23 +51,20 @@
i2c-scl-rising-time-ns = <185>;
i2c-scl-falling-time-ns = <20>;
status = "okay";
+ /* spare dmas for other usage */
+ /delete-property/dmas;
+ /delete-property/dma-names;
- pmic: stpmic1@33 {
+ pmic: stpmic@33 {
compatible = "st,stpmic1";
reg = <0x33>;
- interrupts = <0 2>;
- interrupt-parent = <&gpioa>;
+ interrupts-extended = <&gpioa 0 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>;
@@ -80,20 +78,8 @@
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
- regulator-initial-mode = <2>;
+ regulator-initial-mode = <0>;
regulator-over-current-protection;
-
- regulator-state-standby {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1200000>;
- regulator-mode = <8>;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
};
vdd_ddr: buck2 {
@@ -101,22 +87,8 @@
regulator-min-microvolt = <1350000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
- regulator-initial-mode = <2>;
+ regulator-initial-mode = <0>;
regulator-over-current-protection;
-
- regulator-state-standby {
- regulator-suspend-microvolt = <1350000>;
- regulator-on-in-suspend;
- regulator-mode = <8>;
- };
- regulator-state-mem {
- regulator-suspend-microvolt = <1350000>;
- regulator-on-in-suspend;
- regulator-mode = <8>;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
};
vdd: buck3 {
@@ -124,46 +96,18 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
- st,mask_reset;
- regulator-initial-mode = <8>;
+ st,mask-reset;
+ regulator-initial-mode = <0>;
regulator-over-current-protection;
-
- regulator-state-standby {
- regulator-suspend-microvolt = <3300000>;
- regulator-on-in-suspend;
- regulator-mode = <8>;
- };
- regulator-state-mem {
- regulator-suspend-microvolt = <3300000>;
- regulator-on-in-suspend;
- regulator-mode = <8>;
- };
- regulator-state-disk {
- regulator-suspend-microvolt = <3300000>;
- regulator-on-in-suspend;
- regulator-mode = <8>;
- };
};
v3v3: buck4 {
regulator-name = "v3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
- regulator-boot-on;
+ regulator-always-on;
regulator-over-current-protection;
- regulator-initial-mode = <8>;
-
- regulator-state-standby {
- regulator-suspend-microvolt = <3300000>;
- regulator-unchanged-in-suspend;
- regulator-mode = <8>;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
+ regulator-initial-mode = <0>;
};
vdda: ldo1 {
@@ -171,18 +115,6 @@
regulator-min-microvolt = <2900000>;
regulator-max-microvolt = <2900000>;
interrupts = <IT_CURLIM_LDO1 0>;
- interrupt-parent = <&pmic>;
-
- regulator-state-standby {
- regulator-suspend-microvolt = <2900000>;
- regulator-unchanged-in-suspend;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
};
v2v8: ldo2 {
@@ -190,36 +122,14 @@
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
interrupts = <IT_CURLIM_LDO2 0>;
- interrupt-parent = <&pmic>;
-
- regulator-state-standby {
- regulator-suspend-microvolt = <2800000>;
- regulator-unchanged-in-suspend;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
};
vtt_ddr: ldo3 {
regulator-name = "vtt_ddr";
- regulator-min-microvolt = <0000000>;
- regulator-max-microvolt = <1000000>;
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <750000>;
regulator-always-on;
regulator-over-current-protection;
-
- regulator-state-standby {
- regulator-off-in-suspend;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
};
vdd_usb: ldo4 {
@@ -227,17 +137,6 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
interrupts = <IT_CURLIM_LDO4 0>;
- interrupt-parent = <&pmic>;
-
- regulator-state-standby {
- regulator-unchanged-in-suspend;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
};
vdd_sd: ldo5 {
@@ -245,19 +144,7 @@
regulator-min-microvolt = <2900000>;
regulator-max-microvolt = <2900000>;
interrupts = <IT_CURLIM_LDO5 0>;
- interrupt-parent = <&pmic>;
regulator-boot-on;
-
- regulator-state-standby {
- regulator-suspend-microvolt = <2900000>;
- regulator-unchanged-in-suspend;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
};
v1v8: ldo6 {
@@ -265,66 +152,53 @@
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
interrupts = <IT_CURLIM_LDO6 0>;
- interrupt-parent = <&pmic>;
-
- regulator-state-standby {
- regulator-suspend-microvolt = <1800000>;
- regulator-unchanged-in-suspend;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
};
vref_ddr: vref_ddr {
regulator-name = "vref_ddr";
regulator-always-on;
regulator-over-current-protection;
-
- regulator-state-standby {
- regulator-on-in-suspend;
- };
- regulator-state-mem {
- regulator-on-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
};
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 0>;
+ interrupt-names = "onkey-falling", "onkey-rising";
+ power-off-time-sec = <10>;
+ status = "okay";
+ };
+
+ watchdog {
+ compatible = "st,stpmic1-wdt";
+ status = "disabled";
+ };
};
};
-&iwdg2 {
- timeout-sec = <32>;
+&ipcc {
status = "okay";
};
-&pinctrl {
- hwlocks = <&hwspinlock 0>;
+&iwdg2 {
+ timeout-sec = <32>;
+ status = "okay";
};
&pwr {
@@ -340,7 +214,10 @@
};
&sdmmc1 {
+ pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
+ pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>;
+ pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>;
broken-cd;
st,sig-dir;
st,neg-edge;
@@ -348,11 +225,6 @@
bus-width = <4>;
vmmc-supply = <&vdd_sd>;
vqmmc-supply = <&sd_switch>;
- sd-uhs-sdr12;
- sd-uhs-sdr25;
- sd-uhs-sdr50;
- sd-uhs-ddr50;
- sd-uhs-sdr104;
status = "okay";
};
@@ -371,6 +243,9 @@
&timers6 {
status = "okay";
+ /* spare dmas for other usage */
+ /delete-property/dmas;
+ /delete-property/dma-names;
timer@5 {
status = "okay";
};
@@ -382,6 +257,10 @@
status = "okay";
};
+&usbotg_hs {
+ vbus-supply = <&vbus_otg>;
+};
+
&usbphyc_port0 {
phy-supply = <&vdd_usb>;
};
diff --git a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi
index 994092a195..b656eb120d 100644
--- a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi
@@ -56,6 +56,3 @@
};
};
-&v3v3 {
- regulator-always-on;
-};
diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts
index 663e52aa31..ca2a333d43 100644
--- a/arch/arm/dts/stm32mp157c-ev1.dts
+++ b/arch/arm/dts/stm32mp157c-ev1.dts
@@ -6,6 +6,7 @@
/dts-v1/;
#include "stm32mp157c-ed1.dts"
+#include <dt-bindings/gpio/gpio.h>
/ {
model = "STMicroelectronics STM32MP157C eval daughter on eval mother";
@@ -157,8 +158,9 @@
};
&m_can1 {
- pinctrl-names = "default";
+ pinctrl-names = "default", "sleep";
pinctrl-0 = <&m_can1_pins_a>;
+ pinctrl-1 = <&m_can1_sleep_pins_a>;
status = "okay";
};
@@ -194,6 +196,9 @@
};
&timers2 {
+ /* spare dmas for other usage (un-delete to enable pwm capture) */
+ /delete-property/dmas;
+ /delete-property/dma-names;
status = "disabled";
pwm {
pinctrl-0 = <&pwm2_pins_a>;
@@ -206,6 +211,8 @@
};
&timers8 {
+ /delete-property/dmas;
+ /delete-property/dma-names;
status = "disabled";
pwm {
pinctrl-0 = <&pwm8_pins_a>;
@@ -218,6 +225,8 @@
};
&timers12 {
+ /delete-property/dmas;
+ /delete-property/dma-names;
status = "disabled";
pwm {
pinctrl-0 = <&pwm12_pins_a>;
@@ -232,7 +241,6 @@
&usbh_ehci {
phys = <&usbphyc_port0>;
phy-names = "usb";
- vbus-supply = <&vbus_sw>;
status = "okay";
};
diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi
index 73215855cc..d15fba0c80 100644
--- a/arch/arm/dts/stm32mp157c.dtsi
+++ b/arch/arm/dts/stm32mp157c.dtsi
@@ -35,28 +35,6 @@
cpu_on = <0x84000003>;
};
- aliases {
- gpio0 = &gpioa;
- gpio1 = &gpiob;
- gpio2 = &gpioc;
- gpio3 = &gpiod;
- gpio4 = &gpioe;
- gpio5 = &gpiof;
- gpio6 = &gpiog;
- gpio7 = &gpioh;
- gpio8 = &gpioi;
- gpio9 = &gpioj;
- gpio10 = &gpiok;
- serial0 = &usart1;
- serial1 = &usart2;
- serial2 = &usart3;
- serial3 = &uart4;
- serial4 = &uart5;
- serial5 = &usart6;
- serial6 = &uart7;
- serial7 = &uart8;
- };
-
intc: interrupt-controller@a0021000 {
compatible = "arm,cortex-a7-gic";
#interrupt-cells = <3>;
@@ -106,6 +84,38 @@
};
};
+ thermal-zones {
+ cpu_thermal: cpu-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&dts>;
+
+ trips {
+ cpu_alert1: cpu-alert1 {
+ temperature = <85000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ cpu-crit {
+ temperature = <120000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ };
+ };
+ };
+
+ reboot {
+ compatible = "syscon-reboot";
+ regmap = <&rcc>;
+ offset = <0x404>;
+ mask = <0x1>;
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <1>;
@@ -120,6 +130,12 @@
reg = <0x40000000 0x400>;
clocks = <&rcc TIM2_K>;
clock-names = "int";
+ dmas = <&dmamux1 18 0x400 0x1>,
+ <&dmamux1 19 0x400 0x1>,
+ <&dmamux1 20 0x400 0x1>,
+ <&dmamux1 21 0x400 0x1>,
+ <&dmamux1 22 0x400 0x1>;
+ dma-names = "ch1", "ch2", "ch3", "ch4", "up";
status = "disabled";
pwm {
@@ -141,6 +157,13 @@
reg = <0x40001000 0x400>;
clocks = <&rcc TIM3_K>;
clock-names = "int";
+ dmas = <&dmamux1 23 0x400 0x1>,
+ <&dmamux1 24 0x400 0x1>,
+ <&dmamux1 25 0x400 0x1>,
+ <&dmamux1 26 0x400 0x1>,
+ <&dmamux1 27 0x400 0x1>,
+ <&dmamux1 28 0x400 0x1>;
+ dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig";
status = "disabled";
pwm {
@@ -162,6 +185,11 @@
reg = <0x40002000 0x400>;
clocks = <&rcc TIM4_K>;
clock-names = "int";
+ dmas = <&dmamux1 29 0x400 0x1>,
+ <&dmamux1 30 0x400 0x1>,
+ <&dmamux1 31 0x400 0x1>,
+ <&dmamux1 32 0x400 0x1>;
+ dma-names = "ch1", "ch2", "ch3", "ch4";
status = "disabled";
pwm {
@@ -183,6 +211,13 @@
reg = <0x40003000 0x400>;
clocks = <&rcc TIM5_K>;
clock-names = "int";
+ dmas = <&dmamux1 55 0x400 0x1>,
+ <&dmamux1 56 0x400 0x1>,
+ <&dmamux1 57 0x400 0x1>,
+ <&dmamux1 58 0x400 0x1>,
+ <&dmamux1 59 0x400 0x1>,
+ <&dmamux1 60 0x400 0x1>;
+ dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig";
status = "disabled";
pwm {
@@ -204,6 +239,8 @@
reg = <0x40004000 0x400>;
clocks = <&rcc TIM6_K>;
clock-names = "int";
+ dmas = <&dmamux1 69 0x400 0x1>;
+ dma-names = "up";
status = "disabled";
timer@5 {
@@ -220,6 +257,8 @@
reg = <0x40005000 0x400>;
clocks = <&rcc TIM7_K>;
clock-names = "int";
+ dmas = <&dmamux1 70 0x400 0x1>;
+ dma-names = "up";
status = "disabled";
timer@6 {
@@ -347,6 +386,19 @@
status = "disabled";
};
+ spdifrx: audio-controller@4000d000 {
+ compatible = "st,stm32h7-spdifrx";
+ #sound-dai-cells = <0>;
+ reg = <0x4000d000 0x400>;
+ clocks = <&rcc SPDIF_K>;
+ clock-names = "kclk";
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&dmamux1 93 0x400 0x01>,
+ <&dmamux1 94 0x400 0x01>;
+ dma-names = "rx", "rx-ctrl";
+ status = "disabled";
+ };
+
usart2: serial@4000e000 {
compatible = "st,stm32h7-uart";
reg = <0x4000e000 0x400>;
@@ -487,6 +539,15 @@
reg = <0x44000000 0x400>;
clocks = <&rcc TIM1_K>;
clock-names = "int";
+ dmas = <&dmamux1 11 0x400 0x1>,
+ <&dmamux1 12 0x400 0x1>,
+ <&dmamux1 13 0x400 0x1>,
+ <&dmamux1 14 0x400 0x1>,
+ <&dmamux1 15 0x400 0x1>,
+ <&dmamux1 16 0x400 0x1>,
+ <&dmamux1 17 0x400 0x1>;
+ dma-names = "ch1", "ch2", "ch3", "ch4",
+ "up", "trig", "com";
status = "disabled";
pwm {
@@ -508,6 +569,15 @@
reg = <0x44001000 0x400>;
clocks = <&rcc TIM8_K>;
clock-names = "int";
+ dmas = <&dmamux1 47 0x400 0x1>,
+ <&dmamux1 48 0x400 0x1>,
+ <&dmamux1 49 0x400 0x1>,
+ <&dmamux1 50 0x400 0x1>,
+ <&dmamux1 51 0x400 0x1>,
+ <&dmamux1 52 0x400 0x1>,
+ <&dmamux1 53 0x400 0x1>;
+ dma-names = "ch1", "ch2", "ch3", "ch4",
+ "up", "trig", "com";
status = "disabled";
pwm {
@@ -565,6 +635,11 @@
reg = <0x44006000 0x400>;
clocks = <&rcc TIM15_K>;
clock-names = "int";
+ dmas = <&dmamux1 105 0x400 0x1>,
+ <&dmamux1 106 0x400 0x1>,
+ <&dmamux1 107 0x400 0x1>,
+ <&dmamux1 108 0x400 0x1>;
+ dma-names = "ch1", "up", "trig", "com";
status = "disabled";
pwm {
@@ -586,6 +661,9 @@
reg = <0x44007000 0x400>;
clocks = <&rcc TIM16_K>;
clock-names = "int";
+ dmas = <&dmamux1 109 0x400 0x1>,
+ <&dmamux1 110 0x400 0x1>;
+ dma-names = "ch1", "up";
status = "disabled";
pwm {
@@ -606,6 +684,9 @@
reg = <0x44008000 0x400>;
clocks = <&rcc TIM17_K>;
clock-names = "int";
+ dmas = <&dmamux1 111 0x400 0x1>,
+ <&dmamux1 112 0x400 0x1>;
+ dma-names = "ch1", "up";
status = "disabled";
pwm {
@@ -706,14 +787,14 @@
m_can1: can@4400e000 {
compatible = "bosch,m_can";
- reg = <0x4400e000 0x400>, <0x44011000 0x2800>;
+ reg = <0x4400e000 0x400>, <0x44011000 0x1400>;
reg-names = "m_can", "message_ram";
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
clock-names = "hclk", "cclk";
- bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>;
+ bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>;
status = "disabled";
};
@@ -811,13 +892,14 @@
};
sdmmc3: sdmmc@48004000 {
- compatible = "st,stm32-sdmmc2";
- reg = <0x48004000 0x400>, <0x48005000 0x400>;
- reg-names = "sdmmc", "delay";
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x10153180>;
+ reg = <0x48004000 0x400>;
+ reg-names = "sdmmc";
interrupts = <GIC_SPI 137 IRQ_TYPE_NONE>;
clocks = <&rcc SDMMC3_K>;
+ clock-names = "apb_pclk";
resets = <&rcc SDMMC3_R>;
- st,idma = <1>;
cap-sd-highspeed;
cap-mmc-highspeed;
max-frequency = <120000000>;
@@ -825,7 +907,7 @@
};
usbotg_hs: usb-otg@49000000 {
- compatible = "st,stm32mp1-hsotg", "snps,dwc2";
+ compatible = "snps,dwc2";
reg = <0x49000000 0x10000>;
clocks = <&rcc USBO_K>;
clock-names = "otg";
@@ -846,6 +928,20 @@
reg = <0x4c000000 0x400>;
clocks = <&rcc HSEM>;
clock-names = "hwspinlock";
+ };
+
+ ipcc: mailbox@4c001000 {
+ compatible = "st,stm32mp1-ipcc";
+ #mbox-cells = <1>;
+ reg = <0x4c001000 0x400>;
+ st,proc-id = <0>;
+ interrupts-extended =
+ <&intc GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 61 1>;
+ interrupt-names = "rx", "tx", "wakeup";
+ clocks = <&rcc IPCC>;
+ wakeup-source;
status = "disabled";
};
@@ -856,13 +952,6 @@
#reset-cells = <1>;
};
- rcc_reboot: rcc-reboot@50000000 {
- compatible = "syscon-reboot";
- regmap = <&rcc>;
- offset = <0x404>;
- mask = <0x1>;
- };
-
pwr: pwr@50001000 {
compatible = "st,stm32mp1-pwr", "st,stm32-pwr", "syscon", "simple-mfd";
reg = <0x50001000 0x400>;
@@ -872,7 +961,7 @@
clocks = <&rcc PLL2_R>;
clock-names = "phyclk";
- pwr-regulators@c {
+ pwr-regulators {
compatible = "st,stm32mp1,pwr-reg";
st,tzcr = <&rcc 0x0 0x1>;
@@ -906,6 +995,7 @@
syscfg: syscon@50020000 {
compatible = "st,stm32mp157-syscfg", "syscon";
reg = <0x50020000 0x400>;
+ clocks = <&rcc SYSCFG>;
};
lptimer2: timer@50021000 {
@@ -994,6 +1084,16 @@
status = "disabled";
};
+ dts: thermal@50028000 {
+ compatible = "st,stm32-thermal";
+ reg = <0x50028000 0x100>;
+ interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc TMPSENS>;
+ clock-names = "pclk";
+ #thermal-sensor-cells = <0>;
+ status = "disabled";
+ };
+
cryp1: cryp@54001000 {
compatible = "st,stm32mp1-cryp";
reg = <0x54001000 0x400>;
@@ -1059,26 +1159,27 @@
};
sdmmc1: sdmmc@58005000 {
- compatible = "st,stm32-sdmmc2";
- reg = <0x58005000 0x1000>, <0x58006000 0x1000>;
- reg-names = "sdmmc", "delay";
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x10153180>;
+ reg = <0x58005000 0x1000>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "cmd_irq";
clocks = <&rcc SDMMC1_K>;
+ clock-names = "apb_pclk";
resets = <&rcc SDMMC1_R>;
- st,idma = <1>;
cap-sd-highspeed;
cap-mmc-highspeed;
max-frequency = <120000000>;
- status = "disabled";
};
sdmmc2: sdmmc@58007000 {
- compatible = "st,stm32-sdmmc2";
- reg = <0x58007000 0x1000>, <0x58008000 0x1000>;
- reg-names = "sdmmc", "delay";
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x10153180>;
+ reg = <0x58007000 0x1000>;
interrupts = <GIC_SPI 124 IRQ_TYPE_NONE>;
clocks = <&rcc SDMMC2_K>;
+ clock-names = "apb_pclk";
resets = <&rcc SDMMC2_R>;
- st,idma = <1>;
cap-sd-highspeed;
cap-mmc-highspeed;
max-frequency = <120000000>;
@@ -1102,25 +1203,21 @@
compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
reg = <0x5800a000 0x2000>;
reg-names = "stmmaceth";
- 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";
+ interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
clock-names = "stmmaceth",
"mac-clk-tx",
"mac-clk-rx",
- "ethstp";
+ "ethstp",
+ "syscfg-clk";
clocks = <&rcc ETHMAC>,
<&rcc ETHTX>,
<&rcc ETHRX>,
- <&rcc ETHSTP>;
+ <&rcc ETHSTP>,
+ <&rcc SYSCFG>;
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";
@@ -1245,6 +1342,12 @@
reg = <0x5c005000 0x400>;
#address-cells = <1>;
#size-cells = <1>;
+ ts_cal1: calib@5c {
+ reg = <0x5c 0x2>;
+ };
+ ts_cal2: calib@5e {
+ reg = <0x5e 0x2>;
+ };
};
i2c6: i2c@5c009000 {
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index d9ad6b423b..9dc3c4d1c5 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -38,6 +38,7 @@ config TARGET_STM32MP1
select CPU_V7A
select CPU_V7_HAS_NONSEC if !STM32MP1_TRUSTED
select CPU_V7_HAS_VIRT
+ select OF_BOARD_SETUP
select PINCTRL_STM32
select STM32_RCC
select STM32_RESET
@@ -62,7 +63,17 @@ config STM32MP1_TRUSTED
Say Y here to enable boot with TF-A
Trusted boot chain is :
BootRom => TF-A.stm32 (clock & DDR) => U-Boot.stm32
- TF-A monitor provides proprietary smc to manage secure devices
+ TF-A monitor provides proprietary SMC to manage secure devices
+
+config STM32MP1_OPTEE
+ bool "Support trusted boot with TF-A and OP-TEE"
+ depends on STM32MP1_TRUSTED
+ default n
+ help
+ Say Y here to enable boot with TF-A and OP-TEE
+ Trusted boot chain is :
+ BootRom => TF-A.stm32 (clock & DDR) => OP-TEE => U-Boot.stm32
+ OP-TEE monitor provides ST SMC to access to secure resources
config SYS_TEXT_BASE
prompt "U-Boot base address"
@@ -83,6 +94,21 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2
Partition on the second MMC to load U-Boot from when the MMC is being
used in raw mode
+config STM32_ETZPC
+ bool "STM32 Extended TrustZone Protection"
+ depends on TARGET_STM32MP1
+ default y
+ help
+ Say y to enable STM32 Extended TrustZone Protection
+
+config CMD_STM32KEY
+ bool "command stm32key to fuse public key hash"
+ default y
+ depends on CMD_FUSE
+ help
+ fuse public key hash in corresponding fuse used to authenticate
+ binary.
+
config BOOTSTAGE_STASH_ADDR
default 0xC3000000
diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile
index 1493914a11..77450604b0 100644
--- a/arch/arm/mach-stm32mp/Makefile
+++ b/arch/arm/mach-stm32mp/Makefile
@@ -11,9 +11,11 @@ ifdef CONFIG_SPL_BUILD
obj-y += spl.o
else
obj-y += bsec.o
+obj-$(CONFIG_CMD_STM32KEY) += cmd_stm32key.o
ifndef CONFIG_STM32MP1_TRUSTED
obj-$(CONFIG_SYSRESET) += cmd_poweroff.o
endif
endif
obj-$(CONFIG_ARMV7_PSCI) += psci.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR) += pwr_regulator.o
+obj-$(CONFIG_OF_SYSTEM_SETUP) += fdt.o
diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c
index 0166649685..8018366885 100644
--- a/arch/arm/mach-stm32mp/bsec.c
+++ b/arch/arm/mach-stm32mp/bsec.c
@@ -358,12 +358,13 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset,
bool shadow = true;
int nb_otp = size / sizeof(u32);
int otp;
+ unsigned int offs = offset;
- if (offset >= STM32_BSEC_OTP_OFFSET) {
- offset -= STM32_BSEC_OTP_OFFSET;
+ if (offs >= STM32_BSEC_OTP_OFFSET) {
+ offs -= STM32_BSEC_OTP_OFFSET;
shadow = false;
}
- otp = offset / sizeof(u32);
+ otp = offs / sizeof(u32);
if (otp < 0 || (otp + nb_otp - 1) > BSEC_OTP_MAX_VALUE) {
dev_err(dev, "wrong value for otp, max value : %i\n",
@@ -393,12 +394,13 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset,
bool shadow = true;
int nb_otp = size / sizeof(u32);
int otp;
+ unsigned int offs = offset;
- if (offset >= STM32_BSEC_OTP_OFFSET) {
- offset -= STM32_BSEC_OTP_OFFSET;
+ if (offs >= STM32_BSEC_OTP_OFFSET) {
+ offs -= STM32_BSEC_OTP_OFFSET;
shadow = false;
}
- otp = offset / sizeof(u32);
+ otp = offs / sizeof(u32);
if (otp < 0 || (otp + nb_otp - 1) > BSEC_OTP_MAX_VALUE) {
dev_err(dev, "wrong value for otp, max value : %d\n",
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c
new file mode 100644
index 0000000000..f1f26e7c94
--- /dev/null
+++ b/arch/arm/mach-stm32mp/cmd_stm32key.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <misc.h>
+#include <dm/device.h>
+#include <dm/uclass.h>
+
+#define STM32_OTP_HASH_KEY_START 24
+#define STM32_OTP_HASH_KEY_SIZE 8
+
+static void read_hash_value(u32 addr)
+{
+ int i;
+
+ for (i = 0; i < STM32_OTP_HASH_KEY_SIZE; i++) {
+ printf("OTP value %i: %x\n", STM32_OTP_HASH_KEY_START + i,
+ __be32_to_cpu(*(u32 *)addr));
+ addr += 4;
+ }
+}
+
+static void fuse_hash_value(u32 addr, bool print)
+{
+ struct udevice *dev;
+ u32 word, val;
+ int i, ret;
+
+ ret = uclass_get_device_by_driver(UCLASS_MISC,
+ DM_GET_DRIVER(stm32mp_bsec),
+ &dev);
+ if (ret) {
+ pr_err("Can't find stm32mp_bsec driver\n");
+ return;
+ }
+
+ for (i = 0; i < STM32_OTP_HASH_KEY_SIZE; i++) {
+ if (print)
+ printf("Fuse OTP %i : %x\n",
+ STM32_OTP_HASH_KEY_START + i,
+ __be32_to_cpu(*(u32 *)addr));
+
+ word = STM32_OTP_HASH_KEY_START + i;
+ val = __be32_to_cpu(*(u32 *)addr);
+ misc_write(dev, STM32_BSEC_OTP(word), &val, 4);
+
+ addr += 4;
+ }
+}
+
+static int confirm_prog(void)
+{
+ puts("Warning: Programming fuses is an irreversible operation!\n"
+ " This may brick your system.\n"
+ " Use this command only if you are sure of what you are doing!\n"
+ "\nReally perform this fuse programming? <y/N>\n");
+
+ if (confirm_yesno())
+ return 1;
+
+ puts("Fuse programming aborted\n");
+ return 0;
+}
+
+static int do_stm32key(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ u32 addr;
+ const char *op = argc >= 2 ? argv[1] : NULL;
+ int confirmed = argc > 3 && !strcmp(argv[2], "-y");
+
+ argc -= 2 + confirmed;
+ argv += 2 + confirmed;
+
+ if (argc < 1)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[0], NULL, 16);
+ if (!addr)
+ return CMD_RET_USAGE;
+
+ if (!strcmp(op, "read"))
+ read_hash_value(addr);
+
+ if (!strcmp(op, "fuse")) {
+ if (!confirmed && !confirm_prog())
+ return CMD_RET_FAILURE;
+ fuse_hash_value(addr, !confirmed);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(stm32key, 4, 1, do_stm32key,
+ "Fuse ST Hash key",
+ "read <addr>: Read the hash store at addr in memory\n"
+ "stm32key fuse [-y] <addr> : Fuse hash store at addr in otp\n");
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c
index e1a0a13680..10190f40d4 100644
--- a/arch/arm/mach-stm32mp/cpu.c
+++ b/arch/arm/mach-stm32mp/cpu.c
@@ -78,11 +78,6 @@
#define PKG_SHIFT 27
#define PKG_MASK GENMASK(2, 0)
-#define PKG_AA_LBGA448 4
-#define PKG_AB_LBGA354 3
-#define PKG_AC_TFBGA361 2
-#define PKG_AD_TFBGA257 1
-
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
#ifndef CONFIG_STM32MP1_TRUSTED
static void security_init(void)
@@ -277,7 +272,7 @@ u32 get_cpu_type(void)
}
/* Get Package options from OTP */
-static u32 get_cpu_package(void)
+u32 get_cpu_package(void)
{
return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK);
}
@@ -366,7 +361,7 @@ static void setup_boot_mode(void)
u32 boot_ctx = readl(TAMP_BOOT_CONTEXT);
u32 boot_mode =
(boot_ctx & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT;
- int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1;
+ unsigned int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1;
u32 forced_mode = (boot_ctx & TAMP_BOOT_FORCED_MASK);
struct udevice *dev;
int alias;
diff --git a/arch/arm/mach-stm32mp/fdt.c b/arch/arm/mach-stm32mp/fdt.c
new file mode 100644
index 0000000000..82c430b7c7
--- /dev/null
+++ b/arch/arm/mach-stm32mp/fdt.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <fdt_support.h>
+#include <asm/arch/sys_proto.h>
+#include <dt-bindings/pinctrl/stm32-pinfunc.h>
+#include <linux/io.h>
+
+#define ETZPC_DECPROT(n) (STM32_ETZPC_BASE + 0x10 + 4 * (n))
+#define ETZPC_DECPROT_NB 6
+
+#define DECPROT_MASK 0x03
+#define NB_PROT_PER_REG 0x10
+#define DECPROT_NB_BITS 2
+
+#define DECPROT_SECURED 0x00
+#define DECPROT_WRITE_SECURE 0x01
+#define DECPROT_MCU_ISOLATION 0x02
+#define DECPROT_NON_SECURED 0x03
+
+#define ETZPC_RESERVED 0xffffffff
+
+static const u32 stm32mp1_ip_addr[] = {
+ 0x5c008000, /* 00 stgenc */
+ 0x54000000, /* 01 bkpsram */
+ 0x5c003000, /* 02 iwdg1 */
+ 0x5c000000, /* 03 usart1 */
+ 0x5c001000, /* 04 spi6 */
+ 0x5c002000, /* 05 i2c4 */
+ ETZPC_RESERVED, /* 06 reserved */
+ 0x54003000, /* 07 rng1 */
+ 0x54002000, /* 08 hash1 */
+ 0x54001000, /* 09 cryp1 */
+ 0x5a003000, /* 0A ddrctrl */
+ 0x5a004000, /* 0B ddrphyc */
+ 0x5c009000, /* 0C i2c6 */
+ ETZPC_RESERVED, /* 0D reserved */
+ ETZPC_RESERVED, /* 0E reserved */
+ ETZPC_RESERVED, /* 0F reserved */
+ 0x40000000, /* 10 tim2 */
+ 0x40001000, /* 11 tim3 */
+ 0x40002000, /* 12 tim4 */
+ 0x40003000, /* 13 tim5 */
+ 0x40004000, /* 14 tim6 */
+ 0x40005000, /* 15 tim7 */
+ 0x40006000, /* 16 tim12 */
+ 0x40007000, /* 17 tim13 */
+ 0x40008000, /* 18 tim14 */
+ 0x40009000, /* 19 lptim1 */
+ 0x4000a000, /* 1A wwdg1 */
+ 0x4000b000, /* 1B spi2 */
+ 0x4000c000, /* 1C spi3 */
+ 0x4000d000, /* 1D spdifrx */
+ 0x4000e000, /* 1E usart2 */
+ 0x4000f000, /* 1F usart3 */
+ 0x40010000, /* 20 uart4 */
+ 0x40011000, /* 21 uart5 */
+ 0x40012000, /* 22 i2c1 */
+ 0x40013000, /* 23 i2c2 */
+ 0x40014000, /* 24 i2c3 */
+ 0x40015000, /* 25 i2c5 */
+ 0x40016000, /* 26 cec */
+ 0x40017000, /* 27 dac */
+ 0x40018000, /* 28 uart7 */
+ 0x40019000, /* 29 uart8 */
+ ETZPC_RESERVED, /* 2A reserved */
+ ETZPC_RESERVED, /* 2B reserved */
+ 0x4001c000, /* 2C mdios */
+ ETZPC_RESERVED, /* 2D reserved */
+ ETZPC_RESERVED, /* 2E reserved */
+ ETZPC_RESERVED, /* 2F reserved */
+ 0x44000000, /* 30 tim1 */
+ 0x44001000, /* 31 tim8 */
+ ETZPC_RESERVED, /* 32 reserved */
+ 0x44003000, /* 33 usart6 */
+ 0x44004000, /* 34 spi1 */
+ 0x44005000, /* 35 spi4 */
+ 0x44006000, /* 36 tim15 */
+ 0x44007000, /* 37 tim16 */
+ 0x44008000, /* 38 tim17 */
+ 0x44009000, /* 39 spi5 */
+ 0x4400a000, /* 3A sai1 */
+ 0x4400b000, /* 3B sai2 */
+ 0x4400c000, /* 3C sai3 */
+ 0x4400d000, /* 3D dfsdm */
+ 0x4400e000, /* 3E tt_fdcan */
+ ETZPC_RESERVED, /* 3F reserved */
+ 0x50021000, /* 40 lptim2 */
+ 0x50022000, /* 41 lptim3 */
+ 0x50023000, /* 42 lptim4 */
+ 0x50024000, /* 43 lptim5 */
+ 0x50027000, /* 44 sai4 */
+ 0x50025000, /* 45 vrefbuf */
+ 0x4c006000, /* 46 dcmi */
+ 0x4c004000, /* 47 crc2 */
+ 0x48003000, /* 48 adc */
+ 0x4c002000, /* 49 hash2 */
+ 0x4c003000, /* 4A rng2 */
+ 0x4c005000, /* 4B cryp2 */
+ ETZPC_RESERVED, /* 4C reserved */
+ ETZPC_RESERVED, /* 4D reserved */
+ ETZPC_RESERVED, /* 4E reserved */
+ ETZPC_RESERVED, /* 4F reserved */
+ ETZPC_RESERVED, /* 50 sram1 */
+ ETZPC_RESERVED, /* 51 sram2 */
+ ETZPC_RESERVED, /* 52 sram3 */
+ ETZPC_RESERVED, /* 53 sram4 */
+ ETZPC_RESERVED, /* 54 retram */
+ 0x49000000, /* 55 otg */
+ 0x48004000, /* 56 sdmmc3 */
+ 0x48005000, /* 57 dlybsd3 */
+ 0x48000000, /* 58 dma1 */
+ 0x48001000, /* 59 dma2 */
+ 0x48002000, /* 5A dmamux */
+ 0x58002000, /* 5B fmc */
+ 0x58003000, /* 5C qspi */
+ 0x58004000, /* 5D dlybq */
+ 0x5800a000, /* 5E eth */
+ ETZPC_RESERVED, /* 5F reserved */
+};
+
+/* fdt helper */
+static bool fdt_disable_subnode_by_address(void *fdt, int offset, u32 addr)
+{
+ int node;
+
+ for (node = fdt_first_subnode(fdt, offset);
+ node >= 0;
+ node = fdt_next_subnode(fdt, node)) {
+ if (addr == (u32)fdt_getprop(fdt, node, "reg", 0)) {
+ if (fdtdec_get_is_enabled(fdt, node)) {
+ fdt_status_disabled(fdt, node);
+
+ return true;
+ }
+ return false;
+ }
+ }
+
+ return false;
+}
+
+static int stm32_fdt_fixup_etzpc(void *fdt)
+{
+ const u32 *array;
+ int array_size, i;
+ int soc_node, offset, shift;
+ u32 addr, status, decprot[ETZPC_DECPROT_NB];
+
+ array = stm32mp1_ip_addr;
+ array_size = ARRAY_SIZE(stm32mp1_ip_addr);
+
+ for (i = 0; i < ETZPC_DECPROT_NB; i++)
+ decprot[i] = readl(ETZPC_DECPROT(i));
+
+ soc_node = fdt_path_offset(fdt, "/soc");
+ if (soc_node < 0)
+ return soc_node;
+
+ for (i = 0; i < array_size; i++) {
+ offset = i / NB_PROT_PER_REG;
+ shift = (i % NB_PROT_PER_REG) * DECPROT_NB_BITS;
+ status = (decprot[offset] >> shift) & DECPROT_MASK;
+ addr = array[i];
+
+ debug("ETZPC: 0x%08x decprot %d=%d\n", addr, i, status);
+
+ if (addr == ETZPC_RESERVED ||
+ status == DECPROT_NON_SECURED)
+ continue;
+
+ if (fdt_disable_subnode_by_address(fdt, soc_node, addr))
+ printf("ETZPC: 0x%08x node disabled, decprot %d=%d\n",
+ addr, i, status);
+ }
+
+ return 0;
+}
+
+/*
+ * This function is called right before the kernel is booted. "blob" is the
+ * device tree that will be passed to the kernel.
+ */
+int ft_system_setup(void *blob, bd_t *bd)
+{
+ int ret = 0;
+ u32 pkg;
+
+ if (CONFIG_IS_ENABLED(STM32_ETZPC)) {
+ ret = stm32_fdt_fixup_etzpc(blob);
+ if (ret)
+ return ret;
+ }
+
+ switch (get_cpu_package()) {
+ case PKG_AA_LBGA448:
+ pkg = STM32MP_PKG_AA;
+ break;
+ case PKG_AB_LBGA354:
+ pkg = STM32MP_PKG_AB;
+ break;
+ case PKG_AC_TFBGA361:
+ pkg = STM32MP_PKG_AC;
+ break;
+ case PKG_AD_TFBGA257:
+ pkg = STM32MP_PKG_AD;
+ break;
+ default:
+ pkg = 0;
+ break;
+ }
+ if (pkg) {
+ do_fixup_by_compat_u32(blob, "st,stm32mp157-pinctrl",
+ "st,package", pkg, false);
+ do_fixup_by_compat_u32(blob, "st,stm32mp157-z-pinctrl",
+ "st,package", pkg, false);
+ }
+
+ return ret;
+}
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h
index 6795352044..1d4b5482ac 100644
--- a/arch/arm/mach-stm32mp/include/mach/stm32.h
+++ b/arch/arm/mach-stm32mp/include/mach/stm32.h
@@ -15,6 +15,7 @@
#define STM32_DBGMCU_BASE 0x50081000
#define STM32_TZC_BASE 0x5C006000
#define STM32_ETZPC_BASE 0x5C007000
+#define STM32_STGEN_BASE 0x5C008000
#define STM32_TAMP_BASE 0x5C00A000
#define STM32_USART1_BASE 0x5C000000
@@ -36,9 +37,7 @@
/* enumerated used to identify the SYSCON driver instance */
enum {
STM32MP_SYSCON_UNKNOWN,
- STM32MP_SYSCON_ETZPC,
STM32MP_SYSCON_PWR,
- STM32MP_SYSCON_STGEN,
STM32MP_SYSCON_SYSCFG,
};
diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
index 71a3ba794d..99eefabf6e 100644
--- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h
+++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
@@ -19,5 +19,14 @@ u32 get_cpu_type(void);
/* return CPU_REV constants */
u32 get_cpu_rev(void);
+
+/* Get Package options from OTP */
+u32 get_cpu_package(void);
+
+#define PKG_AA_LBGA448 4
+#define PKG_AB_LBGA354 3
+#define PKG_AC_TFBGA361 2
+#define PKG_AD_TFBGA257 1
+
/* return boot mode */
u32 get_bootmode(void);
diff --git a/arch/arm/mach-stm32mp/syscon.c b/arch/arm/mach-stm32mp/syscon.c
index 242f8340ab..6070837bf0 100644
--- a/arch/arm/mach-stm32mp/syscon.c
+++ b/arch/arm/mach-stm32mp/syscon.c
@@ -9,9 +9,7 @@
#include <asm/arch/stm32.h>
static const struct udevice_id stm32mp_syscon_ids[] = {
- { .compatible = "st,stm32mp1-etzpc", .data = STM32MP_SYSCON_ETZPC },
{ .compatible = "st,stm32mp1-pwr", .data = STM32MP_SYSCON_PWR },
- { .compatible = "st,stm32-stgen", .data = STM32MP_SYSCON_STGEN },
{ .compatible = "st,stm32mp157-syscfg",
.data = STM32MP_SYSCON_SYSCFG },
{ }
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 8147d9781e..531c1afc97 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -823,6 +823,10 @@
dmas = <&dma 0>, <&dma 1>, <&dma 2>;
dma-names = "m2m", "tx0", "rx0";
};
+
+ mdio-test {
+ compatible = "sandbox,mdio";
+ };
};
#include "sandbox_pmic.dtsi"
diff --git a/board/st/stm32f429-discovery/led.c b/board/st/stm32f429-discovery/led.c
index 8320ad4fac..ae6df78f56 100644
--- a/board/st/stm32f429-discovery/led.c
+++ b/board/st/stm32f429-discovery/led.c
@@ -9,7 +9,9 @@
void coloured_LED_init(void)
{
+ gpio_request(CONFIG_RED_LED, "red led");
gpio_direction_output(CONFIG_RED_LED, 0);
+ gpio_request(CONFIG_GREEN_LED, "green led");
gpio_direction_output(CONFIG_GREEN_LED, 0);
}
diff --git a/board/st/stm32mp1/Kconfig b/board/st/stm32mp1/Kconfig
index 5ab94151a9..87216c0963 100644
--- a/board/st/stm32mp1/Kconfig
+++ b/board/st/stm32mp1/Kconfig
@@ -9,4 +9,17 @@ config SYS_VENDOR
config SYS_CONFIG_NAME
default "stm32mp1"
+config ENV_SECT_SIZE
+ default 0x40000 if ENV_IS_IN_SPI_FLASH
+
+config ENV_OFFSET
+ default 0x280000 if ENV_IS_IN_SPI_FLASH
+
+config CMD_STBOARD
+ bool "stboard - command for OTP board information"
+ default y
+ help
+ This compile the stboard command to
+ read and write the board in the OTP.
+
endif
diff --git a/board/st/stm32mp1/MAINTAINERS b/board/st/stm32mp1/MAINTAINERS
index 0a2eddbe03..3bf4c21b60 100644
--- a/board/st/stm32mp1/MAINTAINERS
+++ b/board/st/stm32mp1/MAINTAINERS
@@ -5,5 +5,6 @@ S: Maintained
F: arch/arm/dts/stm32mp157*
F: board/st/stm32mp1
F: configs/stm32mp15_basic_defconfig
+F: configs/stm32mp15_optee_defconfig
F: configs/stm32mp15_trusted_defconfig
F: include/configs/stm32mp1.h
diff --git a/board/st/stm32mp1/Makefile b/board/st/stm32mp1/Makefile
index 8188075b1a..3c6c035b11 100644
--- a/board/st/stm32mp1/Makefile
+++ b/board/st/stm32mp1/Makefile
@@ -7,6 +7,7 @@ ifdef CONFIG_SPL_BUILD
obj-y += spl.o
else
obj-y += stm32mp1.o
+obj-$(CONFIG_CMD_STBOARD) += cmd_stboard.o
endif
obj-y += board.o
diff --git a/board/st/stm32mp1/README b/board/st/stm32mp1/README
index b0c8325061..428357cfa0 100644
--- a/board/st/stm32mp1/README
+++ b/board/st/stm32mp1/README
@@ -25,6 +25,10 @@ It features:
Everything is supported in Linux but U-Boot is limited to:
1. UART
2. SDCard/MMC controller (SDMMC)
+3. NAND controller (FMC)
+4. NOR controller (QSPI)
+5. USB controller (OTG DWC2)
+6. Ethernet controller
And the necessary drivers
1. I2C
@@ -47,20 +51,28 @@ BootRom => FSBL in SYSRAM => SSBL in DDR => OS (Linux Kernel)
with FSBL = First Stage Bootloader
SSBL = Second Stage Bootloader
-2 boot configurations are supported:
+3 boot configurations are supported:
1) The "Trusted" boot chain (defconfig_file : stm32mp15_trusted_defconfig)
BootRom => FSBL = Trusted Firmware-A (TF-A) => SSBL = U-Boot
TF-A performs a full initialization of Secure peripherals and installs a
secure monitor.
U-Boot is running in normal world and uses TF-A monitor
- to access to secure resources
+ to access to secure resources.
-2) The "Basic" boot chain (defconfig_file : stm32mp15_basic_defconfig)
+2) The "Trusted" boot chain with OP-TEE
+ (defconfig_file : stm32mp15_optee_defconfig)
+ BootRom => FSBL = Trusted Firmware-A (TF-A) => SSBL = U-Boot
+ TF-A performs a full initialization of Secure peripherals and installs OP-TEE
+ from specific partitions (teeh, teed, teex).
+ U-Boot is running in normal world and uses OP-TEE monitor to access
+ to secure resources.
+
+3) The "Basic" boot chain (defconfig_file : stm32mp15_basic_defconfig)
BootRom => FSBL = U-Boot SPL => SSBL = U-Boot
SPL has limited security initialisation
U-Boot is running in secure mode and provide a secure monitor to the kernel
- with only PSCI support (Power State Coordination Interface defined by ARM)
+ with only PSCI support (Power State Coordination Interface defined by ARM).
All the STM32MP1 boards supported by U-Boot use the same generic board
stm32mp1 which support all the bootable devices.
@@ -109,13 +121,18 @@ the supported device trees for stm32mp157 are:
for example: use one output directory for each configuration
# export KBUILD_OUTPUT=stm32mp15_trusted
+ # export KBUILD_OUTPUT=stm32mp15_optee
# export KBUILD_OUTPUT=stm32mp15_basic
+ you can build outside of code directory:
+ # export KBUILD_OUTPUT=../build/stm32mp15_trusted
+
4. Configure U-Boot:
# make <defconfig_file>
- For trusted boot mode : "stm32mp15_trusted_defconfig"
+ - For trusted with OP-TEE boot mode : "stm32mp15_optee_defconfig"
- For basic boot mode: "stm32mp15_basic_defconfig"
5. Configure the device-tree and build the U-Boot image:
@@ -129,22 +146,27 @@ the supported device trees for stm32mp157 are:
# make stm32mp15_trusted_defconfig
# make DEVICE_TREE=stm32mp157c-ev1 all
- b) basic boot on ev1
+ b) trusted with OP-TEE boot on dk2
+ # export KBUILD_OUTPUT=stm32mp15_optee
+ # make stm32mp15_optee_defconfig
+ # make DEVICE_TREE=stm32mp157c-dk2 all
+
+ c) basic boot on ev1
# export KBUILD_OUTPUT=stm32mp15_basic
# make stm32mp15_basic_defconfig
# make DEVICE_TREE=stm32mp157c-ev1 all
- c) basic boot on ed1
+ d) basic boot on ed1
# export KBUILD_OUTPUT=stm32mp15_basic
# make stm32mp15_basic_defconfig
# make DEVICE_TREE=stm32mp157c-ed1 all
- d) basic boot on dk2
+ e) basic boot on dk1
# export KBUILD_OUTPUT=stm32mp15_basic
# make stm32mp15_basic_defconfig
- # make DEVICE_TREE=stm32mp157c-dk2 all
+ # make DEVICE_TREE=stm32mp157a-dk1 all
- d) basic boot on avenger96
+ f) basic boot on avenger96
# export KBUILD_OUTPUT=stm32mp15_basic
# make stm32mp15_basic_defconfig
# make DEVICE_TREE=stm32mp157a-avenger96 all
@@ -157,7 +179,7 @@ the supported device trees for stm32mp157 are:
So in the output directory (selected by KBUILD_OUTPUT),
you can found the needed files:
- a) For Trusted boot
+ a) For Trusted boot (with or without OP-TEE)
+ FSBL = tf-a.stm32 (provided by TF-A compilation)
+ SSBL = u-boot.stm32
@@ -170,6 +192,8 @@ the supported device trees for stm32mp157 are:
You can select the boot mode, on the board ed1 with the switch SW1
+- on the daugther board ed1 with the switch SW1 : BOOT0, BOOT1, BOOT2
+
-----------------------------------
Boot Mode BOOT2 BOOT1 BOOT0
-----------------------------------
@@ -267,7 +291,7 @@ for example: with gpt table with 128 entries
# dd if=tf-a.stm32 of=/dev/mmcblk0p2
# dd if=u-boot.stm32 of=/dev/mmcblk0p3
-To boot from SDCard, select BootPinMode = 1 1 1 and reset.
+To boot from SDCard, select BootPinMode = 1 0 1 and reset.
8. Prepare eMMC
===============
diff --git a/board/st/stm32mp1/cmd_stboard.c b/board/st/stm32mp1/cmd_stboard.c
new file mode 100644
index 0000000000..f781c364cf
--- /dev/null
+++ b/board/st/stm32mp1/cmd_stboard.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <console.h>
+#include <misc.h>
+#include <dm/device.h>
+#include <dm/uclass.h>
+
+static bool check_stboard(u16 board)
+{
+ unsigned int i;
+ const u16 st_board_id[] = {
+ 0x1272,
+ 0x1263,
+ 0x1264,
+ 0x1298,
+ 0x1341,
+ 0x1497,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(st_board_id); i++)
+ if (board == st_board_id[i])
+ return true;
+
+ return false;
+}
+
+static void display_stboard(u32 otp)
+{
+ printf("Board: MB%04x Var%d Rev.%c-%02d\n",
+ otp >> 16,
+ (otp >> 12) & 0xF,
+ ((otp >> 8) & 0xF) - 1 + 'A',
+ otp & 0xF);
+}
+
+static int do_stboard(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ int ret;
+ u32 otp;
+ u8 revision;
+ unsigned long board, variant, bom;
+ struct udevice *dev;
+ int confirmed = argc == 6 && !strcmp(argv[1], "-y");
+
+ argc -= 1 + confirmed;
+ argv += 1 + confirmed;
+
+ if (argc != 0 && argc != 4)
+ return CMD_RET_USAGE;
+
+ ret = uclass_get_device_by_driver(UCLASS_MISC,
+ DM_GET_DRIVER(stm32mp_bsec),
+ &dev);
+
+ ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
+ &otp, sizeof(otp));
+
+ if (ret) {
+ puts("OTP read error");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc == 0) {
+ if (!otp)
+ puts("Board : OTP board FREE\n");
+ else
+ display_stboard(otp);
+ return CMD_RET_SUCCESS;
+ }
+
+ if (otp) {
+ display_stboard(otp);
+ printf("ERROR: OTP board not FREE\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (strict_strtoul(argv[0], 16, &board) < 0 ||
+ board == 0 || board > 0xFFFF) {
+ printf("argument %d invalid: %s\n", 1, argv[0]);
+ return CMD_RET_USAGE;
+ }
+
+ if (strict_strtoul(argv[1], 10, &variant) < 0 ||
+ variant == 0 || variant > 15) {
+ printf("argument %d invalid: %s\n", 2, argv[1]);
+ return CMD_RET_USAGE;
+ }
+
+ revision = argv[2][0] - 'A' + 1;
+ if (strlen(argv[2]) > 1 || revision == 0 || revision > 15) {
+ printf("argument %d invalid: %s\n", 3, argv[2]);
+ return CMD_RET_USAGE;
+ }
+
+ if (strict_strtoul(argv[3], 10, &bom) < 0 ||
+ bom == 0 || bom > 15) {
+ printf("argument %d invalid: %s\n", 4, argv[3]);
+ return CMD_RET_USAGE;
+ }
+
+ otp = (board << 16) | (variant << 12) | (revision << 8) | bom;
+ display_stboard(otp);
+ printf("=> OTP[%d] = %08X\n", BSEC_OTP_BOARD, otp);
+
+ if (!check_stboard((u16)board)) {
+ printf("Unknown board MB%04x\n", (u16)board);
+ return CMD_RET_FAILURE;
+ }
+ if (!confirmed) {
+ printf("Warning: Programming BOARD in OTP is irreversible!\n");
+ printf("Really perform this OTP programming? <y/N>\n");
+
+ if (!confirm_yesno()) {
+ puts("BOARD programming aborted\n");
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ ret = misc_write(dev, STM32_BSEC_OTP(BSEC_OTP_BOARD),
+ &otp, sizeof(otp));
+
+ if (ret) {
+ puts("BOARD programming error\n");
+ return CMD_RET_FAILURE;
+ }
+ puts("BOARD programming done\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(stboard, 6, 0, do_stboard,
+ "read/write board reference in OTP",
+ "\n"
+ " Print current board information\n"
+ "stboard [-y] <Board> <Variant> <Revision> <BOM>\n"
+ " Write board information\n"
+ " - Board: xxxx, example 1264 for MB1264\n"
+ " - Variant: 1 ... 15\n"
+ " - Revision: A...O\n"
+ " - BOM: 1...15\n");
diff --git a/board/st/stm32mp1/spl.c b/board/st/stm32mp1/spl.c
index a7844f244b..e19be0f770 100644
--- a/board/st/stm32mp1/spl.c
+++ b/board/st/stm32mp1/spl.c
@@ -9,7 +9,6 @@
#include <dm.h>
#include <ram.h>
#include <asm/io.h>
-#include <post.h>
#include <power/pmic.h>
#include <power/stpmic1.h>
#include <asm/arch/ddr.h>
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 776929350f..b99c6c08a3 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -4,6 +4,7 @@
*/
#include <common.h>
#include <adc.h>
+#include <bootm.h>
#include <config.h>
#include <clk.h>
#include <dm.h>
@@ -13,6 +14,8 @@
#include <i2c.h>
#include <led.h>
#include <misc.h>
+#include <mtd.h>
+#include <mtd_node.h>
#include <phy.h>
#include <reset.h>
#include <syscon.h>
@@ -21,6 +24,7 @@
#include <asm/gpio.h>
#include <asm/arch/stm32.h>
#include <asm/arch/sys_proto.h>
+#include <jffs2/load_kernel.h>
#include <power/regulator.h>
#include <usb/dwc2_udc.h>
@@ -76,7 +80,9 @@ int checkboard(void)
const char *fdt_compat;
int fdt_compat_len;
- if (IS_ENABLED(CONFIG_STM32MP1_TRUSTED))
+ if (IS_ENABLED(CONFIG_STM32MP1_OPTEE))
+ mode = "trusted with OP-TEE";
+ else if (IS_ENABLED(CONFIG_STM32MP1_TRUSTED))
mode = "trusted";
else
mode = "basic";
@@ -515,6 +521,10 @@ int board_init(void)
board_key_check();
+#ifdef CONFIG_DM_REGULATOR
+ regulators_enable_boot_on(_DEBUG);
+#endif
+
sysconf_init();
if (IS_ENABLED(CONFIG_LED))
@@ -745,3 +755,18 @@ void board_mtdparts_default(const char **mtdids, const char **mtdparts)
debug("%s:mtdids=%s & mtdparts=%s\n", __func__, ids, parts);
}
#endif
+
+#if defined(CONFIG_OF_BOARD_SETUP)
+int ft_board_setup(void *blob, bd_t *bd)
+{
+#ifdef CONFIG_FDT_FIXUP_PARTITIONS
+ struct node_info nodes[] = {
+ { "st,stm32f469-qspi", MTD_DEV_TYPE_NOR, },
+ { "st,stm32mp15-fmc2", MTD_DEV_TYPE_NAND, },
+ };
+ fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
+#endif
+
+ return 0;
+}
+#endif
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 7f6bca81a9..67284d8a5f 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -955,15 +955,6 @@ config CMD_NVME
help
NVM Express device support
-config CMD_MMC_SPI
- bool "mmc_spi - Set up MMC SPI device"
- help
- Provides a way to set up an MMC (Multimedia Card) SPI (Serial
- Peripheral Interface) device. The device provides a means of
- accessing an MMC device via SPI using a single data line, limited
- to 20MHz. It is useful since it reduces the amount of protocol code
- required.
-
config CMD_ONENAND
bool "onenand - access to onenand device"
help
diff --git a/cmd/Makefile b/cmd/Makefile
index 49e64cde1d..0aa3741453 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -93,7 +93,6 @@ obj-$(CONFIG_CMD_MII) += mdio.o
endif
obj-$(CONFIG_CMD_MISC) += misc.o
obj-$(CONFIG_CMD_MMC) += mmc.o
-obj-$(CONFIG_CMD_MMC_SPI) += mmc_spi.o
obj-$(CONFIG_MP) += mp.o
obj-$(CONFIG_CMD_MTD) += mtd.o
obj-$(CONFIG_CMD_MTDPARTS) += mtdparts.o
diff --git a/cmd/mdio.c b/cmd/mdio.c
index 5e219f699d..a6fa9266d0 100644
--- a/cmd/mdio.c
+++ b/cmd/mdio.c
@@ -203,6 +203,11 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (argc < 2)
return CMD_RET_USAGE;
+#ifdef CONFIG_DM_MDIO
+ /* probe DM MII device before any operation so they are all accesible */
+ dm_mdio_probe_devices();
+#endif
+
/*
* We use the last specified parameters, unless new ones are
* entered.
diff --git a/cmd/mii.c b/cmd/mii.c
index c0c42a851f..23ee1e6cfa 100644
--- a/cmd/mii.c
+++ b/cmd/mii.c
@@ -12,25 +12,11 @@
#include <command.h>
#include <miiphy.h>
-typedef struct _MII_reg_desc_t {
- ushort regno;
- char * name;
-} MII_reg_desc_t;
-
-static const MII_reg_desc_t reg_0_5_desc_tbl[] = {
- { MII_BMCR, "PHY control register" },
- { MII_BMSR, "PHY status register" },
- { MII_PHYSID1, "PHY ID 1 register" },
- { MII_PHYSID2, "PHY ID 2 register" },
- { MII_ADVERTISE, "Autonegotiation advertisement register" },
- { MII_LPA, "Autonegotiation partner abilities register" },
-};
-
typedef struct _MII_field_desc_t {
ushort hi;
ushort lo;
ushort mask;
- char * name;
+ const char *name;
} MII_field_desc_t;
static const MII_field_desc_t reg_0_desc_tbl[] = {
@@ -87,7 +73,7 @@ static const MII_field_desc_t reg_4_desc_tbl[] = {
{ 7, 7, 0x01, "100BASE-TX able" },
{ 6, 6, 0x01, "10BASE-T full duplex able" },
{ 5, 5, 0x01, "10BASE-T able" },
- { 4, 0, 0x1f, "xxx to do" },
+ { 4, 0, 0x1f, "selector" },
};
static const MII_field_desc_t reg_5_desc_tbl[] = {
@@ -102,50 +88,91 @@ static const MII_field_desc_t reg_5_desc_tbl[] = {
{ 7, 7, 0x01, "100BASE-TX able" },
{ 6, 6, 0x01, "10BASE-T full duplex able" },
{ 5, 5, 0x01, "10BASE-T able" },
- { 4, 0, 0x1f, "xxx to do" },
+ { 4, 0, 0x1f, "partner selector" },
};
-typedef struct _MII_field_desc_and_len_t {
+
+static const MII_field_desc_t reg_9_desc_tbl[] = {
+ { 15, 13, 0x07, "test mode" },
+ { 12, 12, 0x01, "manual master/slave enable" },
+ { 11, 11, 0x01, "manual master/slave value" },
+ { 10, 10, 0x01, "multi/single port" },
+ { 9, 9, 0x01, "1000BASE-T full duplex able" },
+ { 8, 8, 0x01, "1000BASE-T half duplex able" },
+ { 7, 7, 0x01, "automatic TDR on link down" },
+ { 6, 6, 0x7f, "(reserved)" },
+};
+
+static const MII_field_desc_t reg_10_desc_tbl[] = {
+ { 15, 15, 0x01, "master/slave config fault" },
+ { 14, 14, 0x01, "master/slave config result" },
+ { 13, 13, 0x01, "local receiver status OK" },
+ { 12, 12, 0x01, "remote receiver status OK" },
+ { 11, 11, 0x01, "1000BASE-T full duplex able" },
+ { 10, 10, 0x01, "1000BASE-T half duplex able" },
+ { 9, 8, 0x03, "(reserved)" },
+ { 7, 0, 0xff, "1000BASE-T idle error counter"},
+};
+
+typedef struct _MII_reg_desc_t {
+ ushort regno;
const MII_field_desc_t *pdesc;
ushort len;
-} MII_field_desc_and_len_t;
-
-static const MII_field_desc_and_len_t desc_and_len_tbl[] = {
- { reg_0_desc_tbl, ARRAY_SIZE(reg_0_desc_tbl) },
- { reg_1_desc_tbl, ARRAY_SIZE(reg_1_desc_tbl) },
- { reg_2_desc_tbl, ARRAY_SIZE(reg_2_desc_tbl) },
- { reg_3_desc_tbl, ARRAY_SIZE(reg_3_desc_tbl) },
- { reg_4_desc_tbl, ARRAY_SIZE(reg_4_desc_tbl) },
- { reg_5_desc_tbl, ARRAY_SIZE(reg_5_desc_tbl) },
+ const char *name;
+} MII_reg_desc_t;
+
+static const MII_reg_desc_t mii_reg_desc_tbl[] = {
+ { MII_BMCR, reg_0_desc_tbl, ARRAY_SIZE(reg_0_desc_tbl),
+ "PHY control register" },
+ { MII_BMSR, reg_1_desc_tbl, ARRAY_SIZE(reg_1_desc_tbl),
+ "PHY status register" },
+ { MII_PHYSID1, reg_2_desc_tbl, ARRAY_SIZE(reg_2_desc_tbl),
+ "PHY ID 1 register" },
+ { MII_PHYSID2, reg_3_desc_tbl, ARRAY_SIZE(reg_3_desc_tbl),
+ "PHY ID 2 register" },
+ { MII_ADVERTISE, reg_4_desc_tbl, ARRAY_SIZE(reg_4_desc_tbl),
+ "Autonegotiation advertisement register" },
+ { MII_LPA, reg_5_desc_tbl, ARRAY_SIZE(reg_5_desc_tbl),
+ "Autonegotiation partner abilities register" },
+ { MII_CTRL1000, reg_9_desc_tbl, ARRAY_SIZE(reg_9_desc_tbl),
+ "1000BASE-T control register" },
+ { MII_STAT1000, reg_10_desc_tbl, ARRAY_SIZE(reg_10_desc_tbl),
+ "1000BASE-T status register" },
};
static void dump_reg(
ushort regval,
- const MII_reg_desc_t *prd,
- const MII_field_desc_and_len_t *pdl);
-
-static int special_field(
- ushort regno,
- const MII_field_desc_t *pdesc,
- ushort regval);
-
-static void MII_dump_0_to_5(
- ushort regvals[6],
- uchar reglo,
- uchar reghi)
+ const MII_reg_desc_t *prd);
+
+static bool special_field(ushort regno, const MII_field_desc_t *pdesc,
+ ushort regval);
+
+static void MII_dump(const ushort *regvals, uchar reglo, uchar reghi)
{
ulong i;
- for (i = 0; i < 6; i++) {
- if ((reglo <= i) && (i <= reghi))
- dump_reg(regvals[i], &reg_0_5_desc_tbl[i],
- &desc_and_len_tbl[i]);
+ for (i = 0; i < ARRAY_SIZE(mii_reg_desc_tbl); i++) {
+ const uchar reg = mii_reg_desc_tbl[i].regno;
+
+ if (reg >= reglo && reg <= reghi)
+ dump_reg(regvals[reg - reglo], &mii_reg_desc_tbl[i]);
}
}
+/* Print out field position, value, name */
+static void dump_field(const MII_field_desc_t *pdesc, ushort regval)
+{
+ if (pdesc->hi == pdesc->lo)
+ printf("%2u ", pdesc->lo);
+ else
+ printf("%2u-%2u", pdesc->hi, pdesc->lo);
+
+ printf(" = %5u %s", (regval >> pdesc->lo) & pdesc->mask,
+ pdesc->name);
+}
+
static void dump_reg(
ushort regval,
- const MII_reg_desc_t *prd,
- const MII_field_desc_and_len_t *pdl)
+ const MII_reg_desc_t *prd)
{
ulong i;
ushort mask_in_place;
@@ -154,8 +181,8 @@ static void dump_reg(
printf("%u. (%04hx) -- %s --\n",
prd->regno, regval, prd->name);
- for (i = 0; i < pdl->len; i++) {
- pdesc = &pdl->pdesc[i];
+ for (i = 0; i < prd->len; i++) {
+ pdesc = &prd->pdesc[i];
mask_in_place = pdesc->mask << pdesc->lo;
@@ -164,17 +191,8 @@ static void dump_reg(
regval & mask_in_place,
prd->regno);
- if (special_field(prd->regno, pdesc, regval)) {
- }
- else {
- if (pdesc->hi == pdesc->lo)
- printf("%2u ", pdesc->lo);
- else
- printf("%2u-%2u", pdesc->hi, pdesc->lo);
- printf(" = %5u %s",
- (regval & mask_in_place) >> pdesc->lo,
- pdesc->name);
- }
+ if (!special_field(prd->regno, pdesc, regval))
+ dump_field(pdesc, regval);
printf("\n");
}
@@ -190,11 +208,11 @@ static void dump_reg(
** 5.4-0
*/
-static int special_field(
- ushort regno,
- const MII_field_desc_t *pdesc,
- ushort regval)
+static bool special_field(ushort regno, const MII_field_desc_t *pdesc,
+ ushort regval)
{
+ const ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask;
+
if ((regno == MII_BMCR) && (pdesc->lo == 6)) {
ushort speed_bits = regval & (BMCR_SPEED1000 | BMCR_SPEED100);
printf("%2u,%2u = b%u%u speed selection = %s Mbps",
@@ -208,34 +226,26 @@ static int special_field(
}
else if ((regno == MII_BMCR) && (pdesc->lo == 8)) {
- printf("%2u = %5u duplex = %s",
- pdesc->lo,
- (regval >> pdesc->lo) & 1,
- ((regval >> pdesc->lo) & 1) ? "full" : "half");
+ dump_field(pdesc, regval);
+ printf(" = %s", ((regval >> pdesc->lo) & 1) ? "full" : "half");
return 1;
}
else if ((regno == MII_ADVERTISE) && (pdesc->lo == 0)) {
- ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask;
- printf("%2u-%2u = %5u selector = %s",
- pdesc->hi, pdesc->lo, sel_bits,
- sel_bits == PHY_ANLPAR_PSB_802_3 ?
- "IEEE 802.3" :
- sel_bits == PHY_ANLPAR_PSB_802_9 ?
- "IEEE 802.9 ISLAN-16T" :
- "???");
+ dump_field(pdesc, regval);
+ printf(" = %s",
+ sel_bits == PHY_ANLPAR_PSB_802_3 ? "IEEE 802.3 CSMA/CD" :
+ sel_bits == PHY_ANLPAR_PSB_802_9 ?
+ "IEEE 802.9 ISLAN-16T" : "???");
return 1;
}
else if ((regno == MII_LPA) && (pdesc->lo == 0)) {
- ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask;
- printf("%2u-%2u = %u selector = %s",
- pdesc->hi, pdesc->lo, sel_bits,
- sel_bits == PHY_ANLPAR_PSB_802_3 ?
- "IEEE 802.3" :
- sel_bits == PHY_ANLPAR_PSB_802_9 ?
- "IEEE 802.9 ISLAN-16T" :
- "???");
+ dump_field(pdesc, regval);
+ printf(" = %s",
+ sel_bits == PHY_ANLPAR_PSB_802_3 ? "IEEE 802.3 CSMA/CD" :
+ sel_bits == PHY_ANLPAR_PSB_802_9 ?
+ "IEEE 802.9 ISLAN-16T" : "???");
return 1;
}
@@ -406,17 +416,16 @@ static int do_mii(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
}
} else if (strncmp(op, "du", 2) == 0) {
- ushort regs[6];
+ ushort regs[MII_STAT1000 + 1]; /* Last reg is 0x0a */
int ok = 1;
- if ((reglo > 5) || (reghi > 5)) {
- printf(
- "The MII dump command only formats the "
- "standard MII registers, 0-5.\n");
+ if (reglo > MII_STAT1000 || reghi > MII_STAT1000) {
+ printf("The MII dump command only formats the standard MII registers, 0-5, 9-a.\n");
return 1;
}
for (addr = addrlo; addr <= addrhi; addr++) {
- for (reg = reglo; reg < reghi + 1; reg++) {
- if (miiphy_read(devname, addr, reg, &regs[reg]) != 0) {
+ for (reg = reglo; reg <= reghi; reg++) {
+ if (miiphy_read(devname, addr, reg,
+ &regs[reg - reglo]) != 0) {
ok = 0;
printf(
"Error reading from the PHY addr=%02x reg=%02x\n",
@@ -425,7 +434,7 @@ static int do_mii(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
}
if (ok)
- MII_dump_0_to_5(regs, reglo, reghi);
+ MII_dump(regs, reglo, reghi);
printf("\n");
}
} else if (strncmp(op, "de", 2) == 0) {
diff --git a/cmd/mmc_spi.c b/cmd/mmc_spi.c
deleted file mode 100644
index 0c44d06817..0000000000
--- a/cmd/mmc_spi.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Command for mmc_spi setup.
- *
- * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <mmc.h>
-#include <spi.h>
-
-#ifndef CONFIG_MMC_SPI_BUS
-# define CONFIG_MMC_SPI_BUS 0
-#endif
-#ifndef CONFIG_MMC_SPI_CS
-# define CONFIG_MMC_SPI_CS 1
-#endif
-/* in SPI mode, MMC speed limit is 20MHz, while SD speed limit is 25MHz */
-#ifndef CONFIG_MMC_SPI_SPEED
-# define CONFIG_MMC_SPI_SPEED 25000000
-#endif
-/* MMC and SD specs only seem to care that sampling is on the
- * rising edge ... meaning SPI modes 0 or 3. So either SPI mode
- * should be legit. We'll use mode 0 since the steady state is 0,
- * which is appropriate for hotplugging, unless the platform data
- * specify mode 3 (if hardware is not compatible to mode 0).
- */
-#ifndef CONFIG_MMC_SPI_MODE
-# define CONFIG_MMC_SPI_MODE SPI_MODE_0
-#endif
-
-static int do_mmc_spi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- uint bus = CONFIG_MMC_SPI_BUS;
- uint cs = CONFIG_MMC_SPI_CS;
- uint speed = CONFIG_MMC_SPI_SPEED;
- uint mode = CONFIG_MMC_SPI_MODE;
- char *endp;
- struct mmc *mmc;
-
- if (argc < 2)
- goto usage;
-
- cs = simple_strtoul(argv[1], &endp, 0);
- if (*argv[1] == 0 || (*endp != 0 && *endp != ':'))
- goto usage;
- if (*endp == ':') {
- if (endp[1] == 0)
- goto usage;
- bus = cs;
- cs = simple_strtoul(endp + 1, &endp, 0);
- if (*endp != 0)
- goto usage;
- }
- if (argc >= 3) {
- speed = simple_strtoul(argv[2], &endp, 0);
- if (*argv[2] == 0 || *endp != 0)
- goto usage;
- }
- if (argc >= 4) {
- mode = simple_strtoul(argv[3], &endp, 16);
- if (*argv[3] == 0 || *endp != 0)
- goto usage;
- }
- if (!spi_cs_is_valid(bus, cs)) {
- printf("Invalid SPI bus %u cs %u\n", bus, cs);
- return 1;
- }
-
- mmc = mmc_spi_init(bus, cs, speed, mode);
- if (!mmc) {
- printf("Failed to create MMC Device\n");
- return 1;
- }
- printf("%s: %d at %u:%u hz %u mode %u\n", mmc->cfg->name,
- mmc->block_dev.devnum, bus, cs, speed, mode);
- mmc_init(mmc);
- return 0;
-
-usage:
- return CMD_RET_USAGE;
-}
-
-U_BOOT_CMD(
- mmc_spi, 4, 0, do_mmc_spi,
- "mmc_spi setup",
- "[bus:]cs [hz] [mode] - setup mmc_spi device"
-);
diff --git a/cmd/pinmux.c b/cmd/pinmux.c
index 6c8ec5164d..de909a163d 100644
--- a/cmd/pinmux.c
+++ b/cmd/pinmux.c
@@ -27,6 +27,7 @@ static int do_dev(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf("Can't get the pin-controller: %s!\n", name);
return CMD_RET_FAILURE;
}
+ /* fall through */
case 1:
if (!currdev) {
printf("Pin-controller device is not set!\n");
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig
index 41cf0100fa..b940af3f56 100644
--- a/configs/am65x_evm_a53_defconfig
+++ b/configs/am65x_evm_a53_defconfig
@@ -44,6 +44,7 @@ CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y
CONFIG_ENV_IS_IN_FAT=y
CONFIG_ENV_FAT_INTERFACE="mmc"
CONFIG_ENV_FAT_DEVICE_AND_PART="1:1"
+CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_DM=y
CONFIG_SPL_DM=y
CONFIG_SPL_DM_SEQ_ALIAS=y
@@ -58,6 +59,11 @@ CONFIG_K3_SEC_PROXY=y
CONFIG_DM_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_K3_ARASAN=y
+CONFIG_PHY_TI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_TI_AM65_CPSW_NUSS=y
+CONFIG_PHY=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_GENERIC is not set
CONFIG_SPL_PINCTRL=y
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
index 79687d3dfd..adf7b616ee 100644
--- a/configs/stm32mp15_basic_defconfig
+++ b/configs/stm32mp15_basic_defconfig
@@ -4,6 +4,8 @@ CONFIG_SYS_MALLOC_F_LEN=0x3000
CONFIG_SPL_MMC_SUPPORT=y
CONFIG_SPL=y
CONFIG_TARGET_STM32MP1=y
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI_SUPPORT=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_FIT=y
CONFIG_BOOTCOMMAND="run bootcmd_stm32mp"
@@ -11,6 +13,7 @@ CONFIG_SPL_TEXT_BASE=0x2FFC2500
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=3
CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_SPL_MTD_SUPPORT=y
CONFIG_SPL_POWER_SUPPORT=y
CONFIG_SYS_PROMPT="STM32MP> "
# CONFIG_CMD_BOOTD is not set
@@ -43,6 +46,7 @@ CONFIG_CMD_MTDPARTS=y
CONFIG_CMD_UBI=y
# CONFIG_SPL_DOS_PARTITION is not set
CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
+CONFIG_OF_SPL_REMOVE_PROPS="interrupts interrupt-names interrupts-extended interrupt-controller \\\#interrupt-cells interrupt-parent dmas dma-names assigned-clocks assigned-clock-rates assigned-clock-parents hwlocks"
CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_EXT4=y
CONFIG_ENV_IS_IN_SPI_FLASH=y
@@ -66,6 +70,8 @@ CONFIG_DM_I2C=y
CONFIG_SYS_I2C_STM32F7=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
+CONFIG_DM_MAILBOX=y
+CONFIG_STM32_IPCC=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_STM32_SDMMC2=y
@@ -111,5 +117,4 @@ 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
+CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/configs/stm32mp15_optee_defconfig b/configs/stm32mp15_optee_defconfig
new file mode 100644
index 0000000000..a205f47cd8
--- /dev/null
+++ b/configs/stm32mp15_optee_defconfig
@@ -0,0 +1,107 @@
+CONFIG_ARM=y
+CONFIG_ARCH_STM32MP=y
+CONFIG_SYS_MALLOC_F_LEN=0x3000
+CONFIG_TARGET_STM32MP1=y
+CONFIG_STM32MP1_OPTEE=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_BOOTCOMMAND="run bootcmd_stm32mp"
+CONFIG_SYS_PROMPT="STM32MP> "
+# CONFIG_CMD_BOOTD is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_ADC=y
+CONFIG_CMD_CLK=y
+CONFIG_CMD_DFU=y
+CONFIG_CMD_FUSE=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+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_ENV_UBI_VOLUME_REDUND="uboot_config_r"
+CONFIG_STM32_ADC=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
+CONFIG_FASTBOOT_BUF_SIZE=0x02000000
+CONFIG_FASTBOOT_USB_DEV=1
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=1
+CONFIG_DM_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_STM32=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_STM32F7=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_DM_MAILBOX=y
+CONFIG_STM32_IPCC=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
+CONFIG_PINCTRL_STMFX=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_STPMIC1=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_DM_REGULATOR_STM32_VREFBUF=y
+CONFIG_DM_REGULATOR_STPMIC1=y
+CONFIG_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
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0483
+CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
index e1ab2ab0d5..cdb4d95bf6 100644
--- a/configs/stm32mp15_trusted_defconfig
+++ b/configs/stm32mp15_trusted_defconfig
@@ -58,6 +58,8 @@ CONFIG_DM_I2C=y
CONFIG_SYS_I2C_STM32F7=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
+CONFIG_DM_MAILBOX=y
+CONFIG_STM32_IPCC=y
CONFIG_DM_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_STM32_SDMMC2=y
@@ -101,5 +103,4 @@ 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
+CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt b/doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt
index c41ae91f7a..00169255e4 100644
--- a/doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt
+++ b/doc/device-tree-bindings/pinctrl/st,stm32-pinctrl.txt
@@ -8,8 +8,13 @@ controllers onto these pads.
Pin controller node:
Required properies:
- compatible: value should be one of the following:
- (a) "st,stm32f429-pinctrl"
- (b) "st,stm32f746-pinctrl"
+ "st,stm32f429-pinctrl"
+ "st,stm32f469-pinctrl"
+ "st,stm32f746-pinctrl"
+ "st,stm32f769-pinctrl"
+ "st,stm32h743-pinctrl"
+ "st,stm32mp157-pinctrl"
+ "st,stm32mp157-z-pinctrl"
- #address-cells: The value of this property must be 1
- #size-cells : The value of this property must be 1
- ranges : defines mapping between pin controller node (parent) to
@@ -32,13 +37,30 @@ Required properties:
Optional properties:
- reset: : Reference to the reset controller
- - interrupt-parent: phandle of the interrupt parent to which the external
- GPIO interrupts are forwarded to.
- - st,syscfg: Should be phandle/offset pair. The phandle to the syscon node
- which includes IRQ mux selection register, and the offset of the IRQ mux
- selection register.
+ - st,syscfg: Should be phandle/offset/mask.
+ -The phandle to the syscon node which includes IRQ mux selection register.
+ -The offset of the IRQ mux selection register
+ -The field mask of IRQ mux, needed if different of 0xf.
+ - gpio-ranges: Define a dedicated mapping between a pin-controller and
+ a gpio controller. Format is <&phandle a b c> with:
+ -(phandle): phandle of pin-controller.
+ -(a): gpio base offset in range.
+ -(b): pin base offset in range.
+ -(c): gpio count in range
+ This entry has to be used either if there are holes inside a bank:
+ GPIOB0/B1/B2/B14/B15 (see example 2)
+ or if banks are not contiguous:
+ GPIOA/B/C/E...
+ NOTE: If "gpio-ranges" is used for a gpio controller, all gpio-controller
+ have to use a "gpio-ranges" entry.
+ More details in Documentation/devicetree/bindings/gpio/gpio.txt.
+ - st,bank-ioport: should correspond to the EXTI IOport selection (EXTI line
+ used to select GPIOs as interrupts).
+ - hwlocks: reference to a phandle of a hardware spinlock provider node.
+ - st,package: Indicates the SOC package used.
+ More details in include/dt-bindings/pinctrl/stm32-pinfunc.h
-Example:
+Example 1:
#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
...
@@ -60,6 +82,43 @@ Example:
pin-functions nodes follow...
};
+Example 2:
+#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
+...
+
+ pinctrl: pin-controller {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,stm32f429-pinctrl";
+ ranges = <0 0x40020000 0x3000>;
+ pins-are-numbered;
+
+ gpioa: gpio@40020000 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x0 0x400>;
+ resets = <&reset_ahb1 0>;
+ st,bank-name = "GPIOA";
+ gpio-ranges = <&pinctrl 0 0 16>;
+ };
+
+ gpiob: gpio@40020400 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x0 0x400>;
+ resets = <&reset_ahb1 0>;
+ st,bank-name = "GPIOB";
+ ngpios = 4;
+ gpio-ranges = <&pinctrl 0 16 3>,
+ <&pinctrl 14 30 2>;
+ };
+
+
+ ...
+ pin-functions nodes follow...
+ };
+
+
Contents of function subnode node:
----------------------------------
Subnode format
@@ -83,14 +142,31 @@ Required properties:
- port: The gpio port index (PA = 0, PB = 1, ..., PK = 11)
- line: The line offset within the port (PA0 = 0, PA1 = 1, ..., PA15 = 15)
- function: The function number, can be:
- * 0 : GPIO IN
+ * 0 : GPIO
* 1 : Alternate Function 0
* 2 : Alternate Function 1
* 3 : Alternate Function 2
* ...
* 16 : Alternate Function 15
* 17 : Analog
- * 18 : GPIO OUT
+
+ To simplify the usage, macro is available to generate "pinmux" field.
+ This macro is available here:
+ - include/dt-bindings/pinctrl/stm32-pinfunc.h
+
+ Some examples of using macro:
+ /* GPIO A9 set as alernate function 2 */
+ ... {
+ pinmux = <STM32_PINMUX('A', 9, AF2)>;
+ };
+ /* GPIO A9 set as GPIO */
+ ... {
+ pinmux = <STM32_PINMUX('A', 9, GPIO)>;
+ };
+ /* GPIO A9 set as analog */
+ ... {
+ pinmux = <STM32_PINMUX('A', 9, ANALOG)>;
+ };
Optional properties:
- GENERIC_PINCONFIG: is the generic pinconfig options to use.
@@ -114,13 +190,13 @@ pin-controller {
...
usart1_pins_a: usart1@0 {
pins1 {
- pinmux = <STM32F429_PA9_FUNC_USART1_TX>;
+ pinmux = <STM32_PINMUX('A', 9, AF7)>;
bias-disable;
drive-push-pull;
slew-rate = <0>;
};
pins2 {
- pinmux = <STM32F429_PA10_FUNC_USART1_RX>;
+ pinmux = <STM32_PINMUX('A', 10, AF7)>;
bias-disable;
};
};
@@ -129,5 +205,4 @@ pin-controller {
&usart1 {
pinctrl-0 = <&usart1_pins_a>;
pinctrl-names = "default";
- status = "okay";
};
diff --git a/drivers/adc/stm32-adc-core.c b/drivers/adc/stm32-adc-core.c
index a9aa143bfe..04b6a8a2f5 100644
--- a/drivers/adc/stm32-adc-core.c
+++ b/drivers/adc/stm32-adc-core.c
@@ -60,7 +60,8 @@ static int stm32h7_adc_clk_sel(struct udevice *dev,
{
u32 ckmode, presc;
unsigned long rate;
- int i, div;
+ unsigned int i;
+ int div;
/* stm32h7 bus clock is common for all ADC instances (mandatory) */
if (!clk_valid(&common->bclk)) {
diff --git a/drivers/adc/stm32-adc.c b/drivers/adc/stm32-adc.c
index e108062f2f..029338e4af 100644
--- a/drivers/adc/stm32-adc.c
+++ b/drivers/adc/stm32-adc.c
@@ -163,15 +163,16 @@ static int stm32_adc_chan_of_init(struct udevice *dev)
struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
struct stm32_adc *adc = dev_get_priv(dev);
u32 chans[STM32_ADC_CH_MAX];
- int i, num_channels, ret;
+ unsigned int i, num_channels;
+ int ret;
/* Retrieve single ended channels listed in device tree */
- num_channels = dev_read_size(dev, "st,adc-channels");
- if (num_channels < 0) {
- dev_err(dev, "can't get st,adc-channels: %d\n", num_channels);
- return num_channels;
+ ret = dev_read_size(dev, "st,adc-channels");
+ if (ret < 0) {
+ dev_err(dev, "can't get st,adc-channels: %d\n", ret);
+ return ret;
}
- num_channels /= sizeof(u32);
+ num_channels = ret / sizeof(u32);
if (num_channels > adc->cfg->max_channels) {
dev_err(dev, "too many st,adc-channels: %d\n", num_channels);
diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c
index f295e4864b..6ffa05b8fd 100644
--- a/drivers/clk/clk_stm32mp1.c
+++ b/drivers/clk/clk_stm32mp1.c
@@ -805,10 +805,11 @@ static int stm32mp1_clk_get_parent(struct stm32mp1_clk_priv *priv,
const struct stm32mp1_clk_sel *sel = priv->data->sel;
int i;
int s, p;
+ unsigned int idx;
- for (i = 0; i < ARRAY_SIZE(stm32mp1_clks); i++)
- if (stm32mp1_clks[i][0] == id)
- return stm32mp1_clks[i][1];
+ for (idx = 0; idx < ARRAY_SIZE(stm32mp1_clks); idx++)
+ if (stm32mp1_clks[idx][0] == id)
+ return stm32mp1_clks[idx][1];
i = stm32mp1_clk_get_id(priv, id);
if (i < 0)
@@ -1542,8 +1543,7 @@ static void stgen_config(struct stm32mp1_clk_priv *priv)
u32 stgenc, cntfid0;
ulong rate;
- stgenc = (u32)syscon_get_first_range(STM32MP_SYSCON_STGEN);
-
+ stgenc = STM32_STGEN_BASE;
cntfid0 = readl(stgenc + STGENC_CNTFID0);
p = stm32mp1_clk_get_parent(priv, STGEN_K);
rate = stm32mp1_clk_get(priv, p);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 4532ed3211..800584f512 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -271,13 +271,13 @@ config PIC32_GPIO
help
Say yes here to support Microchip PIC32 GPIOs.
-config STM32F7_GPIO
+config STM32_GPIO
bool "ST STM32 GPIO driver"
depends on DM_GPIO && (STM32 || ARCH_STM32MP)
default y
help
Device model driver support for STM32 GPIO controller. It should be
- usable on many stm32 families like stm32f4 & stm32H7.
+ usable on many stm32 families like stm32f4/f7/h7 and stm32mp1.
Tested on STM32F7.
config MVEBU_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 7337153e0e..4a8aa0ff6f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -47,7 +47,7 @@ obj-$(CONFIG_ADI_GPIO2) += adi_gpio2.o
obj-$(CONFIG_TCA642X) += tca642x.o
obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o
obj-$(CONFIG_LPC32XX_GPIO) += lpc32xx_gpio.o
-obj-$(CONFIG_STM32F7_GPIO) += stm32f7_gpio.o
+obj-$(CONFIG_STM32_GPIO) += stm32_gpio.o
obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o
obj-$(CONFIG_ZYNQ_GPIO) += zynq_gpio.o
obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o
diff --git a/drivers/gpio/stm32f7_gpio.c b/drivers/gpio/stm32_gpio.c
index 5c9f2fe64d..302a434947 100644
--- a/drivers/gpio/stm32f7_gpio.c
+++ b/drivers/gpio/stm32_gpio.c
@@ -27,7 +27,7 @@
int stm32_offset_to_index(struct udevice *dev, unsigned int offset)
{
struct stm32_gpio_priv *priv = dev_get_priv(dev);
- int idx = 0;
+ unsigned int idx = 0;
int i;
for (i = 0; i < STM32_GPIOS_PER_BANK; i++) {
@@ -210,15 +210,9 @@ static int gpio_stm32_probe(struct udevice *dev)
return 0;
}
-static const struct udevice_id stm32_gpio_ids[] = {
- { .compatible = "st,stm32-gpio" },
- { }
-};
-
U_BOOT_DRIVER(gpio_stm32) = {
.name = "gpio_stm32",
.id = UCLASS_GPIO,
- .of_match = stm32_gpio_ids,
.probe = gpio_stm32_probe,
#ifndef CONFIG_SPL_BUILD
.ops = &gpio_stm32_ops,
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c
index 50c4fd0de2..2b18735fea 100644
--- a/drivers/i2c/stm32f7_i2c.c
+++ b/drivers/i2c/stm32f7_i2c.c
@@ -519,13 +519,13 @@ static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup,
/* Compute possible values for PRESC, SCLDEL and SDADEL */
for (p = 0; p < STM32_PRESC_MAX; p++) {
for (l = 0; l < STM32_SCLDEL_MAX; l++) {
- u32 scldel = (l + 1) * (p + 1) * i2cclk;
+ int scldel = (l + 1) * (p + 1) * i2cclk;
if (scldel < scldel_min)
continue;
for (a = 0; a < STM32_SDADEL_MAX; a++) {
- u32 sdadel = (a * (p + 1) + 1) * i2cclk;
+ int sdadel = (a * (p + 1) + 1) * i2cclk;
if (((sdadel >= sdadel_min) &&
(sdadel <= sdadel_max)) &&
@@ -613,10 +613,12 @@ static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup,
if ((tscl >= clk_min) && (tscl <= clk_max) &&
(tscl_h >= i2c_specs[setup->speed].h_min) &&
(i2cclk < tscl_h)) {
- int clk_error = tscl - i2cbus;
+ u32 clk_error;
- if (clk_error < 0)
- clk_error = -clk_error;
+ if (tscl > i2cbus)
+ clk_error = tscl - i2cbus;
+ else
+ clk_error = i2cbus - tscl;
if (clk_error < clk_error_prev) {
clk_error_prev = clk_error;
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 2836ee4a7b..11bf5522db 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -24,6 +24,13 @@ config TEGRA_HSP
This enables support for the NVIDIA Tegra HSP Hw module, which
implements doorbells, mailboxes, semaphores, and shared interrupts.
+config STM32_IPCC
+ bool "Enable STM32 IPCC controller support"
+ depends on DM_MAILBOX && ARCH_STM32MP
+ help
+ This enables support for the STM32MP IPCC Hw module, which
+ implements doorbells between 2 processors.
+
config K3_SEC_PROXY
bool "Texas Instruments K3 Secure Proxy Driver"
depends on DM_MAILBOX && ARCH_K3
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index cd237698ba..a753cc4e68 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -6,5 +6,6 @@
obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox-uclass.o
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox.o
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox-test.o
+obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o
obj-$(CONFIG_TEGRA_HSP) += tegra-hsp.o
obj-$(CONFIG_K3_SEC_PROXY) += k3-sec-proxy.o
diff --git a/drivers/mailbox/stm32-ipcc.c b/drivers/mailbox/stm32-ipcc.c
new file mode 100644
index 0000000000..c3df9678a7
--- /dev/null
+++ b/drivers/mailbox/stm32-ipcc.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <mailbox-uclass.h>
+#include <asm/io.h>
+
+/*
+ * IPCC has one set of registers per CPU
+ * IPCC_PROC_OFFST allows to define cpu registers set base address
+ * according to the assigned proc_id.
+ */
+
+#define IPCC_PROC_OFFST 0x010
+
+#define IPCC_XSCR 0x008
+#define IPCC_XTOYSR 0x00c
+
+#define IPCC_HWCFGR 0x3f0
+#define IPCFGR_CHAN_MASK GENMASK(7, 0)
+
+#define RX_BIT_CHAN(chan) BIT(chan)
+#define TX_BIT_SHIFT 16
+#define TX_BIT_CHAN(chan) BIT(TX_BIT_SHIFT + (chan))
+
+#define STM32_MAX_PROCS 2
+
+struct stm32_ipcc {
+ void __iomem *reg_base;
+ void __iomem *reg_proc;
+ u32 proc_id;
+ u32 n_chans;
+};
+
+static int stm32_ipcc_request(struct mbox_chan *chan)
+{
+ struct stm32_ipcc *ipcc = dev_get_priv(chan->dev);
+
+ debug("%s(chan=%p)\n", __func__, chan);
+
+ if (chan->id >= ipcc->n_chans) {
+ debug("%s failed to request channel: %ld\n",
+ __func__, chan->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int stm32_ipcc_free(struct mbox_chan *chan)
+{
+ debug("%s(chan=%p)\n", __func__, chan);
+
+ return 0;
+}
+
+static int stm32_ipcc_send(struct mbox_chan *chan, const void *data)
+{
+ struct stm32_ipcc *ipcc = dev_get_priv(chan->dev);
+
+ debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
+
+ if (readl(ipcc->reg_proc + IPCC_XTOYSR) & BIT(chan->id))
+ return -EBUSY;
+
+ /* set channel n occupied */
+ setbits_le32(ipcc->reg_proc + IPCC_XSCR, TX_BIT_CHAN(chan->id));
+
+ return 0;
+}
+
+static int stm32_ipcc_recv(struct mbox_chan *chan, void *data)
+{
+ struct stm32_ipcc *ipcc = dev_get_priv(chan->dev);
+ u32 val;
+ int proc_offset;
+
+ debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
+
+ /* read 'channel occupied' status from other proc */
+ proc_offset = ipcc->proc_id ? -IPCC_PROC_OFFST : IPCC_PROC_OFFST;
+ val = readl(ipcc->reg_proc + proc_offset + IPCC_XTOYSR);
+
+ if (!(val & BIT(chan->id)))
+ return -ENODATA;
+
+ setbits_le32(ipcc->reg_proc + IPCC_XSCR, RX_BIT_CHAN(chan->id));
+
+ return 0;
+}
+
+static int stm32_ipcc_probe(struct udevice *dev)
+{
+ struct stm32_ipcc *ipcc = dev_get_priv(dev);
+ fdt_addr_t addr;
+ const fdt32_t *cell;
+ struct clk clk;
+ int len, ret;
+
+ debug("%s(dev=%p)\n", __func__, dev);
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ ipcc->reg_base = (void __iomem *)addr;
+
+ /* proc_id */
+ cell = dev_read_prop(dev, "st,proc_id", &len);
+ if (len < sizeof(fdt32_t)) {
+ dev_dbg(dev, "Missing st,proc_id\n");
+ return -EINVAL;
+ }
+
+ ipcc->proc_id = fdtdec_get_number(cell, 1);
+
+ if (ipcc->proc_id >= STM32_MAX_PROCS) {
+ dev_err(dev, "Invalid proc_id (%d)\n", ipcc->proc_id);
+ return -EINVAL;
+ }
+
+ ipcc->reg_proc = ipcc->reg_base + ipcc->proc_id * IPCC_PROC_OFFST;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return ret;
+
+ ret = clk_enable(&clk);
+ if (ret)
+ goto clk_free;
+
+ /* get channel number */
+ ipcc->n_chans = readl(ipcc->reg_base + IPCC_HWCFGR);
+ ipcc->n_chans &= IPCFGR_CHAN_MASK;
+
+ return 0;
+
+clk_free:
+ clk_free(&clk);
+
+ return ret;
+}
+
+static const struct udevice_id stm32_ipcc_ids[] = {
+ { .compatible = "st,stm32mp1-ipcc" },
+ { }
+};
+
+struct mbox_ops stm32_ipcc_mbox_ops = {
+ .request = stm32_ipcc_request,
+ .free = stm32_ipcc_free,
+ .send = stm32_ipcc_send,
+ .recv = stm32_ipcc_recv,
+};
+
+U_BOOT_DRIVER(stm32_ipcc) = {
+ .name = "stm32_ipcc",
+ .id = UCLASS_MAILBOX,
+ .of_match = stm32_ipcc_ids,
+ .probe = stm32_ipcc_probe,
+ .priv_auto_alloc_size = sizeof(struct stm32_ipcc),
+ .ops = &stm32_ipcc_mbox_ops,
+};
diff --git a/drivers/misc/stm32mp_fuse.c b/drivers/misc/stm32mp_fuse.c
index 8dc246b0db..801d946b77 100644
--- a/drivers/misc/stm32mp_fuse.c
+++ b/drivers/misc/stm32mp_fuse.c
@@ -5,6 +5,7 @@
#include <common.h>
#include <command.h>
+#include <fuse.h>
#include <misc.h>
#include <errno.h>
#include <dm/device.h>
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index b5180ea4a0..890ef358a0 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -46,6 +46,24 @@ config SPL_DM_MMC
if MMC
+config MMC_SPI
+ bool "Support for SPI-based MMC controller"
+ depends on DM_MMC && DM_SPI
+ help
+ This selects SPI-based MMC controllers.
+ If you have an MMC controller on a SPI bus, say Y here.
+
+ If unsure, say N.
+
+config MMC_SPI_CRC_ON
+ bool "Support CRC for SPI-based MMC controller"
+ depends on MMC_SPI
+ default y
+ help
+ This enables CRC for SPI-based MMC controllers.
+
+ If unsure, say N.
+
config ARM_PL180_MMCI
bool "ARM AMBA Multimedia Card Interface and compatible support"
depends on DM_MMC && OF_CONTROL
@@ -117,6 +135,18 @@ config SPL_MMC_UHS_SUPPORT
cards. The IO voltage must be switchable from 3.3v to 1.8v. The bus
frequency can go up to 208MHz (SDR104)
+config MMC_HS400_ES_SUPPORT
+ bool "enable HS400 Enhanced Strobe support"
+ help
+ The HS400 Enhanced Strobe mode is support by some eMMC. The bus
+ frequency is up to 200MHz. This mode does not tune the IO.
+
+config SPL_MMC_HS400_ES_SUPPORT
+ bool "enable HS400 Enhanced Strobe support in SPL"
+ help
+ The HS400 Enhanced Strobe mode is support by some eMMC. The bus
+ frequency is up to 200MHz. This mode does not tune the IO.
+
config MMC_HS400_SUPPORT
bool "enable HS400 support"
select MMC_HS200_SUPPORT
diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c
index c0d47ba378..43106dec75 100644
--- a/drivers/mmc/fsl_esdhc_imx.c
+++ b/drivers/mmc/fsl_esdhc_imx.c
@@ -101,7 +101,6 @@ struct fsl_esdhc_plat {
struct esdhc_soc_data {
u32 flags;
- u32 caps;
};
/**
@@ -146,7 +145,7 @@ struct fsl_esdhc_priv {
u32 tuning_start_tap;
u32 strobe_dll_delay_target;
u32 signal_voltage;
-#if IS_ENABLED(CONFIG_DM_REGULATOR)
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
struct udevice *vqmmc_dev;
struct udevice *vmmc_dev;
#endif
@@ -514,9 +513,9 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
/* Workaround for ESDHC errata ENGcm03648 */
if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
- int timeout = 6000;
+ int timeout = 50000;
- /* Poll on DATA0 line for cmd with busy signal for 600 ms */
+ /* Poll on DATA0 line for cmd with busy signal for 5000 ms */
while (timeout > 0 && !(esdhc_read32(&regs->prsstat) &
PRSSTAT_DAT0)) {
udelay(100);
@@ -704,6 +703,7 @@ static int esdhc_change_pinstate(struct udevice *dev)
case UHS_SDR104:
case MMC_HS_200:
case MMC_HS_400:
+ case MMC_HS_400_ES:
ret = pinctrl_select_state(dev, "state_200mhz");
break;
default:
@@ -774,6 +774,7 @@ static int esdhc_set_timing(struct mmc *mmc)
writel(mixctrl, &regs->mixctrl);
break;
case MMC_HS_400:
+ case MMC_HS_400_ES:
mixctrl |= MIX_CTRL_DDREN | MIX_CTRL_HS400_EN;
writel(mixctrl, &regs->mixctrl);
esdhc_set_strobe_dll(mmc);
@@ -1426,10 +1427,8 @@ static int fsl_esdhc_probe(struct udevice *dev)
priv->esdhc_regs = (struct fsl_esdhc *)addr;
priv->dev = dev;
priv->mode = -1;
- if (data) {
+ if (data)
priv->flags = data->flags;
- priv->caps = data->caps;
- }
val = dev_read_u32_default(dev, "bus-width", -1);
if (val == 8)
@@ -1490,9 +1489,6 @@ static int fsl_esdhc_probe(struct udevice *dev)
}
#endif
- if (fdt_get_property(fdt, node, "no-1-8-v", NULL))
- priv->caps &= ~(UHS_CAPS | MMC_MODE_HS200 | MMC_MODE_HS400);
-
/*
* TODO:
* Because lack of clk driver, if SDHC clk is not enabled,
@@ -1515,7 +1511,7 @@ static int fsl_esdhc_probe(struct udevice *dev)
init_clk_usdhc(dev->seq);
- if (IS_ENABLED(CONFIG_CLK)) {
+ if (CONFIG_IS_ENABLED(CLK)) {
/* Assigned clock already set clock */
ret = clk_get_by_name(dev, "per", &priv->per_clk);
if (ret) {
@@ -1543,6 +1539,10 @@ static int fsl_esdhc_probe(struct udevice *dev)
return ret;
}
+ ret = mmc_of_parse(dev, &plat->cfg);
+ if (ret)
+ return ret;
+
mmc = &plat->mmc;
mmc->cfg = &plat->cfg;
mmc->dev = dev;
@@ -1596,6 +1596,21 @@ static int fsl_esdhc_set_ios(struct udevice *dev)
return esdhc_set_ios_common(priv, &plat->mmc);
}
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+static int fsl_esdhc_set_enhanced_strobe(struct udevice *dev)
+{
+ struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+ struct fsl_esdhc *regs = priv->esdhc_regs;
+ u32 m;
+
+ m = readl(&regs->mixctrl);
+ m |= MIX_CTRL_HS400_ES;
+ writel(m, &regs->mixctrl);
+
+ return 0;
+}
+#endif
+
static const struct dm_mmc_ops fsl_esdhc_ops = {
.get_cd = fsl_esdhc_get_cd,
.send_cmd = fsl_esdhc_send_cmd,
@@ -1603,6 +1618,9 @@ static const struct dm_mmc_ops fsl_esdhc_ops = {
#ifdef MMC_SUPPORTS_TUNING
.execute_tuning = fsl_esdhc_execute_tuning,
#endif
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+ .set_enhanced_strobe = fsl_esdhc_set_enhanced_strobe,
+#endif
};
#endif
@@ -1610,8 +1628,12 @@ static struct esdhc_soc_data usdhc_imx7d_data = {
.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
| ESDHC_FLAG_HS400,
- .caps = UHS_CAPS | MMC_MODE_HS200 | MMC_MODE_DDR_52MHz |
- MMC_MODE_HS_52MHz | MMC_MODE_HS,
+};
+
+static struct esdhc_soc_data usdhc_imx8qm_data = {
+ .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING |
+ ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 |
+ ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES,
};
static const struct udevice_id fsl_esdhc_ids[] = {
@@ -1622,6 +1644,7 @@ static const struct udevice_id fsl_esdhc_ids[] = {
{ .compatible = "fsl,imx6q-usdhc", },
{ .compatible = "fsl,imx7d-usdhc", .data = (ulong)&usdhc_imx7d_data,},
{ .compatible = "fsl,imx7ulp-usdhc", },
+ { .compatible = "fsl,imx8qm-usdhc", .data = (ulong)&usdhc_imx8qm_data,},
{ .compatible = "fsl,esdhc", },
{ /* sentinel */ }
};
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index a9c8f335c1..551007905c 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -47,20 +47,6 @@ int mmc_set_ios(struct mmc *mmc)
return dm_mmc_set_ios(mmc->dev);
}
-void dm_mmc_send_init_stream(struct udevice *dev)
-{
- struct dm_mmc_ops *ops = mmc_get_ops(dev);
-
- if (ops->send_init_stream)
- ops->send_init_stream(dev);
-}
-
-void mmc_send_init_stream(struct mmc *mmc)
-{
- dm_mmc_send_init_stream(mmc->dev);
-}
-
-#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout)
{
struct dm_mmc_ops *ops = mmc_get_ops(dev);
@@ -74,7 +60,6 @@ int mmc_wait_dat0(struct mmc *mmc, int state, int timeout)
{
return dm_mmc_wait_dat0(mmc->dev, state, timeout);
}
-#endif
int dm_mmc_get_wp(struct udevice *dev)
{
@@ -120,6 +105,23 @@ int mmc_execute_tuning(struct mmc *mmc, uint opcode)
}
#endif
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+int dm_mmc_set_enhanced_strobe(struct udevice *dev)
+{
+ struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+ if (ops->set_enhanced_strobe)
+ return ops->set_enhanced_strobe(dev);
+
+ return -ENOTSUPP;
+}
+
+int mmc_set_enhanced_strobe(struct mmc *mmc)
+{
+ return dm_mmc_set_enhanced_strobe(mmc->dev);
+}
+#endif
+
int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)
{
int val;
@@ -170,6 +172,22 @@ int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)
cfg->host_caps |= MMC_CAP(MMC_HS_400);
if (dev_read_bool(dev, "mmc-hs400-1_2v"))
cfg->host_caps |= MMC_CAP(MMC_HS_400);
+ if (dev_read_bool(dev, "mmc-hs400-enhanced-strobe"))
+ cfg->host_caps |= MMC_CAP(MMC_HS_400_ES);
+
+ if (dev_read_bool(dev, "non-removable")) {
+ cfg->host_caps |= MMC_CAP_NONREMOVABLE;
+ } else {
+ if (dev_read_bool(dev, "cd-inverted"))
+ cfg->host_caps |= MMC_CAP_CD_ACTIVE_HIGH;
+ if (dev_read_bool(dev, "broken-cd"))
+ cfg->host_caps |= MMC_CAP_NEEDS_POLL;
+ }
+
+ if (dev_read_bool(dev, "no-1-8-v")) {
+ cfg->host_caps &= ~(UHS_CAPS | MMC_MODE_HS200 |
+ MMC_MODE_HS400 | MMC_MODE_HS400_ES);
+ }
return 0;
}
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 71b52c6cf2..c9aa13b409 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -21,6 +21,8 @@
#include <div64.h>
#include "mmc_private.h"
+#define DEFAULT_CMD6_TIMEOUT_MS 500
+
static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
static int mmc_power_cycle(struct mmc *mmc);
#if !CONFIG_IS_ENABLED(MMC_TINY)
@@ -29,12 +31,10 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps);
#if !CONFIG_IS_ENABLED(DM_MMC)
-#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout)
{
return -ENOSYS;
}
-#endif
__weak int board_mmc_getwp(struct mmc *mmc)
{
@@ -148,6 +148,7 @@ const char *mmc_mode_name(enum bus_mode mode)
[MMC_DDR_52] = "MMC DDR52 (52MHz)",
[MMC_HS_200] = "HS200 (200MHz)",
[MMC_HS_400] = "HS400 (200MHz)",
+ [MMC_HS_400_ES] = "HS400ES (200MHz)",
};
if (mode >= MMC_MODES_END)
@@ -173,6 +174,7 @@ static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode)
[UHS_SDR104] = 208000000,
[MMC_HS_200] = 200000000,
[MMC_HS_400] = 200000000,
+ [MMC_HS_400_ES] = 200000000,
};
if (mode == MMC_LEGACY)
@@ -206,7 +208,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
}
#endif
-int mmc_send_status(struct mmc *mmc, int timeout)
+int mmc_send_status(struct mmc *mmc, unsigned int *status)
{
struct mmc_cmd cmd;
int err, retries = 5;
@@ -216,23 +218,43 @@ int mmc_send_status(struct mmc *mmc, int timeout)
if (!mmc_host_is_spi(mmc))
cmd.cmdarg = mmc->rca << 16;
- while (1) {
+ while (retries--) {
err = mmc_send_cmd(mmc, &cmd, NULL);
if (!err) {
- if ((cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) &&
- (cmd.response[0] & MMC_STATUS_CURR_STATE) !=
- MMC_STATE_PRG)
- break;
+ mmc_trace_state(mmc, &cmd);
+ *status = cmd.response[0];
+ return 0;
+ }
+ }
+ mmc_trace_state(mmc, &cmd);
+ return -ECOMM;
+}
+
+int mmc_poll_for_busy(struct mmc *mmc, int timeout)
+{
+ unsigned int status;
+ int err;
+
+ err = mmc_wait_dat0(mmc, 1, timeout);
+ if (err != -ENOSYS)
+ return err;
- if (cmd.response[0] & MMC_STATUS_MASK) {
+ while (1) {
+ err = mmc_send_status(mmc, &status);
+ if (err)
+ return err;
+
+ if ((status & MMC_STATUS_RDY_FOR_DATA) &&
+ (status & MMC_STATUS_CURR_STATE) !=
+ MMC_STATE_PRG)
+ break;
+
+ if (status & MMC_STATUS_MASK) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
- pr_err("Status Error: 0x%08x\n",
- cmd.response[0]);
+ pr_err("Status Error: 0x%08x\n", status);
#endif
- return -ECOMM;
- }
- } else if (--retries < 0)
- return err;
+ return -ECOMM;
+ }
if (timeout-- <= 0)
break;
@@ -240,7 +262,6 @@ int mmc_send_status(struct mmc *mmc, int timeout)
udelay(1000);
}
- mmc_trace_state(mmc, &cmd);
if (timeout <= 0) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
pr_err("Timeout waiting card ready\n");
@@ -727,36 +748,67 @@ static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
bool send_status)
{
+ unsigned int status, start;
struct mmc_cmd cmd;
- int timeout = 1000;
+ int timeout = DEFAULT_CMD6_TIMEOUT_MS;
+ bool is_part_switch = (set == EXT_CSD_CMD_SET_NORMAL) &&
+ (index == EXT_CSD_PART_CONF);
int retries = 3;
int ret;
+ if (mmc->gen_cmd6_time)
+ timeout = mmc->gen_cmd6_time * 10;
+
+ if (is_part_switch && mmc->part_switch_time)
+ timeout = mmc->part_switch_time * 10;
+
cmd.cmdidx = MMC_CMD_SWITCH;
cmd.resp_type = MMC_RSP_R1b;
cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
(index << 16) |
(value << 8);
- while (retries > 0) {
+ do {
ret = mmc_send_cmd(mmc, &cmd, NULL);
+ } while (ret && retries-- > 0);
- if (ret) {
- retries--;
- continue;
- }
+ if (ret)
+ return ret;
- if (!send_status) {
- mdelay(50);
- return 0;
- }
+ start = get_timer(0);
- /* Waiting for the ready status */
- return mmc_send_status(mmc, timeout);
- }
+ /* poll dat0 for rdy/buys status */
+ ret = mmc_wait_dat0(mmc, 1, timeout);
+ if (ret && ret != -ENOSYS)
+ return ret;
- return ret;
+ /*
+ * In cases when not allowed to poll by using CMD13 or because we aren't
+ * capable of polling by using mmc_wait_dat0, then rely on waiting the
+ * stated timeout to be sufficient.
+ */
+ if (ret == -ENOSYS && !send_status)
+ mdelay(timeout);
+
+ /* Finally wait until the card is ready or indicates a failure
+ * to switch. It doesn't hurt to use CMD13 here even if send_status
+ * is false, because by now (after 'timeout' ms) the bus should be
+ * reliable.
+ */
+ do {
+ ret = mmc_send_status(mmc, &status);
+
+ if (!ret && (status & MMC_STATUS_SWITCH_ERROR)) {
+ pr_debug("switch failed %d/%d/0x%x !\n", set, index,
+ value);
+ return -EIO;
+ }
+ if (!ret && (status & MMC_STATUS_RDY_FOR_DATA))
+ return 0;
+ udelay(100);
+ } while (get_timer(start) < timeout);
+ return -ETIMEDOUT;
}
int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
@@ -789,6 +841,11 @@ static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode,
speed_bits = EXT_CSD_TIMING_HS400;
break;
#endif
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+ case MMC_HS_400_ES:
+ speed_bits = EXT_CSD_TIMING_HS400;
+ break;
+#endif
case MMC_LEGACY:
speed_bits = EXT_CSD_TIMING_LEGACY;
break;
@@ -859,7 +916,8 @@ static int mmc_get_capabilities(struct mmc *mmc)
mmc->card_caps |= MMC_MODE_HS200;
}
#endif
-#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) || \
+ CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
if (cardtype & (EXT_CSD_CARD_TYPE_HS400_1_2V |
EXT_CSD_CARD_TYPE_HS400_1_8V)) {
mmc->card_caps |= MMC_MODE_HS400;
@@ -873,6 +931,13 @@ static int mmc_get_capabilities(struct mmc *mmc)
if (cardtype & EXT_CSD_CARD_TYPE_26)
mmc->card_caps |= MMC_MODE_HS;
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+ if (ext_csd[EXT_CSD_STROBE_SUPPORT] &&
+ (mmc->card_caps & MMC_MODE_HS400)) {
+ mmc->card_caps |= MMC_MODE_HS400_ES;
+ }
+#endif
+
return 0;
}
#endif
@@ -905,49 +970,17 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num)
return 0;
}
-#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
-static int mmc_boot_part_access_chk(struct mmc *mmc, unsigned int part_num)
-{
- int forbidden = 0;
- bool change = false;
-
- if (part_num & PART_ACCESS_MASK)
- forbidden = MMC_CAP(MMC_HS_200) | MMC_CAP(MMC_HS_400);
-
- if (MMC_CAP(mmc->selected_mode) & forbidden) {
- pr_debug("selected mode (%s) is forbidden for part %d\n",
- mmc_mode_name(mmc->selected_mode), part_num);
- change = true;
- } else if (mmc->selected_mode != mmc->best_mode) {
- pr_debug("selected mode is not optimal\n");
- change = true;
- }
-
- if (change)
- return mmc_select_mode_and_width(mmc,
- mmc->card_caps & ~forbidden);
-
- return 0;
-}
-#else
-static inline int mmc_boot_part_access_chk(struct mmc *mmc,
- unsigned int part_num)
-{
- return 0;
-}
-#endif
-
int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
{
int ret;
+ int retry = 3;
- ret = mmc_boot_part_access_chk(mmc, part_num);
- if (ret)
- return ret;
-
- ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
- (mmc->part_config & ~PART_ACCESS_MASK)
- | (part_num & PART_ACCESS_MASK));
+ do {
+ ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_PART_CONF,
+ (mmc->part_config & ~PART_ACCESS_MASK)
+ | (part_num & PART_ACCESS_MASK));
+ } while (ret && retry--);
/*
* Set the capacity if the switch succeeded or was intended
@@ -1504,10 +1537,6 @@ static int mmc_execute_tuning(struct mmc *mmc, uint opcode)
}
#endif
-static void mmc_send_init_stream(struct mmc *mmc)
-{
-}
-
static int mmc_set_ios(struct mmc *mmc)
{
int ret = 0;
@@ -1672,6 +1701,13 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
mmc_dump_capabilities("host", mmc->host_caps);
#endif
+ if (mmc_host_is_spi(mmc)) {
+ mmc_set_bus_width(mmc, 1);
+ mmc_select_mode(mmc, SD_LEGACY);
+ mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
+ return 0;
+ }
+
/* Restrict card's capabilities by what the host can do */
caps = card_caps & mmc->host_caps;
@@ -1778,6 +1814,7 @@ static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
u32 card_mask = 0;
switch (mode) {
+ case MMC_HS_400_ES:
case MMC_HS_400:
case MMC_HS_200:
if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_8V |
@@ -1820,6 +1857,12 @@ static inline int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
#endif
static const struct mode_width_tuning mmc_modes_by_pref[] = {
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+ {
+ .mode = MMC_HS_400_ES,
+ .widths = MMC_MODE_8BIT,
+ },
+#endif
#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
{
.mode = MMC_HS_400,
@@ -1917,6 +1960,47 @@ static int mmc_select_hs400(struct mmc *mmc)
}
#endif
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+#if !CONFIG_IS_ENABLED(DM_MMC)
+static int mmc_set_enhanced_strobe(struct mmc *mmc)
+{
+ return -ENOTSUPP;
+}
+#endif
+static int mmc_select_hs400es(struct mmc *mmc)
+{
+ int err;
+
+ err = mmc_set_card_speed(mmc, MMC_HS, true);
+ if (err)
+ return err;
+
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
+ EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG |
+ EXT_CSD_BUS_WIDTH_STROBE);
+ if (err) {
+ printf("switch to bus width for hs400 failed\n");
+ return err;
+ }
+ /* TODO: driver strength */
+ err = mmc_set_card_speed(mmc, MMC_HS_400_ES, false);
+ if (err)
+ return err;
+
+ mmc_select_mode(mmc, MMC_HS_400_ES);
+ err = mmc_set_clock(mmc, mmc->tran_speed, false);
+ if (err)
+ return err;
+
+ return mmc_set_enhanced_strobe(mmc);
+}
+#else
+static int mmc_select_hs400es(struct mmc *mmc)
+{
+ return -ENOTSUPP;
+}
+#endif
+
#define for_each_supported_width(caps, ddr, ecbv) \
for (ecbv = ext_csd_bus_width;\
ecbv < ext_csd_bus_width + ARRAY_SIZE(ext_csd_bus_width);\
@@ -1934,6 +2018,13 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
mmc_dump_capabilities("host", mmc->host_caps);
#endif
+ if (mmc_host_is_spi(mmc)) {
+ mmc_set_bus_width(mmc, 1);
+ mmc_select_mode(mmc, MMC_LEGACY);
+ mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE);
+ return 0;
+ }
+
/* Restrict card's capabilities by what the host can do */
card_caps &= mmc->host_caps;
@@ -1988,6 +2079,13 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
printf("Select HS400 failed %d\n", err);
goto error;
}
+ } else if (mwt->mode == MMC_HS_400_ES) {
+ err = mmc_select_hs400es(mmc);
+ if (err) {
+ printf("Select HS400ES failed %d\n",
+ err);
+ goto error;
+ }
} else {
/* configure the bus speed (card) */
err = mmc_set_card_speed(mmc, mwt->mode, false);
@@ -2122,6 +2220,9 @@ static int mmc_startup_v4(struct mmc *mmc)
mmc->capacity_user = capacity;
}
+ if (mmc->version >= MMC_VERSION_4_5)
+ mmc->gen_cmd6_time = ext_csd[EXT_CSD_GENERIC_CMD6_TIME];
+
/* The partition data may be non-zero but it is only
* effective if PARTITION_SETTING_COMPLETED is set in
* EXT_CSD, so ignore any data if this bit is not set,
@@ -2131,6 +2232,11 @@ static int mmc_startup_v4(struct mmc *mmc)
part_completed = !!(ext_csd[EXT_CSD_PARTITION_SETTING] &
EXT_CSD_PARTITION_SETTING_COMPLETED);
+ mmc->part_switch_time = ext_csd[EXT_CSD_PART_SWITCH_TIME];
+ /* Some eMMC set the value too low so set a minimum */
+ if (mmc->part_switch_time < MMC_MIN_PART_SWITCH_TIME && mmc->part_switch_time)
+ mmc->part_switch_time = MMC_MIN_PART_SWITCH_TIME;
+
/* store the partition info of emmc */
mmc->part_support = ext_csd[EXT_CSD_PARTITIONING_SUPPORT];
if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) ||
@@ -2664,7 +2770,6 @@ int mmc_get_op_cond(struct mmc *mmc)
retry:
mmc_set_initial_state(mmc);
- mmc_send_init_stream(mmc);
/* Reset the Card */
err = mmc_go_idle(mmc);
diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h
index f49b6eb573..35170d03ab 100644
--- a/drivers/mmc/mmc_private.h
+++ b/drivers/mmc/mmc_private.h
@@ -11,10 +11,11 @@
#include <mmc.h>
-extern int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
- struct mmc_data *data);
-extern int mmc_send_status(struct mmc *mmc, int timeout);
-extern int mmc_set_blocklen(struct mmc *mmc, int len);
+int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data);
+int mmc_send_status(struct mmc *mmc, unsigned int *status);
+int mmc_poll_for_busy(struct mmc *mmc, int timeout);
+
+int mmc_set_blocklen(struct mmc *mmc, int len);
#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
void mmc_adapter_card_type_ident(void);
#endif
diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index 4f57990d9c..f3d687ae80 100644
--- a/drivers/mmc/mmc_spi.c
+++ b/drivers/mmc/mmc_spi.c
@@ -2,6 +2,8 @@
* generic mmc spi driver
*
* Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
+ * Copyright 2019 Bhargav Shah <bhargavshah1988@gmail.com>
+ *
* Licensed under the GPL-2 or later.
*/
#include <common.h>
@@ -9,21 +11,23 @@
#include <malloc.h>
#include <part.h>
#include <mmc.h>
-#include <spi.h>
+#include <stdlib.h>
#include <u-boot/crc.h>
#include <linux/crc7.h>
#include <asm/byteorder.h>
+#include <dm.h>
+#include <spi.h>
/* MMC/SD in SPI mode reports R1 status always */
-#define R1_SPI_IDLE (1 << 0)
-#define R1_SPI_ERASE_RESET (1 << 1)
-#define R1_SPI_ILLEGAL_COMMAND (1 << 2)
-#define R1_SPI_COM_CRC (1 << 3)
-#define R1_SPI_ERASE_SEQ (1 << 4)
-#define R1_SPI_ADDRESS (1 << 5)
-#define R1_SPI_PARAMETER (1 << 6)
+#define R1_SPI_IDLE BIT(0)
+#define R1_SPI_ERASE_RESET BIT(1)
+#define R1_SPI_ILLEGAL_COMMAND BIT(2)
+#define R1_SPI_COM_CRC BIT(3)
+#define R1_SPI_ERASE_SEQ BIT(4)
+#define R1_SPI_ADDRESS BIT(5)
+#define R1_SPI_PARAMETER BIT(6)
/* R1 bit 7 is always zero, reuse this bit for error */
-#define R1_SPI_ERROR (1 << 7)
+#define R1_SPI_ERROR BIT(7)
/* Response tokens used to ack each block written: */
#define SPI_MMC_RESPONSE_CODE(x) ((x) & 0x1f)
@@ -34,28 +38,45 @@
/* Read and write blocks start with these tokens and end with crc;
* on error, read tokens act like a subset of R2_SPI_* values.
*/
-#define SPI_TOKEN_SINGLE 0xfe /* single block r/w, multiblock read */
-#define SPI_TOKEN_MULTI_WRITE 0xfc /* multiblock write */
-#define SPI_TOKEN_STOP_TRAN 0xfd /* terminate multiblock write */
+/* single block write multiblock read */
+#define SPI_TOKEN_SINGLE 0xfe
+/* multiblock write */
+#define SPI_TOKEN_MULTI_WRITE 0xfc
+/* terminate multiblock write */
+#define SPI_TOKEN_STOP_TRAN 0xfd
/* MMC SPI commands start with a start bit "0" and a transmit bit "1" */
-#define MMC_SPI_CMD(x) (0x40 | (x & 0x3f))
+#define MMC_SPI_CMD(x) (0x40 | (x))
/* bus capability */
-#define MMC_SPI_VOLTAGE (MMC_VDD_32_33 | MMC_VDD_33_34)
-#define MMC_SPI_MIN_CLOCK 400000 /* 400KHz to meet MMC spec */
+#define MMC_SPI_VOLTAGE (MMC_VDD_32_33 | MMC_VDD_33_34)
+#define MMC_SPI_MIN_CLOCK 400000 /* 400KHz to meet MMC spec */
+#define MMC_SPI_MAX_CLOCK 25000000 /* SD/MMC legacy speed */
/* timeout value */
-#define CTOUT 8
-#define RTOUT 3000000 /* 1 sec */
-#define WTOUT 3000000 /* 1 sec */
+#define CMD_TIMEOUT 8
+#define READ_TIMEOUT 3000000 /* 1 sec */
+#define WRITE_TIMEOUT 3000000 /* 1 sec */
-static uint mmc_spi_sendcmd(struct mmc *mmc, ushort cmdidx, u32 cmdarg)
+struct mmc_spi_priv {
+ struct spi_slave *spi;
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+
+static int mmc_spi_sendcmd(struct udevice *dev,
+ ushort cmdidx, u32 cmdarg, u32 resp_type,
+ u8 *resp, u32 resp_size,
+ bool resp_match, u8 resp_match_value)
{
- struct spi_slave *spi = mmc->priv;
- u8 cmdo[7];
- u8 r1;
- int i;
+ int i, rpos = 0, ret = 0;
+ u8 cmdo[7], r;
+
+ debug("%s: cmd%d cmdarg=0x%x resp_type=0x%x "
+ "resp_size=%d resp_match=%d resp_match_value=0x%x\n",
+ __func__, cmdidx, cmdarg, resp_type,
+ resp_size, resp_match, resp_match_value);
+
cmdo[0] = 0xff;
cmdo[1] = MMC_SPI_CMD(cmdidx);
cmdo[2] = cmdarg >> 24;
@@ -63,37 +84,79 @@ static uint mmc_spi_sendcmd(struct mmc *mmc, ushort cmdidx, u32 cmdarg)
cmdo[4] = cmdarg >> 8;
cmdo[5] = cmdarg;
cmdo[6] = (crc7(0, &cmdo[1], 5) << 1) | 0x01;
- spi_xfer(spi, sizeof(cmdo) * 8, cmdo, NULL, 0);
- for (i = 0; i < CTOUT; i++) {
- spi_xfer(spi, 1 * 8, NULL, &r1, 0);
- if (i && (r1 & 0x80) == 0) /* r1 response */
- break;
+ ret = dm_spi_xfer(dev, sizeof(cmdo) * 8, cmdo, NULL, 0);
+ if (ret)
+ return ret;
+
+ ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
+ if (ret)
+ return ret;
+
+ if (!resp || !resp_size)
+ return 0;
+
+ debug("%s: cmd%d", __func__, cmdidx);
+
+ if (resp_match) {
+ r = ~resp_match_value;
+ i = CMD_TIMEOUT;
+ while (i--) {
+ ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
+ if (ret)
+ return ret;
+ debug(" resp%d=0x%x", rpos, r);
+ rpos++;
+ if (r == resp_match_value)
+ break;
+ }
+ if (!i && (r != resp_match_value))
+ return -ETIMEDOUT;
+ }
+
+ for (i = 0; i < resp_size; i++) {
+ if (i == 0 && resp_match) {
+ resp[i] = resp_match_value;
+ continue;
+ }
+ ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
+ if (ret)
+ return ret;
+ debug(" resp%d=0x%x", rpos, r);
+ rpos++;
+ resp[i] = r;
}
- debug("%s:cmd%d resp%d %x\n", __func__, cmdidx, i, r1);
- return r1;
+
+ debug("\n");
+
+ return 0;
}
-static uint mmc_spi_readdata(struct mmc *mmc, void *xbuf,
- u32 bcnt, u32 bsize)
+static int mmc_spi_readdata(struct udevice *dev,
+ void *xbuf, u32 bcnt, u32 bsize)
{
- struct spi_slave *spi = mmc->priv;
- u8 *buf = xbuf;
- u8 r1;
u16 crc;
- int i;
+ u8 *buf = xbuf, r1;
+ int i, ret = 0;
+
while (bcnt--) {
- for (i = 0; i < RTOUT; i++) {
- spi_xfer(spi, 1 * 8, NULL, &r1, 0);
- if (r1 != 0xff) /* data token */
+ for (i = 0; i < READ_TIMEOUT; i++) {
+ ret = dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
+ if (ret)
+ return ret;
+ if (r1 == SPI_TOKEN_SINGLE)
break;
}
- debug("%s:tok%d %x\n", __func__, i, r1);
+ debug("%s: data tok%d 0x%x\n", __func__, i, r1);
if (r1 == SPI_TOKEN_SINGLE) {
- spi_xfer(spi, bsize * 8, NULL, buf, 0);
- spi_xfer(spi, 2 * 8, NULL, &crc, 0);
+ ret = dm_spi_xfer(dev, bsize * 8, NULL, buf, 0);
+ if (ret)
+ return ret;
+ ret = dm_spi_xfer(dev, 2 * 8, NULL, &crc, 0);
+ if (ret)
+ return ret;
#ifdef CONFIG_MMC_SPI_CRC_ON
- if (be_to_cpu16(crc16_ccitt(0, buf, bsize)) != crc) {
- debug("%s: CRC error\n", mmc->cfg->name);
+ if (be16_to_cpu(crc16_ccitt(0, buf, bsize)) != crc) {
+ debug("%s: data crc error\n", __func__);
r1 = R1_SPI_COM_CRC;
break;
}
@@ -105,48 +168,56 @@ static uint mmc_spi_readdata(struct mmc *mmc, void *xbuf,
}
buf += bsize;
}
- return r1;
+
+ if (r1 & R1_SPI_COM_CRC)
+ ret = -ECOMM;
+ else if (r1) /* other errors */
+ ret = -ETIMEDOUT;
+
+ return ret;
}
-static uint mmc_spi_writedata(struct mmc *mmc, const void *xbuf,
- u32 bcnt, u32 bsize, int multi)
+static int mmc_spi_writedata(struct udevice *dev, const void *xbuf,
+ u32 bcnt, u32 bsize, int multi)
{
- struct spi_slave *spi = mmc->priv;
const u8 *buf = xbuf;
- u8 r1;
+ u8 r1, tok[2];
u16 crc;
- u8 tok[2];
- int i;
+ int i, ret = 0;
+
tok[0] = 0xff;
tok[1] = multi ? SPI_TOKEN_MULTI_WRITE : SPI_TOKEN_SINGLE;
+
while (bcnt--) {
#ifdef CONFIG_MMC_SPI_CRC_ON
crc = cpu_to_be16(crc16_ccitt(0, (u8 *)buf, bsize));
#endif
- spi_xfer(spi, 2 * 8, tok, NULL, 0);
- spi_xfer(spi, bsize * 8, buf, NULL, 0);
- spi_xfer(spi, 2 * 8, &crc, NULL, 0);
- for (i = 0; i < CTOUT; i++) {
- spi_xfer(spi, 1 * 8, NULL, &r1, 0);
+ dm_spi_xfer(dev, 2 * 8, tok, NULL, 0);
+ dm_spi_xfer(dev, bsize * 8, buf, NULL, 0);
+ dm_spi_xfer(dev, 2 * 8, &crc, NULL, 0);
+ for (i = 0; i < CMD_TIMEOUT; i++) {
+ dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
if ((r1 & 0x10) == 0) /* response token */
break;
}
- debug("%s:tok%d %x\n", __func__, i, r1);
+ debug("%s: data tok%d 0x%x\n", __func__, i, r1);
if (SPI_MMC_RESPONSE_CODE(r1) == SPI_RESPONSE_ACCEPTED) {
- for (i = 0; i < WTOUT; i++) { /* wait busy */
- spi_xfer(spi, 1 * 8, NULL, &r1, 0);
+ debug("%s: data accepted\n", __func__);
+ for (i = 0; i < WRITE_TIMEOUT; i++) { /* wait busy */
+ dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
if (i && r1 == 0xff) {
r1 = 0;
break;
}
}
- if (i == WTOUT) {
- debug("%s:wtout %x\n", __func__, r1);
+ if (i == WRITE_TIMEOUT) {
+ debug("%s: data write timeout 0x%x\n",
+ __func__, r1);
r1 = R1_SPI_ERROR;
break;
}
} else {
- debug("%s: err %x\n", __func__, r1);
+ debug("%s: data error 0x%x\n", __func__, r1);
r1 = R1_SPI_COM_CRC;
break;
}
@@ -154,140 +225,204 @@ static uint mmc_spi_writedata(struct mmc *mmc, const void *xbuf,
}
if (multi && bcnt == -1) { /* stop multi write */
tok[1] = SPI_TOKEN_STOP_TRAN;
- spi_xfer(spi, 2 * 8, tok, NULL, 0);
- for (i = 0; i < WTOUT; i++) { /* wait busy */
- spi_xfer(spi, 1 * 8, NULL, &r1, 0);
+ dm_spi_xfer(dev, 2 * 8, tok, NULL, 0);
+ for (i = 0; i < WRITE_TIMEOUT; i++) { /* wait busy */
+ dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
if (i && r1 == 0xff) {
r1 = 0;
break;
}
}
- if (i == WTOUT) {
- debug("%s:wstop %x\n", __func__, r1);
+ if (i == WRITE_TIMEOUT) {
+ debug("%s: data write timeout 0x%x\n", __func__, r1);
r1 = R1_SPI_ERROR;
}
}
- return r1;
-}
-static int mmc_spi_request(struct mmc *mmc, struct mmc_cmd *cmd,
- struct mmc_data *data)
-{
- struct spi_slave *spi = mmc->priv;
- u8 r1;
- int i;
- int ret = 0;
- debug("%s:cmd%d %x %x\n", __func__,
- cmd->cmdidx, cmd->resp_type, cmd->cmdarg);
- spi_claim_bus(spi);
- spi_cs_activate(spi);
- r1 = mmc_spi_sendcmd(mmc, cmd->cmdidx, cmd->cmdarg);
- if (r1 == 0xff) { /* no response */
- ret = -ENOMEDIUM;
- goto done;
- } else if (r1 & R1_SPI_COM_CRC) {
+ if (r1 & R1_SPI_COM_CRC)
ret = -ECOMM;
- goto done;
- } else if (r1 & ~R1_SPI_IDLE) { /* other errors */
+ else if (r1) /* other errors */
ret = -ETIMEDOUT;
+
+ return ret;
+}
+
+static int dm_mmc_spi_set_ios(struct udevice *dev)
+{
+ return 0;
+}
+
+static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ int i, multi, ret = 0;
+ u8 *resp = NULL;
+ u32 resp_size = 0;
+ bool resp_match = false;
+ u8 resp8 = 0, resp40[5] = { 0 }, resp_match_value = 0;
+
+ dm_spi_claim_bus(dev);
+
+ for (i = 0; i < 4; i++)
+ cmd->response[i] = 0;
+
+ switch (cmd->cmdidx) {
+ case SD_CMD_APP_SEND_OP_COND:
+ case MMC_CMD_SEND_OP_COND:
+ resp = &resp8;
+ resp_size = sizeof(resp8);
+ cmd->cmdarg = 0x40000000;
+ break;
+ case SD_CMD_SEND_IF_COND:
+ resp = (u8 *)&resp40[0];
+ resp_size = sizeof(resp40);
+ resp_match = true;
+ resp_match_value = R1_SPI_IDLE;
+ break;
+ case MMC_CMD_SPI_READ_OCR:
+ resp = (u8 *)&resp40[0];
+ resp_size = sizeof(resp40);
+ break;
+ case MMC_CMD_SEND_STATUS:
+ case MMC_CMD_SET_BLOCKLEN:
+ case MMC_CMD_SPI_CRC_ON_OFF:
+ case MMC_CMD_STOP_TRANSMISSION:
+ resp = &resp8;
+ resp_size = sizeof(resp8);
+ resp_match = true;
+ resp_match_value = 0x0;
+ break;
+ case MMC_CMD_SEND_CSD:
+ case MMC_CMD_SEND_CID:
+ case MMC_CMD_READ_SINGLE_BLOCK:
+ case MMC_CMD_READ_MULTIPLE_BLOCK:
+ case MMC_CMD_WRITE_SINGLE_BLOCK:
+ case MMC_CMD_WRITE_MULTIPLE_BLOCK:
+ break;
+ default:
+ resp = &resp8;
+ resp_size = sizeof(resp8);
+ resp_match = true;
+ resp_match_value = R1_SPI_IDLE;
+ break;
+ };
+
+ ret = mmc_spi_sendcmd(dev, cmd->cmdidx, cmd->cmdarg, cmd->resp_type,
+ resp, resp_size, resp_match, resp_match_value);
+ if (ret)
goto done;
- } else if (cmd->resp_type == MMC_RSP_R2) {
- r1 = mmc_spi_readdata(mmc, cmd->response, 1, 16);
+
+ switch (cmd->cmdidx) {
+ case SD_CMD_APP_SEND_OP_COND:
+ case MMC_CMD_SEND_OP_COND:
+ cmd->response[0] = (resp8 & R1_SPI_IDLE) ? 0 : OCR_BUSY;
+ break;
+ case SD_CMD_SEND_IF_COND:
+ case MMC_CMD_SPI_READ_OCR:
+ cmd->response[0] = resp40[4];
+ cmd->response[0] |= (uint)resp40[3] << 8;
+ cmd->response[0] |= (uint)resp40[2] << 16;
+ cmd->response[0] |= (uint)resp40[1] << 24;
+ break;
+ case MMC_CMD_SEND_STATUS:
+ cmd->response[0] = (resp8 & 0xff) ?
+ MMC_STATUS_ERROR : MMC_STATUS_RDY_FOR_DATA;
+ break;
+ case MMC_CMD_SEND_CID:
+ case MMC_CMD_SEND_CSD:
+ ret = mmc_spi_readdata(dev, cmd->response, 1, 16);
+ if (ret)
+ return ret;
for (i = 0; i < 4; i++)
- cmd->response[i] = be32_to_cpu(cmd->response[i]);
- debug("r128 %x %x %x %x\n", cmd->response[0], cmd->response[1],
- cmd->response[2], cmd->response[3]);
- } else if (!data) {
- switch (cmd->cmdidx) {
- case SD_CMD_APP_SEND_OP_COND:
- case MMC_CMD_SEND_OP_COND:
- cmd->response[0] = (r1 & R1_SPI_IDLE) ? 0 : OCR_BUSY;
- break;
- case SD_CMD_SEND_IF_COND:
- case MMC_CMD_SPI_READ_OCR:
- spi_xfer(spi, 4 * 8, NULL, cmd->response, 0);
- cmd->response[0] = be32_to_cpu(cmd->response[0]);
- debug("r32 %x\n", cmd->response[0]);
- break;
- case MMC_CMD_SEND_STATUS:
- spi_xfer(spi, 1 * 8, NULL, cmd->response, 0);
- cmd->response[0] = (cmd->response[0] & 0xff) ?
- MMC_STATUS_ERROR : MMC_STATUS_RDY_FOR_DATA;
- break;
- }
- } else {
- debug("%s:data %x %x %x\n", __func__,
- data->flags, data->blocks, data->blocksize);
+ cmd->response[i] =
+ cpu_to_be32(cmd->response[i]);
+ break;
+ default:
+ cmd->response[0] = resp8;
+ break;
+ }
+
+ debug("%s: cmd%d resp0=0x%x resp1=0x%x resp2=0x%x resp3=0x%x\n",
+ __func__, cmd->cmdidx, cmd->response[0], cmd->response[1],
+ cmd->response[2], cmd->response[3]);
+
+ if (data) {
+ debug("%s: data flags=0x%x blocks=%d block_size=%d\n",
+ __func__, data->flags, data->blocks, data->blocksize);
+ multi = (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK);
if (data->flags == MMC_DATA_READ)
- r1 = mmc_spi_readdata(mmc, data->dest,
- data->blocks, data->blocksize);
+ ret = mmc_spi_readdata(dev, data->dest,
+ data->blocks, data->blocksize);
else if (data->flags == MMC_DATA_WRITE)
- r1 = mmc_spi_writedata(mmc, data->src,
- data->blocks, data->blocksize,
- (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK));
- if (r1 & R1_SPI_COM_CRC)
- ret = -ECOMM;
- else if (r1) /* other errors */
- ret = -ETIMEDOUT;
+ ret = mmc_spi_writedata(dev, data->src,
+ data->blocks, data->blocksize,
+ multi);
}
+
done:
- spi_cs_deactivate(spi);
- spi_release_bus(spi);
+ dm_spi_release_bus(dev);
+
return ret;
}
-static int mmc_spi_set_ios(struct mmc *mmc)
+static int mmc_spi_probe(struct udevice *dev)
{
- struct spi_slave *spi = mmc->priv;
+ struct mmc_spi_priv *priv = dev_get_priv(dev);
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ char *name;
+
+ priv->spi = dev_get_parent_priv(dev);
+ if (!priv->spi->max_hz)
+ priv->spi->max_hz = MMC_SPI_MAX_CLOCK;
+ priv->spi->speed = 0;
+ priv->spi->mode = SPI_MODE_0;
+ priv->spi->wordlen = 8;
+
+ name = malloc(strlen(dev->parent->name) + strlen(dev->name) + 4);
+ if (!name)
+ return -ENOMEM;
+ sprintf(name, "%s:%s", dev->parent->name, dev->name);
+
+ priv->cfg.name = name;
+ priv->cfg.host_caps = MMC_MODE_SPI;
+ priv->cfg.voltages = MMC_SPI_VOLTAGE;
+ priv->cfg.f_min = MMC_SPI_MIN_CLOCK;
+ priv->cfg.f_max = priv->spi->max_hz;
+ priv->cfg.part_type = PART_TYPE_DOS;
+ priv->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+ priv->mmc.cfg = &priv->cfg;
+ priv->mmc.priv = priv;
+ priv->mmc.dev = dev;
+
+ upriv->mmc = &priv->mmc;
- debug("%s: clock %u\n", __func__, mmc->clock);
- if (mmc->clock)
- spi_set_speed(spi, mmc->clock);
return 0;
}
-static int mmc_spi_init_p(struct mmc *mmc)
+static int mmc_spi_bind(struct udevice *dev)
{
- struct spi_slave *spi = mmc->priv;
- spi_set_speed(spi, MMC_SPI_MIN_CLOCK);
- spi_claim_bus(spi);
- /* cs deactivated for 100+ clock */
- spi_xfer(spi, 18 * 8, NULL, NULL, 0);
- spi_release_bus(spi);
- return 0;
+ struct mmc_spi_priv *priv = dev_get_priv(dev);
+
+ return mmc_bind(dev, &priv->mmc, &priv->cfg);
}
-static const struct mmc_ops mmc_spi_ops = {
- .send_cmd = mmc_spi_request,
- .set_ios = mmc_spi_set_ios,
- .init = mmc_spi_init_p,
+static const struct dm_mmc_ops mmc_spi_ops = {
+ .send_cmd = dm_mmc_spi_request,
+ .set_ios = dm_mmc_spi_set_ios,
};
-static struct mmc_config mmc_spi_cfg = {
- .name = "MMC_SPI",
- .ops = &mmc_spi_ops,
- .host_caps = MMC_MODE_SPI,
- .voltages = MMC_SPI_VOLTAGE,
- .f_min = MMC_SPI_MIN_CLOCK,
- .part_type = PART_TYPE_DOS,
- .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
+static const struct udevice_id dm_mmc_spi_match[] = {
+ { .compatible = "mmc-spi-slot" },
+ { /* sentinel */ }
};
-struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode)
-{
- struct mmc *mmc;
- struct spi_slave *spi;
-
- spi = spi_setup_slave(bus, cs, speed, mode);
- if (spi == NULL)
- return NULL;
-
- mmc_spi_cfg.f_max = speed;
-
- mmc = mmc_create(&mmc_spi_cfg, spi);
- if (mmc == NULL) {
- spi_free_slave(spi);
- return NULL;
- }
- return mmc;
-}
+U_BOOT_DRIVER(mmc_spi) = {
+ .name = "mmc_spi",
+ .id = UCLASS_MMC,
+ .of_match = dm_mmc_spi_match,
+ .ops = &mmc_spi_ops,
+ .probe = mmc_spi_probe,
+ .bind = mmc_spi_bind,
+ .priv_auto_alloc_size = sizeof(struct mmc_spi_priv),
+};
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index c8c83c9188..02648b0f50 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -119,7 +119,7 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
blk += blk_r;
/* Waiting for the ready status */
- if (mmc_send_status(mmc, timeout))
+ if (mmc_poll_for_busy(mmc, timeout))
return 0;
}
@@ -177,7 +177,7 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
}
/* Waiting for the ready status */
- if (mmc_send_status(mmc, timeout))
+ if (mmc_poll_for_busy(mmc, timeout))
return 0;
return blkcnt;
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 133cdc1352..3ea7f4e173 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -430,7 +430,6 @@ static void omap_hsmmc_conf_bus_power(struct mmc *mmc, uint signal_voltage)
writel(ac12, &mmc_base->ac12);
}
-#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
static int omap_hsmmc_wait_dat0(struct udevice *dev, int state, int timeout)
{
int ret = -ETIMEDOUT;
@@ -456,7 +455,6 @@ static int omap_hsmmc_wait_dat0(struct udevice *dev, int state, int timeout)
return ret;
}
-#endif
#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE)
#if CONFIG_IS_ENABLED(DM_REGULATOR)
@@ -775,14 +773,6 @@ tuning_error:
return ret;
}
#endif
-
-static void omap_hsmmc_send_init_stream(struct udevice *dev)
-{
- struct omap_hsmmc_data *priv = dev_get_priv(dev);
- struct hsmmc *mmc_base = priv->base_addr;
-
- mmc_init_stream(mmc_base);
-}
#endif
static void mmc_enable_irq(struct mmc *mmc, struct mmc_cmd *cmd)
@@ -1065,18 +1055,17 @@ static int omap_hsmmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
if (get_timer(0) - start > MAX_RETRY_MS) {
printf("%s: timedout waiting on cmd inhibit to clear\n",
__func__);
+ mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
+ mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC);
return -ETIMEDOUT;
}
}
writel(0xFFFFFFFF, &mmc_base->stat);
- start = get_timer(0);
- while (readl(&mmc_base->stat)) {
- if (get_timer(0) - start > MAX_RETRY_MS) {
- printf("%s: timedout waiting for STAT (%x) to clear\n",
- __func__, readl(&mmc_base->stat));
- return -ETIMEDOUT;
- }
+ if (readl(&mmc_base->stat)) {
+ mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
+ mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC);
}
+
/*
* CMDREG
* CMDIDX[13:8] : Command index
@@ -1522,10 +1511,7 @@ static const struct dm_mmc_ops omap_hsmmc_ops = {
#ifdef MMC_SUPPORTS_TUNING
.execute_tuning = omap_hsmmc_execute_tuning,
#endif
- .send_init_stream = omap_hsmmc_send_init_stream,
-#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
.wait_dat0 = omap_hsmmc_wait_dat0,
-#endif
};
#else
static const struct mmc_ops omap_hsmmc_ops = {
diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c
index 908f192089..33371fe562 100644
--- a/drivers/mmc/rpmb.c
+++ b/drivers/mmc/rpmb.c
@@ -103,7 +103,7 @@ static int mmc_rpmb_request(struct mmc *mmc, const struct s_rpmb *s,
cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
cmd.cmdarg = 0;
- cmd.resp_type = MMC_RSP_R1b;
+ cmd.resp_type = MMC_RSP_R1;
data.src = (const char *)s;
data.blocks = 1;
@@ -327,7 +327,7 @@ static int send_write_mult_block(struct mmc *mmc, const struct s_rpmb *frm,
{
struct mmc_cmd cmd = {
.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK,
- .resp_type = MMC_RSP_R1b,
+ .resp_type = MMC_RSP_R1,
};
struct mmc_data data = {
.src = (const void *)frm,
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index e2bb90abbd..c4e88790bc 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -12,6 +12,7 @@
#include <malloc.h>
#include <mmc.h>
#include <sdhci.h>
+#include <dm.h>
#if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER)
void *aligned_buffer = (void *)CONFIG_FIXED_SDHCI_ALIGNED_BUFFER;
@@ -590,6 +591,12 @@ static int sdhci_set_ios(struct mmc *mmc)
static int sdhci_init(struct mmc *mmc)
{
struct sdhci_host *host = mmc->priv;
+#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_GPIO)
+ struct udevice *dev = mmc->dev;
+
+ gpio_request_by_name(dev, "cd-gpio", 0,
+ &host->cd_gpio, GPIOD_IS_IN);
+#endif
sdhci_reset(host, SDHCI_RESET_ALL);
@@ -624,9 +631,40 @@ int sdhci_probe(struct udevice *dev)
return sdhci_init(mmc);
}
+int sdhci_get_cd(struct udevice *dev)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+ struct sdhci_host *host = mmc->priv;
+ int value;
+
+ /* If nonremovable, assume that the card is always present. */
+ if (mmc->cfg->host_caps & MMC_CAP_NONREMOVABLE)
+ return 1;
+ /* If polling, assume that the card is always present. */
+ if (mmc->cfg->host_caps & MMC_CAP_NEEDS_POLL)
+ return 1;
+
+#if CONFIG_IS_ENABLED(DM_GPIO)
+ value = dm_gpio_get_value(&host->cd_gpio);
+ if (value >= 0) {
+ if (mmc->cfg->host_caps & MMC_CAP_CD_ACTIVE_HIGH)
+ return !value;
+ else
+ return value;
+ }
+#endif
+ value = !!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
+ SDHCI_CARD_PRESENT);
+ if (mmc->cfg->host_caps & MMC_CAP_CD_ACTIVE_HIGH)
+ return !value;
+ else
+ return value;
+}
+
const struct dm_mmc_ops sdhci_ops = {
.send_cmd = sdhci_send_command,
.set_ios = sdhci_set_ios,
+ .get_cd = sdhci_get_cd,
#ifdef MMC_SUPPORTS_TUNING
.execute_tuning = sdhci_execute_tuning,
#endif
diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c
index ed31ca126e..867ed569eb 100644
--- a/drivers/mmc/stm32_sdmmc2.c
+++ b/drivers/mmc/stm32_sdmmc2.c
@@ -669,6 +669,7 @@ static int stm32_sdmmc2_probe(struct udevice *dev)
switch (dev_read_u32_default(dev, "bus-width", 1)) {
case 8:
cfg->host_caps |= MMC_MODE_8BIT;
+ /* fall through */
case 4:
cfg->host_caps |= MMC_MODE_4BIT;
break;
@@ -692,7 +693,7 @@ clk_free:
return ret;
}
-int stm32_sdmmc_bind(struct udevice *dev)
+static int stm32_sdmmc_bind(struct udevice *dev)
{
struct stm32_sdmmc2_plat *plat = dev_get_platdata(dev);
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 2bb749d7f7..f3179cc21f 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -627,21 +627,16 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
struct stm32_fmc2_timings *tims = &nand->timings;
unsigned long hclk = clk_get_rate(&fmc2->clk);
unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
- int tar, tclr, thiz, twait, tset_mem, tset_att, thold_mem, thold_att;
-
- tar = hclkp;
- if (tar < sdrt->tAR_min)
- tar = sdrt->tAR_min;
- tims->tar = DIV_ROUND_UP(tar, hclkp) - 1;
- if (tims->tar > FMC2_PCR_TIMING_MASK)
- tims->tar = FMC2_PCR_TIMING_MASK;
-
- tclr = hclkp;
- if (tclr < sdrt->tCLR_min)
- tclr = sdrt->tCLR_min;
- tims->tclr = DIV_ROUND_UP(tclr, hclkp) - 1;
- if (tims->tclr > FMC2_PCR_TIMING_MASK)
- tims->tclr = FMC2_PCR_TIMING_MASK;
+ unsigned long timing, tar, tclr, thiz, twait;
+ unsigned long tset_mem, tset_att, thold_mem, thold_att;
+
+ tar = max_t(unsigned long, hclkp, sdrt->tAR_min);
+ timing = DIV_ROUND_UP(tar, hclkp) - 1;
+ tims->tar = min_t(unsigned long, timing, FMC2_PCR_TIMING_MASK);
+
+ tclr = max_t(unsigned long, hclkp, sdrt->tCLR_min);
+ timing = DIV_ROUND_UP(tclr, hclkp) - 1;
+ tims->tclr = min_t(unsigned long, timing, FMC2_PCR_TIMING_MASK);
tims->thiz = FMC2_THIZ;
thiz = (tims->thiz + 1) * hclkp;
@@ -651,18 +646,11 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
* tWAIT > tWP
* tWAIT > tREA + tIO
*/
- twait = hclkp;
- if (twait < sdrt->tRP_min)
- twait = sdrt->tRP_min;
- if (twait < sdrt->tWP_min)
- twait = sdrt->tWP_min;
- if (twait < sdrt->tREA_max + FMC2_TIO)
- twait = sdrt->tREA_max + FMC2_TIO;
- tims->twait = DIV_ROUND_UP(twait, hclkp);
- if (tims->twait == 0)
- tims->twait = 1;
- else if (tims->twait > FMC2_PMEM_PATT_TIMING_MASK)
- tims->twait = FMC2_PMEM_PATT_TIMING_MASK;
+ twait = max_t(unsigned long, hclkp, sdrt->tRP_min);
+ twait = max_t(unsigned long, twait, sdrt->tWP_min);
+ twait = max_t(unsigned long, twait, sdrt->tREA_max + FMC2_TIO);
+ timing = DIV_ROUND_UP(twait, hclkp);
+ tims->twait = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
/*
* tSETUP_MEM > tCS - tWAIT
@@ -677,20 +665,15 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
if (twait > thiz && (sdrt->tDS_min > twait - thiz) &&
(tset_mem < sdrt->tDS_min - (twait - thiz)))
tset_mem = sdrt->tDS_min - (twait - thiz);
- tims->tset_mem = DIV_ROUND_UP(tset_mem, hclkp);
- if (tims->tset_mem == 0)
- tims->tset_mem = 1;
- else if (tims->tset_mem > FMC2_PMEM_PATT_TIMING_MASK)
- tims->tset_mem = FMC2_PMEM_PATT_TIMING_MASK;
+ timing = DIV_ROUND_UP(tset_mem, hclkp);
+ tims->tset_mem = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
/*
* tHOLD_MEM > tCH
* tHOLD_MEM > tREH - tSETUP_MEM
* tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT)
*/
- thold_mem = hclkp;
- if (thold_mem < sdrt->tCH_min)
- thold_mem = sdrt->tCH_min;
+ thold_mem = max_t(unsigned long, hclkp, sdrt->tCH_min);
if (sdrt->tREH_min > tset_mem &&
(thold_mem < sdrt->tREH_min - tset_mem))
thold_mem = sdrt->tREH_min - tset_mem;
@@ -700,11 +683,8 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
if ((sdrt->tWC_min > tset_mem + twait) &&
(thold_mem < sdrt->tWC_min - (tset_mem + twait)))
thold_mem = sdrt->tWC_min - (tset_mem + twait);
- tims->thold_mem = DIV_ROUND_UP(thold_mem, hclkp);
- if (tims->thold_mem == 0)
- tims->thold_mem = 1;
- else if (tims->thold_mem > FMC2_PMEM_PATT_TIMING_MASK)
- tims->thold_mem = FMC2_PMEM_PATT_TIMING_MASK;
+ timing = DIV_ROUND_UP(thold_mem, hclkp);
+ tims->thold_mem = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
/*
* tSETUP_ATT > tCS - tWAIT
@@ -726,11 +706,8 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
if (twait > thiz && (sdrt->tDS_min > twait - thiz) &&
(tset_att < sdrt->tDS_min - (twait - thiz)))
tset_att = sdrt->tDS_min - (twait - thiz);
- tims->tset_att = DIV_ROUND_UP(tset_att, hclkp);
- if (tims->tset_att == 0)
- tims->tset_att = 1;
- else if (tims->tset_att > FMC2_PMEM_PATT_TIMING_MASK)
- tims->tset_att = FMC2_PMEM_PATT_TIMING_MASK;
+ timing = DIV_ROUND_UP(tset_att, hclkp);
+ tims->tset_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
/*
* tHOLD_ATT > tALH
@@ -745,17 +722,11 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
* tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT)
* tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT)
*/
- thold_att = hclkp;
- if (thold_att < sdrt->tALH_min)
- thold_att = sdrt->tALH_min;
- if (thold_att < sdrt->tCH_min)
- thold_att = sdrt->tCH_min;
- if (thold_att < sdrt->tCLH_min)
- thold_att = sdrt->tCLH_min;
- if (thold_att < sdrt->tCOH_min)
- thold_att = sdrt->tCOH_min;
- if (thold_att < sdrt->tDH_min)
- thold_att = sdrt->tDH_min;
+ thold_att = max_t(unsigned long, hclkp, sdrt->tALH_min);
+ thold_att = max_t(unsigned long, thold_att, sdrt->tCH_min);
+ thold_att = max_t(unsigned long, thold_att, sdrt->tCLH_min);
+ thold_att = max_t(unsigned long, thold_att, sdrt->tCOH_min);
+ thold_att = max_t(unsigned long, thold_att, sdrt->tDH_min);
if ((sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC > tset_mem) &&
(thold_att < sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem))
thold_att = sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem;
@@ -774,11 +745,8 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
if ((sdrt->tWC_min > tset_att + twait) &&
(thold_att < sdrt->tWC_min - (tset_att + twait)))
thold_att = sdrt->tWC_min - (tset_att + twait);
- tims->thold_att = DIV_ROUND_UP(thold_att, hclkp);
- if (tims->thold_att == 0)
- tims->thold_att = 1;
- else if (tims->thold_att > FMC2_PMEM_PATT_TIMING_MASK)
- tims->thold_att = FMC2_PMEM_PATT_TIMING_MASK;
+ timing = DIV_ROUND_UP(thold_att, hclkp);
+ tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
}
static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
@@ -932,7 +900,8 @@ static int stm32_fmc2_probe(struct udevice *dev)
struct nand_ecclayout *ecclayout;
struct resource resource;
struct reset_ctl reset;
- int oob_index, chip_cs, mem_region, ret, i;
+ int oob_index, chip_cs, mem_region, ret;
+ unsigned int i;
spin_lock_init(&fmc2->controller.lock);
init_waitqueue_head(&fmc2->controller.wq);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e6a4fdf30e..635f8d72c2 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -11,6 +11,29 @@ config DM_ETH
This is currently implemented in net/eth-uclass.c
Look in include/net.h for details.
+config DM_MDIO
+ bool "Enable Driver Model for MDIO devices"
+ depends on DM_ETH && PHYLIB
+ help
+ Enable driver model for MDIO devices
+
+ Adds UCLASS_MDIO DM class supporting MDIO buses that are probed as
+ stand-alone devices. Useful in particular for systems that support
+ DM_ETH and have a stand-alone MDIO hardware block shared by multiple
+ Ethernet interfaces.
+ This is currently implemented in net/mdio-uclass.c
+ Look in include/miiphy.h for details.
+
+config MDIO_SANDBOX
+ depends on DM_MDIO && SANDBOX
+ default y
+ bool "Sandbox: Mocked MDIO driver"
+ help
+ This driver implements dummy read/write/reset MDIO functions mimicking
+ a bus with a single PHY.
+
+ This driver is used in for testing in test/dm/mdio.c
+
menuconfig NETDEVICES
bool "Network device support"
depends on NET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 8d02a37896..40038427db 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -77,3 +77,4 @@ obj-y += ti/
obj-$(CONFIG_MEDIATEK_ETH) += mtk_eth.o
obj-y += mscc_eswitch/
obj-$(CONFIG_HIGMACV300_ETH) += higmacv300.o
+obj-$(CONFIG_MDIO_SANDBOX) += mdio_sandbox.o
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index c5560a7111..a7eddd647d 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -613,10 +613,12 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
/* First check for GMAC and that it is GiB capable */
if (gem_is_gigabit_capable(macb)) {
- lpa = macb_mdio_read(macb, MII_STAT1000);
+ lpa = macb_mdio_read(macb, MII_LPA);
- if (lpa & (LPA_1000FULL | LPA_1000HALF)) {
- duplex = ((lpa & LPA_1000FULL) ? 1 : 0);
+ if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
+ LPA_1000XHALF)) {
+ duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ?
+ 1 : 0);
printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
name,
diff --git a/drivers/net/mdio_sandbox.c b/drivers/net/mdio_sandbox.c
new file mode 100644
index 0000000000..07515e078c
--- /dev/null
+++ b/drivers/net/mdio_sandbox.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <dm.h>
+#include <errno.h>
+#include <miiphy.h>
+
+#define SANDBOX_PHY_ADDR 5
+#define SANDBOX_PHY_REG 0
+
+struct mdio_sandbox_priv {
+ int enabled;
+ u16 reg;
+};
+
+static int mdio_sandbox_read(struct udevice *dev, int addr, int devad, int reg)
+{
+ struct mdio_sandbox_priv *priv = dev_get_priv(dev);
+
+ if (!priv->enabled)
+ return -ENODEV;
+
+ if (addr != SANDBOX_PHY_ADDR)
+ return -ENODEV;
+ if (devad != MDIO_DEVAD_NONE)
+ return -ENODEV;
+ if (reg != SANDBOX_PHY_REG)
+ return -ENODEV;
+
+ return priv->reg;
+}
+
+static int mdio_sandbox_write(struct udevice *dev, int addr, int devad, int reg,
+ u16 val)
+{
+ struct mdio_sandbox_priv *priv = dev_get_priv(dev);
+
+ if (!priv->enabled)
+ return -ENODEV;
+
+ if (addr != SANDBOX_PHY_ADDR)
+ return -ENODEV;
+ if (devad != MDIO_DEVAD_NONE)
+ return -ENODEV;
+ if (reg != SANDBOX_PHY_REG)
+ return -ENODEV;
+
+ priv->reg = val;
+
+ return 0;
+}
+
+static int mdio_sandbox_reset(struct udevice *dev)
+{
+ struct mdio_sandbox_priv *priv = dev_get_priv(dev);
+
+ priv->reg = 0;
+
+ return 0;
+}
+
+static const struct mdio_ops mdio_sandbox_ops = {
+ .read = mdio_sandbox_read,
+ .write = mdio_sandbox_write,
+ .reset = mdio_sandbox_reset,
+};
+
+static int mdio_sandbox_probe(struct udevice *dev)
+{
+ struct mdio_sandbox_priv *priv = dev_get_priv(dev);
+
+ priv->enabled = 1;
+
+ return 0;
+}
+
+static const struct udevice_id mdio_sandbox_ids[] = {
+ { .compatible = "sandbox,mdio" },
+ { }
+};
+
+U_BOOT_DRIVER(mdio_sandbox) = {
+ .name = "mdio_sandbox",
+ .id = UCLASS_MDIO,
+ .of_match = mdio_sandbox_ids,
+ .probe = mdio_sandbox_probe,
+ .ops = &mdio_sandbox_ops,
+ .priv_auto_alloc_size = sizeof(struct mdio_sandbox_priv),
+};
diff --git a/drivers/net/mscc_eswitch/Makefile b/drivers/net/mscc_eswitch/Makefile
index 02f39a76bb..d583fe9fc4 100644
--- a/drivers/net/mscc_eswitch/Makefile
+++ b/drivers/net/mscc_eswitch/Makefile
@@ -1,6 +1,6 @@
-obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_xfer.o mscc_mac_table.o
-obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_xfer.o mscc_mac_table.o
-obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o
-obj-$(CONFIG_MSCC_SERVALT_SWITCH) += servalt_switch.o mscc_xfer.o
-obj-$(CONFIG_MSCC_SERVAL_SWITCH) += serval_switch.o mscc_xfer.o mscc_mac_table.o
+obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_xfer.o mscc_mac_table.o mscc_miim.o
+obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_xfer.o mscc_mac_table.o mscc_miim.o
+obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o mscc_miim.o
+obj-$(CONFIG_MSCC_SERVALT_SWITCH) += servalt_switch.o mscc_xfer.o mscc_miim.o
+obj-$(CONFIG_MSCC_SERVAL_SWITCH) += serval_switch.o mscc_xfer.o mscc_mac_table.o mscc_miim.o
diff --git a/drivers/net/mscc_eswitch/jr2_switch.c b/drivers/net/mscc_eswitch/jr2_switch.c
index 60d408f1c7..665517775e 100644
--- a/drivers/net/mscc_eswitch/jr2_switch.c
+++ b/drivers/net/mscc_eswitch/jr2_switch.c
@@ -17,20 +17,7 @@
#include <dt-bindings/mscc/jr2_data.h>
#include "mscc_xfer.h"
-
-#define GCB_MIIM_MII_STATUS 0x0
-#define GCB_MIIM_STAT_BUSY BIT(3)
-#define GCB_MIIM_MII_CMD 0x8
-#define GCB_MIIM_MII_CMD_SCAN BIT(0)
-#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
-#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
-#define GCB_MIIM_MII_CMD_SINGLE_SCAN BIT(3)
-#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
-#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
-#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
-#define GCB_MIIM_MII_CMD_VLD BIT(31)
-#define GCB_MIIM_DATA 0xC
-#define GCB_MIIM_DATA_ERROR (0x3 << 16)
+#include "mscc_miim.h"
#define ANA_AC_RAM_CTRL_RAM_INIT 0x94358
#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET 0x94370
@@ -279,13 +266,6 @@ struct jr2_private {
struct jr2_phy_port_t ports[MAX_PORT];
};
-struct jr2_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
-};
-
static const unsigned long jr2_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x8,
[MSCC_QS_XTR_FLUSH] = 0x18,
@@ -294,99 +274,9 @@ static const unsigned long jr2_regs_qs[] = {
[MSCC_QS_INJ_CTRL] = 0x34,
};
-static struct jr2_miim_dev miim[JR2_MIIM_BUS_COUNT];
+static struct mscc_miim_dev miim[JR2_MIIM_BUS_COUNT];
static int miim_count = -1;
-static int mscc_miim_wait_ready(struct jr2_miim_dev *miim)
-{
- unsigned long deadline;
- u32 val;
-
- deadline = timer_get_us() + 250000;
-
- do {
- val = readl(miim->regs + GCB_MIIM_MII_STATUS);
- } while (timer_get_us() <= deadline && (val & GCB_MIIM_STAT_BUSY));
-
- if (val & GCB_MIIM_STAT_BUSY)
- return -ETIMEDOUT;
-
- return 0;
-}
-
-static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
- struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
- u32 val;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
- miim->regs + GCB_MIIM_MII_CMD);
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
- ret = -EIO;
- goto out;
- }
-
- ret = val & 0xFFFF;
- out:
- return ret;
-}
-
-static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
- u16 val)
-{
- struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
- GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
-
- out:
- return ret;
-}
-
-static struct mii_dev *jr2_mdiobus_init(phys_addr_t miim_base,
- unsigned long miim_size)
-{
- struct mii_dev *bus;
-
- bus = mdio_alloc();
- if (!bus)
- return NULL;
-
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
-
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
-
- if (mdio_register(bus))
- return NULL;
-
- miim[miim_count].bus = bus;
- return bus;
-}
-
static void jr2_cpu_capture_setup(struct jr2_private *priv)
{
/* ASM: No preamble and IFH prefix on CPU injected frames */
@@ -973,7 +863,7 @@ static int jr2_probe(struct udevice *dev)
}
/* Initialize miim buses */
- memset(&miim, 0x0, sizeof(struct jr2_miim_dev) * JR2_MIIM_BUS_COUNT);
+ memset(&miim, 0x0, sizeof(struct mscc_miim_dev) * JR2_MIIM_BUS_COUNT);
/* iterate all the ports and find out on which bus they are */
i = 0;
@@ -1008,7 +898,8 @@ static int jr2_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
- jr2_mdiobus_init(addr_base, addr_size);
+ mscc_mdiobus_init(miim, &miim_count, addr_base,
+ addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
diff --git a/drivers/net/mscc_eswitch/luton_switch.c b/drivers/net/mscc_eswitch/luton_switch.c
index 94852b06e7..dffe81d873 100644
--- a/drivers/net/mscc_eswitch/luton_switch.c
+++ b/drivers/net/mscc_eswitch/luton_switch.c
@@ -17,18 +17,7 @@
#include "mscc_xfer.h"
#include "mscc_mac_table.h"
-
-#define GCB_MIIM_MII_STATUS 0x0
-#define GCB_MIIM_STAT_BUSY BIT(3)
-#define GCB_MIIM_MII_CMD 0x8
-#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
-#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
-#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
-#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
-#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
-#define GCB_MIIM_MII_CMD_VLD BIT(31)
-#define GCB_MIIM_DATA 0xC
-#define GCB_MIIM_DATA_ERROR (0x2 << 16)
+#include "mscc_miim.h"
#define ANA_PORT_VLAN_CFG(x) (0x00 + 0x80 * (x))
#define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20)
@@ -189,13 +178,6 @@ struct luton_private {
struct luton_phy_port_t ports[MAX_PORT];
};
-struct mscc_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
-};
-
static const unsigned long luton_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x18,
[MSCC_QS_XTR_FLUSH] = 0x28,
@@ -213,84 +195,6 @@ static const unsigned long luton_regs_ana_table[] = {
static struct mscc_miim_dev miim[LUTON_MIIM_BUS_COUNT];
static int miim_count = -1;
-static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
-{
- return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
- GCB_MIIM_STAT_BUSY, false, 250, false);
-}
-
-static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- u32 val;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
- miim->regs + GCB_MIIM_MII_CMD);
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
- ret = -EIO;
- goto out;
- }
-
- ret = val & 0xFFFF;
- out:
- return ret;
-}
-
-static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
- u16 val)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
- GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
- out:
- return ret;
-}
-
-static struct mii_dev *serval_mdiobus_init(phys_addr_t miim_base,
- unsigned long miim_size)
-{
- struct mii_dev *bus;
-
- bus = mdio_alloc();
- if (!bus)
- return NULL;
-
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
-
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
-
- if (mdio_register(bus))
- return NULL;
-
- miim[miim_count].bus = bus;
- return bus;
-}
-
static void luton_stop(struct udevice *dev)
{
struct luton_private *priv = dev_get_priv(dev);
@@ -760,7 +664,8 @@ static int luton_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
- serval_mdiobus_init(addr_base, addr_size);
+ mscc_mdiobus_init(miim, &miim_count, addr_base,
+ addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
diff --git a/drivers/net/mscc_eswitch/mscc_miim.c b/drivers/net/mscc_eswitch/mscc_miim.c
index 419dcc1dd6..d8ee8df47b 100644
--- a/drivers/net/mscc_eswitch/mscc_miim.c
+++ b/drivers/net/mscc_eswitch/mscc_miim.c
@@ -72,3 +72,31 @@ int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
out:
return ret;
}
+
+struct mii_dev *mscc_mdiobus_init(struct mscc_miim_dev *miim, int *miim_count,
+ phys_addr_t miim_base,
+ unsigned long miim_size)
+{
+ struct mii_dev *bus;
+
+ bus = mdio_alloc();
+
+ if (!bus)
+ return NULL;
+
+ *miim_count += 1;
+ sprintf(bus->name, "miim-bus%d", *miim_count);
+
+ miim[*miim_count].regs = ioremap(miim_base, miim_size);
+ miim[*miim_count].miim_base = miim_base;
+ miim[*miim_count].miim_size = miim_size;
+ bus->priv = &miim[*miim_count];
+ bus->read = mscc_miim_read;
+ bus->write = mscc_miim_write;
+
+ if (mdio_register(bus))
+ return NULL;
+
+ miim[*miim_count].bus = bus;
+ return bus;
+}
diff --git a/drivers/net/mscc_eswitch/mscc_miim.h b/drivers/net/mscc_eswitch/mscc_miim.h
index 0e5d5e3c81..feb1f40ae5 100644
--- a/drivers/net/mscc_eswitch/mscc_miim.h
+++ b/drivers/net/mscc_eswitch/mscc_miim.h
@@ -3,10 +3,22 @@
* Copyright (c) 2018 Microsemi Corporation
*/
+#ifndef _MSCC_MIIM_H_
+#define _MSCC_MIIM_H_
+
struct mscc_miim_dev {
void __iomem *regs;
- void __iomem *phy_regs;
+ phys_addr_t miim_base;
+ unsigned long miim_size;
+ struct mii_dev *bus;
};
int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg);
int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg, u16 val);
+
+struct mii_dev *mscc_mdiobus_init(struct mscc_miim_dev *miim, int *miim_count,
+ phys_addr_t miim_base,
+ unsigned long miim_size);
+
+
+#endif /* _MSCC_MIIM_H_ */
diff --git a/drivers/net/mscc_eswitch/ocelot_switch.c b/drivers/net/mscc_eswitch/ocelot_switch.c
index 5c7e6961be..0ba84ab78a 100644
--- a/drivers/net/mscc_eswitch/ocelot_switch.c
+++ b/drivers/net/mscc_eswitch/ocelot_switch.c
@@ -17,6 +17,7 @@
#include "mscc_xfer.h"
#include "mscc_mac_table.h"
+#include "mscc_miim.h"
#define PHY_CFG 0x0
#define PHY_CFG_ENA 0xF
@@ -25,20 +26,6 @@
#define PHY_STAT 0x4
#define PHY_STAT_SUPERVISOR_COMPLETE BIT(0)
-#define GCB_MIIM_MII_STATUS 0x0
-#define GCB_MIIM_STAT_BUSY BIT(3)
-#define GCB_MIIM_MII_CMD 0x8
-#define GCB_MIIM_MII_CMD_SCAN BIT(0)
-#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
-#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
-#define GCB_MIIM_MII_CMD_SINGLE_SCAN BIT(3)
-#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
-#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
-#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
-#define GCB_MIIM_MII_CMD_VLD BIT(31)
-#define GCB_MIIM_DATA 0xC
-#define GCB_MIIM_DATA_ERROR (0x3 << 16)
-
#define ANA_PORT_VLAN_CFG(x) (0x7000 + 0x100 * (x))
#define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20)
#define ANA_PORT_VLAN_CFG_POP_CNT(x) ((x) << 18)
@@ -173,13 +160,6 @@ struct ocelot_private {
struct ocelot_phy_port_t ports[MAX_PORT];
};
-struct mscc_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
-};
-
static struct mscc_miim_dev miim[OCELOT_MIIM_BUS_COUNT];
static int miim_count = -1;
@@ -209,85 +189,6 @@ static void mscc_phy_reset(void)
}
}
-static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
-{
- return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
- GCB_MIIM_STAT_BUSY, false, 250, false);
-}
-
-static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- u32 val;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
- miim->regs + GCB_MIIM_MII_CMD);
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
- ret = -EIO;
- goto out;
- }
-
- ret = val & 0xFFFF;
- out:
- return ret;
-}
-
-static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
- u16 val)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
- GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
- out:
- return ret;
-}
-
-static struct mii_dev *ocelot_mdiobus_init(phys_addr_t miim_base,
- unsigned long miim_size)
-{
- struct mii_dev *bus;
-
- bus = mdio_alloc();
-
- if (!bus)
- return NULL;
-
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
-
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
-
- if (mdio_register(bus))
- return NULL;
-
- miim[miim_count].bus = bus;
- return bus;
-}
-
__weak void mscc_switch_reset(void)
{
}
@@ -682,7 +583,8 @@ static int ocelot_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
- ocelot_mdiobus_init(addr_base, addr_size);
+ mscc_mdiobus_init(miim, &miim_count, addr_base,
+ addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
diff --git a/drivers/net/mscc_eswitch/serval_switch.c b/drivers/net/mscc_eswitch/serval_switch.c
index 2559f5d0cd..1a21360a96 100644
--- a/drivers/net/mscc_eswitch/serval_switch.c
+++ b/drivers/net/mscc_eswitch/serval_switch.c
@@ -17,18 +17,7 @@
#include "mscc_xfer.h"
#include "mscc_mac_table.h"
-
-#define GCB_MIIM_MII_STATUS 0x0
-#define GCB_MIIM_STAT_BUSY BIT(3)
-#define GCB_MIIM_MII_CMD 0x8
-#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
-#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
-#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
-#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
-#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
-#define GCB_MIIM_MII_CMD_VLD BIT(31)
-#define GCB_MIIM_DATA 0xC
-#define GCB_MIIM_DATA_ERROR (0x2 << 16)
+#include "mscc_miim.h"
#define ANA_PORT_VLAN_CFG(x) (0xc000 + 0x100 * (x))
#define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20)
@@ -156,13 +145,6 @@ struct serval_private {
struct serval_phy_port_t ports[MAX_PORT];
};
-struct mscc_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
-};
-
static const unsigned long serval_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x8,
[MSCC_QS_XTR_FLUSH] = 0x18,
@@ -180,84 +162,6 @@ static const unsigned long serval_regs_ana_table[] = {
static struct mscc_miim_dev miim[SERVAL_MIIM_BUS_COUNT];
static int miim_count = -1;
-static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
-{
- return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
- GCB_MIIM_STAT_BUSY, false, 250, false);
-}
-
-static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- u32 val;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
- miim->regs + GCB_MIIM_MII_CMD);
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
- ret = -EIO;
- goto out;
- }
-
- ret = val & 0xFFFF;
- out:
- return ret;
-}
-
-static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
- u16 val)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
- GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
- out:
- return ret;
-}
-
-static struct mii_dev *serval_mdiobus_init(phys_addr_t miim_base,
- unsigned long miim_size)
-{
- struct mii_dev *bus;
-
- bus = mdio_alloc();
- if (!bus)
- return NULL;
-
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
-
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
-
- if (mdio_register(bus))
- return NULL;
-
- miim[miim_count].bus = bus;
- return bus;
-}
-
static void serval_cpu_capture_setup(struct serval_private *priv)
{
int i;
@@ -356,8 +260,6 @@ static void serdes_write(void __iomem *base, u32 addr)
do {
data = readl(base + HSIO_MCB_SERDES1G_CFG);
} while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
-
- mdelay(100);
}
static void serdes1g_setup(void __iomem *base, uint32_t addr,
@@ -636,7 +538,8 @@ static int serval_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
- serval_mdiobus_init(addr_base, addr_size);
+ mscc_mdiobus_init(miim, &miim_count, addr_base,
+ addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
diff --git a/drivers/net/mscc_eswitch/servalt_switch.c b/drivers/net/mscc_eswitch/servalt_switch.c
index 995c62309d..d20ec49d56 100644
--- a/drivers/net/mscc_eswitch/servalt_switch.c
+++ b/drivers/net/mscc_eswitch/servalt_switch.c
@@ -16,18 +16,7 @@
#include <wait_bit.h>
#include "mscc_xfer.h"
-
-#define GCB_MIIM_MII_STATUS 0x0
-#define GCB_MIIM_STAT_BUSY BIT(3)
-#define GCB_MIIM_MII_CMD 0x8
-#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1)
-#define GCB_MIIM_MII_CMD_OPR_READ BIT(2)
-#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4)
-#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20)
-#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25)
-#define GCB_MIIM_MII_CMD_VLD BIT(31)
-#define GCB_MIIM_DATA 0xC
-#define GCB_MIIM_DATA_ERROR (0x3 << 16)
+#include "mscc_miim.h"
#define PHY_CFG 0x0
#define PHY_CFG_ENA 0x3
@@ -134,13 +123,6 @@ struct servalt_private {
struct servalt_phy_port_t ports[MAX_PORT];
};
-struct mscc_miim_dev {
- void __iomem *regs;
- phys_addr_t miim_base;
- unsigned long miim_size;
- struct mii_dev *bus;
-};
-
static const unsigned long servalt_regs_qs[] = {
[MSCC_QS_XTR_RD] = 0x8,
[MSCC_QS_XTR_FLUSH] = 0x18,
@@ -152,85 +134,6 @@ static const unsigned long servalt_regs_qs[] = {
static struct mscc_miim_dev miim[SERVALT_MIIM_BUS_COUNT];
static int miim_count = -1;
-static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
-{
- return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
- GCB_MIIM_STAT_BUSY, false, 250, false);
-}
-
-static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- u32 val;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
- miim->regs + GCB_MIIM_MII_CMD);
-
- ret = mscc_miim_wait_ready(miim);
- if (ret)
- goto out;
-
- val = readl(miim->regs + GCB_MIIM_DATA);
- if (val & GCB_MIIM_DATA_ERROR) {
- ret = -EIO;
- goto out;
- }
-
- ret = val & 0xFFFF;
-out:
- return ret;
-}
-
-static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
- u16 val)
-{
- struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
- int ret;
-
- ret = mscc_miim_wait_ready(miim);
- if (ret < 0)
- goto out;
-
- writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
- GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
- GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
-
-out:
- return ret;
-}
-
-static struct mii_dev *servalt_mdiobus_init(phys_addr_t miim_base,
- unsigned long miim_size)
-{
- struct mii_dev *bus;
-
- bus = mdio_alloc();
- if (!bus)
- return NULL;
-
- ++miim_count;
- sprintf(bus->name, "miim-bus%d", miim_count);
-
- miim[miim_count].regs = ioremap(miim_base, miim_size);
- miim[miim_count].miim_base = miim_base;
- miim[miim_count].miim_size = miim_size;
- bus->priv = &miim[miim_count];
- bus->read = mscc_miim_read;
- bus->write = mscc_miim_write;
-
- if (mdio_register(bus))
- return NULL;
-
- miim[miim_count].bus = bus;
- return bus;
-}
-
static void mscc_phy_reset(void)
{
writel(0, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG);
@@ -564,7 +467,8 @@ static int servalt_probe(struct udevice *dev)
/* If the bus is new then create a new bus */
if (!get_mdiobus(addr_base, addr_size))
priv->bus[miim_count] =
- servalt_mdiobus_init(addr_base, addr_size);
+ mscc_mdiobus_init(miim, &miim_count, addr_base,
+ addr_size);
/* Connect mdio bus with the port */
bus = get_mdiobus(addr_base, addr_size);
diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c
index a04a118f90..ec81dab3f6 100644
--- a/drivers/net/phy/cortina.c
+++ b/drivers/net/phy/cortina.c
@@ -176,8 +176,13 @@ void cs4340_upload_firmware(struct phy_device *phydev)
printf("MMC read: dev # %u, block # %u, count %u ...\n",
dev, blk, cnt);
mmc_init(mmc);
+#ifdef CONFIG_BLK
+ (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
+ addr);
+#else
(void)mmc->block_dev.block_read(&mmc->block_dev, blk, cnt,
addr);
+#endif
}
#endif
diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c
index 25f1332ca9..7509936465 100644
--- a/drivers/net/phy/ti.c
+++ b/drivers/net/phy/ti.c
@@ -103,7 +103,7 @@ struct dp83867_private {
int io_impedance;
bool rxctrl_strap_quirk;
int port_mirroring;
- int clk_output_sel;
+ unsigned int clk_output_sel;
};
static int dp83867_config_port_mirroring(struct phy_device *phydev)
@@ -136,17 +136,11 @@ static int dp83867_of_init(struct phy_device *phydev)
ofnode node;
u16 val;
- /* Optional configuration */
-
node = phy_get_ofnode(phydev);
if (!ofnode_valid(node))
return -EINVAL;
- /*
- * Keep the default value if ti,clk-output-sel is not set
- * or to high
- */
-
+ /* Keep the default value if ti,clk-output-sel is not set */
dp83867->clk_output_sel =
ofnode_read_u32_default(node, "ti,clk-output-sel",
DP83867_CLK_O_SEL_REF_CLK);
@@ -162,14 +156,14 @@ static int dp83867_of_init(struct phy_device *phydev)
dp83867->rxctrl_strap_quirk = true;
dp83867->rx_id_delay = ofnode_read_u32_default(node,
"ti,rx-internal-delay",
- -1);
+ DEFAULT_RX_ID_DELAY);
dp83867->tx_id_delay = ofnode_read_u32_default(node,
"ti,tx-internal-delay",
- -1);
+ DEFAULT_TX_ID_DELAY);
dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth",
- -1);
+ DEFAULT_FIFO_DEPTH);
if (ofnode_read_bool(node, "enet-phy-lane-swap"))
dp83867->port_mirroring = DP83867_PORT_MIRRORING_EN;
diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig
index 82bc9f5d03..ecf642de10 100644
--- a/drivers/net/ti/Kconfig
+++ b/drivers/net/ti/Kconfig
@@ -18,3 +18,11 @@ config DRIVER_TI_KEYSTONE_NET
bool "TI Keystone 2 Ethernet"
help
This driver supports the TI Keystone 2 Ethernet subsystem
+
+config TI_AM65_CPSW_NUSS
+ bool "TI K3 AM65x MCU CPSW Nuss Ethernet controller driver"
+ depends on ARCH_K3
+ select PHYLIB
+ help
+ This driver supports TI K3 MCU CPSW Nuss Ethernet controller
+ in Texas Instruments K3 AM65x SoCs.
diff --git a/drivers/net/ti/Makefile b/drivers/net/ti/Makefile
index ee3e4eb5d6..8d3808bb4b 100644
--- a/drivers/net/ti/Makefile
+++ b/drivers/net/ti/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o cpsw-common.o cpsw_mdio.o
obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o cpsw_mdio.o
+obj-$(CONFIG_TI_AM65_CPSW_NUSS) += am65-cpsw-nuss.o cpsw_mdio.o
diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c
new file mode 100644
index 0000000000..e11fbdeed3
--- /dev/null
+++ b/drivers/net/ti/am65-cpsw-nuss.c
@@ -0,0 +1,792 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver
+ *
+ * Copyright (C) 2019, Texas Instruments, Incorporated
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dma-uclass.h>
+#include <dm/of_access.h>
+#include <miiphy.h>
+#include <net.h>
+#include <phy.h>
+#include <power-domain.h>
+#include <linux/soc/ti/ti-udma.h>
+
+#include "cpsw_mdio.h"
+
+#define AM65_CPSW_CPSWNU_MAX_PORTS 2
+
+#define AM65_CPSW_SS_BASE 0x0
+#define AM65_CPSW_SGMII_BASE 0x100
+#define AM65_CPSW_MDIO_BASE 0xf00
+#define AM65_CPSW_XGMII_BASE 0x2100
+#define AM65_CPSW_CPSW_NU_BASE 0x20000
+#define AM65_CPSW_CPSW_NU_ALE_BASE 0x1e000
+
+#define AM65_CPSW_CPSW_NU_PORTS_OFFSET 0x1000
+#define AM65_CPSW_CPSW_NU_PORT_MACSL_OFFSET 0x330
+
+#define AM65_CPSW_MDIO_BUS_FREQ_DEF 1000000
+
+#define AM65_CPSW_CTL_REG 0x4
+#define AM65_CPSW_STAT_PORT_EN_REG 0x14
+#define AM65_CPSW_PTYPE_REG 0x18
+
+#define AM65_CPSW_CTL_REG_P0_ENABLE BIT(2)
+#define AM65_CPSW_CTL_REG_P0_TX_CRC_REMOVE BIT(13)
+#define AM65_CPSW_CTL_REG_P0_RX_PAD BIT(14)
+
+#define AM65_CPSW_P0_FLOW_ID_REG 0x8
+#define AM65_CPSW_PN_RX_MAXLEN_REG 0x24
+#define AM65_CPSW_PN_REG_SA_L 0x308
+#define AM65_CPSW_PN_REG_SA_H 0x30c
+
+#define AM65_CPSW_ALE_CTL_REG 0x8
+#define AM65_CPSW_ALE_CTL_REG_ENABLE BIT(31)
+#define AM65_CPSW_ALE_CTL_REG_RESET_TBL BIT(30)
+#define AM65_CPSW_ALE_CTL_REG_BYPASS BIT(4)
+#define AM65_CPSW_ALE_PN_CTL_REG(x) (0x40 + (x) * 4)
+#define AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD 0x3
+#define AM65_CPSW_ALE_PN_CTL_REG_MAC_ONLY BIT(11)
+
+#define AM65_CPSW_MACSL_CTL_REG 0x0
+#define AM65_CPSW_MACSL_CTL_REG_IFCTL_A BIT(15)
+#define AM65_CPSW_MACSL_CTL_REG_GIG BIT(7)
+#define AM65_CPSW_MACSL_CTL_REG_GMII_EN BIT(5)
+#define AM65_CPSW_MACSL_CTL_REG_LOOPBACK BIT(1)
+#define AM65_CPSW_MACSL_CTL_REG_FULL_DUPLEX BIT(0)
+#define AM65_CPSW_MACSL_RESET_REG 0x8
+#define AM65_CPSW_MACSL_RESET_REG_RESET BIT(0)
+#define AM65_CPSW_MACSL_STATUS_REG 0x4
+#define AM65_CPSW_MACSL_RESET_REG_PN_IDLE BIT(31)
+#define AM65_CPSW_MACSL_RESET_REG_PN_E_IDLE BIT(30)
+#define AM65_CPSW_MACSL_RESET_REG_PN_P_IDLE BIT(29)
+#define AM65_CPSW_MACSL_RESET_REG_PN_TX_IDLE BIT(28)
+#define AM65_CPSW_MACSL_RESET_REG_IDLE_MASK \
+ (AM65_CPSW_MACSL_RESET_REG_PN_IDLE | \
+ AM65_CPSW_MACSL_RESET_REG_PN_E_IDLE | \
+ AM65_CPSW_MACSL_RESET_REG_PN_P_IDLE | \
+ AM65_CPSW_MACSL_RESET_REG_PN_TX_IDLE)
+
+#define AM65_CPSW_CPPI_PKT_TYPE 0x7
+
+struct am65_cpsw_port {
+ fdt_addr_t port_base;
+ fdt_addr_t macsl_base;
+ bool disabled;
+ u32 mac_control;
+};
+
+struct am65_cpsw_common {
+ struct udevice *dev;
+ fdt_addr_t ss_base;
+ fdt_addr_t cpsw_base;
+ fdt_addr_t mdio_base;
+ fdt_addr_t ale_base;
+ fdt_addr_t gmii_sel;
+ fdt_addr_t mac_efuse;
+
+ struct clk fclk;
+ struct power_domain pwrdmn;
+
+ u32 port_num;
+ struct am65_cpsw_port ports[AM65_CPSW_CPSWNU_MAX_PORTS];
+ u32 rflow_id_base;
+
+ struct mii_dev *bus;
+ u32 bus_freq;
+
+ struct dma dma_tx;
+ struct dma dma_rx;
+ u32 rx_next;
+ u32 rx_pend;
+ bool started;
+};
+
+struct am65_cpsw_priv {
+ struct udevice *dev;
+ struct am65_cpsw_common *cpsw_common;
+ u32 port_id;
+
+ struct phy_device *phydev;
+ bool has_phy;
+ ofnode phy_node;
+ u32 phy_addr;
+};
+
+#ifdef PKTSIZE_ALIGN
+#define UDMA_RX_BUF_SIZE PKTSIZE_ALIGN
+#else
+#define UDMA_RX_BUF_SIZE ALIGN(1522, ARCH_DMA_MINALIGN)
+#endif
+
+#ifdef PKTBUFSRX
+#define UDMA_RX_DESC_NUM PKTBUFSRX
+#else
+#define UDMA_RX_DESC_NUM 4
+#endif
+
+#define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \
+ ((mac)[2] << 16) | ((mac)[3] << 24))
+#define mac_lo(mac) (((mac)[4] << 0) | ((mac)[5] << 8))
+
+static void am65_cpsw_set_sl_mac(struct am65_cpsw_port *slave,
+ unsigned char *addr)
+{
+ writel(mac_hi(addr),
+ slave->port_base + AM65_CPSW_PN_REG_SA_H);
+ writel(mac_lo(addr),
+ slave->port_base + AM65_CPSW_PN_REG_SA_L);
+}
+
+int am65_cpsw_macsl_reset(struct am65_cpsw_port *slave)
+{
+ u32 i = 100;
+
+ /* Set the soft reset bit */
+ writel(AM65_CPSW_MACSL_RESET_REG_RESET,
+ slave->macsl_base + AM65_CPSW_MACSL_RESET_REG);
+
+ while ((readl(slave->macsl_base + AM65_CPSW_MACSL_RESET_REG) &
+ AM65_CPSW_MACSL_RESET_REG_RESET) && i--)
+ cpu_relax();
+
+ /* Timeout on the reset */
+ return i;
+}
+
+static int am65_cpsw_macsl_wait_for_idle(struct am65_cpsw_port *slave)
+{
+ u32 i = 100;
+
+ while ((readl(slave->macsl_base + AM65_CPSW_MACSL_STATUS_REG) &
+ AM65_CPSW_MACSL_RESET_REG_IDLE_MASK) && i--)
+ cpu_relax();
+
+ return i;
+}
+
+static int am65_cpsw_update_link(struct am65_cpsw_priv *priv)
+{
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ struct am65_cpsw_port *port = &common->ports[priv->port_id];
+ struct phy_device *phy = priv->phydev;
+ u32 mac_control = 0;
+
+ if (phy->link) { /* link up */
+ mac_control = /*AM65_CPSW_MACSL_CTL_REG_LOOPBACK |*/
+ AM65_CPSW_MACSL_CTL_REG_GMII_EN;
+ if (phy->speed == 1000)
+ mac_control |= AM65_CPSW_MACSL_CTL_REG_GIG;
+ if (phy->duplex == DUPLEX_FULL)
+ mac_control |= AM65_CPSW_MACSL_CTL_REG_FULL_DUPLEX;
+ if (phy->speed == 100)
+ mac_control |= AM65_CPSW_MACSL_CTL_REG_IFCTL_A;
+ }
+
+ if (mac_control == port->mac_control)
+ goto out;
+
+ if (mac_control) {
+ printf("link up on port %d, speed %d, %s duplex\n",
+ priv->port_id, phy->speed,
+ (phy->duplex == DUPLEX_FULL) ? "full" : "half");
+ } else {
+ printf("link down on port %d\n", priv->port_id);
+ }
+
+ writel(mac_control, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
+ port->mac_control = mac_control;
+
+out:
+ return phy->link;
+}
+
+#define AM65_GMII_SEL_MODE_MII 0
+#define AM65_GMII_SEL_MODE_RMII 1
+#define AM65_GMII_SEL_MODE_RGMII 2
+
+#define AM65_GMII_SEL_RGMII_IDMODE BIT(4)
+
+static void am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
+ phy_interface_t phy_mode, int slave)
+{
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ u32 reg;
+ u32 mode = 0;
+ bool rgmii_id = false;
+
+ reg = readl(common->gmii_sel);
+
+ dev_dbg(common->dev, "old gmii_sel: %08x\n", reg);
+
+ switch (phy_mode) {
+ case PHY_INTERFACE_MODE_RMII:
+ mode = AM65_GMII_SEL_MODE_RMII;
+ break;
+
+ case PHY_INTERFACE_MODE_RGMII:
+ mode = AM65_GMII_SEL_MODE_RGMII;
+ break;
+
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ mode = AM65_GMII_SEL_MODE_RGMII;
+ rgmii_id = true;
+ break;
+
+ default:
+ dev_warn(common->dev,
+ "Unsupported PHY mode: %u. Defaulting to MII.\n",
+ phy_mode);
+ /* fallthrough */
+ case PHY_INTERFACE_MODE_MII:
+ mode = AM65_GMII_SEL_MODE_MII;
+ break;
+ };
+
+ if (rgmii_id)
+ mode |= AM65_GMII_SEL_RGMII_IDMODE;
+
+ reg = mode;
+ dev_dbg(common->dev, "gmii_sel PHY mode: %u, new gmii_sel: %08x\n",
+ phy_mode, reg);
+ writel(reg, common->gmii_sel);
+
+ reg = readl(common->gmii_sel);
+ if (reg != mode)
+ dev_err(common->dev,
+ "gmii_sel PHY mode NOT SET!: requested: %08x, gmii_sel: %08x\n",
+ mode, reg);
+}
+
+static int am65_cpsw_start(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ struct am65_cpsw_port *port = &common->ports[priv->port_id];
+ struct am65_cpsw_port *port0 = &common->ports[0];
+ int ret, i;
+
+ ret = power_domain_on(&common->pwrdmn);
+ if (ret) {
+ dev_err(dev, "power_domain_on() failed %d\n", ret);
+ goto out;
+ }
+
+ ret = clk_enable(&common->fclk);
+ if (ret) {
+ dev_err(dev, "clk enabled failed %d\n", ret);
+ goto err_off_pwrdm;
+ }
+
+ common->rx_next = 0;
+ common->rx_pend = 0;
+ ret = dma_get_by_name(common->dev, "tx0", &common->dma_tx);
+ if (ret) {
+ dev_err(dev, "TX dma get failed %d\n", ret);
+ goto err_off_clk;
+ }
+ ret = dma_get_by_name(common->dev, "rx", &common->dma_rx);
+ if (ret) {
+ dev_err(dev, "RX dma get failed %d\n", ret);
+ goto err_free_tx;
+ }
+
+ for (i = 0; i < UDMA_RX_DESC_NUM; i++) {
+ ret = dma_prepare_rcv_buf(&common->dma_rx,
+ net_rx_packets[i],
+ UDMA_RX_BUF_SIZE);
+ if (ret) {
+ dev_err(dev, "RX dma add buf failed %d\n", ret);
+ goto err_free_tx;
+ }
+ }
+
+ ret = dma_enable(&common->dma_tx);
+ if (ret) {
+ dev_err(dev, "TX dma_enable failed %d\n", ret);
+ goto err_free_rx;
+ }
+ ret = dma_enable(&common->dma_rx);
+ if (ret) {
+ dev_err(dev, "RX dma_enable failed %d\n", ret);
+ goto err_dis_tx;
+ }
+
+ /* Control register */
+ writel(AM65_CPSW_CTL_REG_P0_ENABLE |
+ AM65_CPSW_CTL_REG_P0_TX_CRC_REMOVE |
+ AM65_CPSW_CTL_REG_P0_RX_PAD,
+ common->cpsw_base + AM65_CPSW_CTL_REG);
+
+ /* disable priority elevation */
+ writel(0, common->cpsw_base + AM65_CPSW_PTYPE_REG);
+
+ /* enable statistics */
+ writel(BIT(0) | BIT(priv->port_id),
+ common->cpsw_base + AM65_CPSW_STAT_PORT_EN_REG);
+
+ /* Port 0 length register */
+ writel(PKTSIZE_ALIGN, port0->port_base + AM65_CPSW_PN_RX_MAXLEN_REG);
+
+ /* set base flow_id */
+ writel(common->rflow_id_base,
+ port0->port_base + AM65_CPSW_P0_FLOW_ID_REG);
+
+ /* Reset and enable the ALE */
+ writel(AM65_CPSW_ALE_CTL_REG_ENABLE | AM65_CPSW_ALE_CTL_REG_RESET_TBL |
+ AM65_CPSW_ALE_CTL_REG_BYPASS,
+ common->ale_base + AM65_CPSW_ALE_CTL_REG);
+
+ /* port 0 put into forward mode */
+ writel(AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD,
+ common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
+
+ /* PORT x configuration */
+
+ /* Port x Max length register */
+ writel(PKTSIZE_ALIGN, port->port_base + AM65_CPSW_PN_RX_MAXLEN_REG);
+
+ /* Port x set mac */
+ am65_cpsw_set_sl_mac(port, pdata->enetaddr);
+
+ /* Port x ALE: mac_only, Forwarding */
+ writel(AM65_CPSW_ALE_PN_CTL_REG_MAC_ONLY |
+ AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD,
+ common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
+
+ port->mac_control = 0;
+ if (!am65_cpsw_macsl_reset(port)) {
+ dev_err(dev, "mac_sl reset failed\n");
+ ret = -EFAULT;
+ goto err_dis_rx;
+ }
+
+ ret = phy_startup(priv->phydev);
+ if (ret) {
+ dev_err(dev, "phy_startup failed\n");
+ goto err_dis_rx;
+ }
+
+ ret = am65_cpsw_update_link(priv);
+ if (!ret) {
+ ret = -ENODEV;
+ goto err_phy_shutdown;
+ }
+
+ common->started = true;
+
+ return 0;
+
+err_phy_shutdown:
+ phy_shutdown(priv->phydev);
+err_dis_rx:
+ /* disable ports */
+ writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
+ writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
+ if (!am65_cpsw_macsl_wait_for_idle(port))
+ dev_err(dev, "mac_sl idle timeout\n");
+ writel(0, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
+ writel(0, common->ale_base + AM65_CPSW_ALE_CTL_REG);
+ writel(0, common->cpsw_base + AM65_CPSW_CTL_REG);
+
+ dma_disable(&common->dma_rx);
+err_dis_tx:
+ dma_disable(&common->dma_tx);
+err_free_rx:
+ dma_free(&common->dma_rx);
+err_free_tx:
+ dma_free(&common->dma_tx);
+err_off_clk:
+ clk_disable(&common->fclk);
+err_off_pwrdm:
+ power_domain_off(&common->pwrdmn);
+out:
+ dev_err(dev, "%s end error\n", __func__);
+
+ return ret;
+}
+
+static int am65_cpsw_send(struct udevice *dev, void *packet, int length)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ struct ti_udma_drv_packet_data packet_data;
+ int ret;
+
+ packet_data.pkt_type = AM65_CPSW_CPPI_PKT_TYPE;
+ packet_data.dest_tag = priv->port_id;
+ ret = dma_send(&common->dma_tx, packet, length, &packet_data);
+ if (ret) {
+ dev_err(dev, "TX dma_send failed %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int am65_cpsw_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+
+ /* try to receive a new packet */
+ return dma_receive(&common->dma_rx, (void **)packetp, NULL);
+}
+
+static int am65_cpsw_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ int ret;
+
+ if (length > 0) {
+ u32 pkt = common->rx_next % UDMA_RX_DESC_NUM;
+
+ ret = dma_prepare_rcv_buf(&common->dma_rx,
+ net_rx_packets[pkt],
+ UDMA_RX_BUF_SIZE);
+ if (ret)
+ dev_err(dev, "RX dma free_pkt failed %d\n", ret);
+ common->rx_next++;
+ }
+
+ return 0;
+}
+
+static void am65_cpsw_stop(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ struct am65_cpsw_port *port = &common->ports[priv->port_id];
+
+ if (!common->started)
+ return;
+
+ phy_shutdown(priv->phydev);
+
+ writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
+ writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
+ if (!am65_cpsw_macsl_wait_for_idle(port))
+ dev_err(dev, "mac_sl idle timeout\n");
+ writel(0, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
+ writel(0, common->ale_base + AM65_CPSW_ALE_CTL_REG);
+ writel(0, common->cpsw_base + AM65_CPSW_CTL_REG);
+
+ dma_disable(&common->dma_tx);
+ dma_free(&common->dma_tx);
+
+ dma_disable(&common->dma_rx);
+ dma_free(&common->dma_rx);
+
+ common->started = false;
+}
+
+static int am65_cpsw_read_rom_hwaddr(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *common = priv->cpsw_common;
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ u32 mac_hi, mac_lo;
+
+ if (common->mac_efuse == FDT_ADDR_T_NONE)
+ return -1;
+
+ mac_lo = readl(common->mac_efuse);
+ mac_hi = readl(common->mac_efuse + 4);
+ pdata->enetaddr[0] = (mac_hi >> 8) & 0xff;
+ pdata->enetaddr[1] = mac_hi & 0xff;
+ pdata->enetaddr[2] = (mac_lo >> 24) & 0xff;
+ pdata->enetaddr[3] = (mac_lo >> 16) & 0xff;
+ pdata->enetaddr[4] = (mac_lo >> 8) & 0xff;
+ pdata->enetaddr[5] = mac_lo & 0xff;
+
+ return 0;
+}
+
+static const struct eth_ops am65_cpsw_ops = {
+ .start = am65_cpsw_start,
+ .send = am65_cpsw_send,
+ .recv = am65_cpsw_recv,
+ .free_pkt = am65_cpsw_free_pkt,
+ .stop = am65_cpsw_stop,
+ .read_rom_hwaddr = am65_cpsw_read_rom_hwaddr,
+};
+
+static int am65_cpsw_mdio_init(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
+
+ if (!priv->has_phy || cpsw_common->bus)
+ return 0;
+
+ cpsw_common->bus = cpsw_mdio_init(dev->name,
+ cpsw_common->mdio_base,
+ cpsw_common->bus_freq,
+ clk_get_rate(&cpsw_common->fclk));
+ if (!cpsw_common->bus)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int am65_cpsw_phy_init(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct phy_device *phydev;
+ u32 supported = PHY_GBIT_FEATURES;
+ int ret;
+
+ phydev = phy_connect(cpsw_common->bus,
+ priv->phy_addr,
+ priv->dev,
+ pdata->phy_interface);
+
+ if (!phydev) {
+ dev_err(dev, "phy_connect() failed\n");
+ return -ENODEV;
+ }
+
+ phydev->supported &= supported;
+ if (pdata->max_speed) {
+ ret = phy_set_supported(phydev, pdata->max_speed);
+ if (ret)
+ return ret;
+ }
+ phydev->advertising = phydev->supported;
+
+ if (ofnode_valid(priv->phy_node))
+ phydev->node = priv->phy_node;
+
+ priv->phydev = phydev;
+ ret = phy_config(phydev);
+ if (ret < 0)
+ pr_err("phy_config() failed: %d", ret);
+
+ return ret;
+}
+
+static int am65_cpsw_ofdata_parse_phy(struct udevice *dev, ofnode port_np)
+{
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct ofnode_phandle_args out_args;
+ const char *phy_mode;
+ int ret = 0;
+
+ phy_mode = ofnode_read_string(port_np, "phy-mode");
+ if (phy_mode) {
+ pdata->phy_interface =
+ phy_get_interface_by_name(phy_mode);
+ if (pdata->phy_interface == -1) {
+ dev_err(dev, "Invalid PHY mode '%s', port %u\n",
+ phy_mode, priv->port_id);
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ ofnode_read_u32(port_np, "max-speed", (u32 *)&pdata->max_speed);
+ if (pdata->max_speed)
+ dev_err(dev, "Port %u speed froced to %uMbit\n",
+ priv->port_id, pdata->max_speed);
+
+ priv->has_phy = true;
+ ret = ofnode_parse_phandle_with_args(port_np, "phy-handle",
+ NULL, 0, 0, &out_args);
+ if (ret) {
+ dev_err(dev, "can't parse phy-handle port %u (%d)\n",
+ priv->port_id, ret);
+ priv->has_phy = false;
+ ret = 0;
+ }
+
+ priv->phy_node = out_args.node;
+ if (priv->has_phy) {
+ ret = ofnode_read_u32(priv->phy_node, "reg", &priv->phy_addr);
+ if (ret) {
+ dev_err(dev, "failed to get phy_addr port %u (%d)\n",
+ priv->port_id, ret);
+ goto out;
+ }
+ }
+
+out:
+ return ret;
+}
+
+static int am65_cpsw_probe_cpsw(struct udevice *dev)
+{
+ struct am65_cpsw_priv *priv = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+ struct am65_cpsw_common *cpsw_common;
+ ofnode ports_np, node;
+ int ret, i;
+
+ priv->dev = dev;
+
+ cpsw_common = calloc(1, sizeof(*priv->cpsw_common));
+ if (!cpsw_common)
+ return -ENOMEM;
+ priv->cpsw_common = cpsw_common;
+
+ cpsw_common->dev = dev;
+ cpsw_common->ss_base = dev_read_addr(dev);
+ if (cpsw_common->ss_base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+ cpsw_common->mac_efuse = devfdt_get_addr_name(dev, "mac_efuse");
+ /* no err check - optional */
+
+ ret = power_domain_get_by_index(dev, &cpsw_common->pwrdmn, 0);
+ if (ret) {
+ dev_err(dev, "failed to get pwrdmn: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_get_by_name(dev, "fck", &cpsw_common->fclk);
+ if (ret) {
+ power_domain_free(&cpsw_common->pwrdmn);
+ dev_err(dev, "failed to get clock %d\n", ret);
+ return ret;
+ }
+
+ cpsw_common->cpsw_base = cpsw_common->ss_base + AM65_CPSW_CPSW_NU_BASE;
+ cpsw_common->ale_base = cpsw_common->cpsw_base +
+ AM65_CPSW_CPSW_NU_ALE_BASE;
+ cpsw_common->mdio_base = cpsw_common->ss_base + AM65_CPSW_MDIO_BASE;
+
+ cpsw_common->rflow_id_base = 0;
+ cpsw_common->rflow_id_base =
+ dev_read_u32_default(dev, "ti,rx-flow-id-base",
+ cpsw_common->rflow_id_base);
+
+ ports_np = dev_read_subnode(dev, "ports");
+ if (!ofnode_valid(ports_np)) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ ofnode_for_each_subnode(node, ports_np) {
+ const char *node_name;
+ u32 port_id;
+ bool disabled;
+
+ node_name = ofnode_get_name(node);
+
+ disabled = !ofnode_is_available(node);
+
+ ret = ofnode_read_u32(node, "reg", &port_id);
+ if (ret) {
+ dev_err(dev, "%s: failed to get port_id (%d)\n",
+ node_name, ret);
+ goto out;
+ }
+
+ if (port_id >= AM65_CPSW_CPSWNU_MAX_PORTS) {
+ dev_err(dev, "%s: invalid port_id (%d)\n",
+ node_name, port_id);
+ ret = -EINVAL;
+ goto out;
+ }
+ cpsw_common->port_num++;
+
+ if (!port_id)
+ continue;
+
+ priv->port_id = port_id;
+ cpsw_common->ports[port_id].disabled = disabled;
+ if (disabled)
+ continue;
+
+ ret = am65_cpsw_ofdata_parse_phy(dev, node);
+ if (ret)
+ goto out;
+ }
+
+ for (i = 0; i < AM65_CPSW_CPSWNU_MAX_PORTS; i++) {
+ struct am65_cpsw_port *port = &cpsw_common->ports[i];
+
+ port->port_base = cpsw_common->cpsw_base +
+ AM65_CPSW_CPSW_NU_PORTS_OFFSET +
+ (i * AM65_CPSW_CPSW_NU_PORTS_OFFSET);
+ port->macsl_base = port->port_base +
+ AM65_CPSW_CPSW_NU_PORT_MACSL_OFFSET;
+ }
+
+ node = dev_read_subnode(dev, "cpsw-phy-sel");
+ if (!ofnode_valid(node)) {
+ dev_err(dev, "can't find cpsw-phy-sel\n");
+ ret = -ENOENT;
+ goto out;
+ }
+
+ cpsw_common->gmii_sel = ofnode_get_addr(node);
+ if (cpsw_common->gmii_sel == FDT_ADDR_T_NONE) {
+ dev_err(dev, "failed to get gmii_sel base\n");
+ goto out;
+ }
+
+ node = dev_read_subnode(dev, "mdio");
+ if (!ofnode_valid(node)) {
+ dev_err(dev, "can't find mdio\n");
+ ret = -ENOENT;
+ goto out;
+ }
+
+ cpsw_common->bus_freq =
+ dev_read_u32_default(dev, "bus_freq",
+ AM65_CPSW_MDIO_BUS_FREQ_DEF);
+
+ am65_cpsw_gmii_sel_k3(priv, pdata->phy_interface, priv->port_id);
+
+ ret = am65_cpsw_mdio_init(dev);
+ if (ret)
+ goto out;
+
+ ret = am65_cpsw_phy_init(dev);
+ if (ret)
+ goto out;
+
+ dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u rflow_id_base:%u mdio_freq:%u\n",
+ readl(cpsw_common->ss_base),
+ readl(cpsw_common->cpsw_base),
+ readl(cpsw_common->ale_base),
+ cpsw_common->port_num,
+ cpsw_common->rflow_id_base,
+ cpsw_common->bus_freq);
+
+out:
+ clk_free(&cpsw_common->fclk);
+ power_domain_free(&cpsw_common->pwrdmn);
+ return ret;
+}
+
+static const struct udevice_id am65_cpsw_nuss_ids[] = {
+ { .compatible = "ti,am654-cpsw-nuss" },
+ { }
+};
+
+U_BOOT_DRIVER(am65_cpsw_nuss_slave) = {
+ .name = "am65_cpsw_nuss_slave",
+ .id = UCLASS_ETH,
+ .of_match = am65_cpsw_nuss_ids,
+ .probe = am65_cpsw_probe_cpsw,
+ .ops = &am65_cpsw_ops,
+ .priv_auto_alloc_size = sizeof(struct am65_cpsw_priv),
+ .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/drivers/net/ti/cpsw_mdio.c b/drivers/net/ti/cpsw_mdio.c
index 70f547e6d7..6e8f652011 100644
--- a/drivers/net/ti/cpsw_mdio.c
+++ b/drivers/net/ti/cpsw_mdio.c
@@ -125,7 +125,7 @@ u32 cpsw_mdio_get_alive(struct mii_dev *bus)
return val & GENMASK(15, 0);
}
-struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
+struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
u32 bus_freq, int fck_freq)
{
struct cpsw_mdio *cpsw_mdio;
@@ -144,7 +144,7 @@ struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
return NULL;
}
- cpsw_mdio->regs = (struct cpsw_mdio_regs *)mdio_base;
+ cpsw_mdio->regs = (struct cpsw_mdio_regs *)(uintptr_t)mdio_base;
if (!bus_freq || !fck_freq)
cpsw_mdio->div = CPSW_MDIO_DIV_DEF;
diff --git a/drivers/net/ti/cpsw_mdio.h b/drivers/net/ti/cpsw_mdio.h
index 4a76d4e5c5..dbf4a2dcac 100644
--- a/drivers/net/ti/cpsw_mdio.h
+++ b/drivers/net/ti/cpsw_mdio.h
@@ -10,7 +10,7 @@
struct cpsw_mdio;
-struct mii_dev *cpsw_mdio_init(const char *name, u32 mdio_base,
+struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
u32 bus_freq, int fck_freq);
void cpsw_mdio_free(struct mii_dev *bus);
u32 cpsw_mdio_get_alive(struct mii_dev *bus);
diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
index 43dbdd9d6a..cdbe463cff 100644
--- a/drivers/pinctrl/pinctrl_stm32.c
+++ b/drivers/pinctrl/pinctrl_stm32.c
@@ -1,5 +1,6 @@
#include <common.h>
#include <dm.h>
+#include <dm/lists.h>
#include <dm/pinctrl.h>
#include <hwspinlock.h>
#include <asm/arch/gpio.h>
@@ -136,7 +137,7 @@ static struct udevice *stm32_pinctrl_get_gpio_dev(struct udevice *dev,
*/
*idx = stm32_offset_to_index(gpio_bank->gpio_dev,
selector - pin_count);
- if (*idx < 0)
+ if (IS_ERR_VALUE(*idx))
return NULL;
return gpio_bank->gpio_dev;
@@ -215,7 +216,7 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
#endif
-int stm32_pinctrl_probe(struct udevice *dev)
+static int stm32_pinctrl_probe(struct udevice *dev)
{
struct stm32_pinctrl_priv *priv = dev_get_priv(dev);
int ret;
@@ -364,6 +365,35 @@ static int stm32_pinctrl_config(int offset)
return 0;
}
+static int stm32_pinctrl_bind(struct udevice *dev)
+{
+ ofnode node;
+ const char *name;
+ int ret;
+
+ dev_for_each_subnode(node, dev) {
+ debug("%s: bind %s\n", __func__, ofnode_get_name(node));
+
+ ofnode_get_property(node, "gpio-controller", &ret);
+ if (ret < 0)
+ continue;
+ /* Get the name of each gpio node */
+ name = ofnode_get_name(node);
+ if (!name)
+ return -EINVAL;
+
+ /* Bind each gpio node */
+ ret = device_bind_driver_to_node(dev, "gpio_stm32",
+ name, node, NULL);
+ if (ret)
+ return ret;
+
+ debug("%s: bind %s\n", __func__, name);
+ }
+
+ return 0;
+}
+
#if CONFIG_IS_ENABLED(PINCTRL_FULL)
static int stm32_pinctrl_set_state(struct udevice *dev, struct udevice *config)
{
@@ -433,7 +463,7 @@ U_BOOT_DRIVER(pinctrl_stm32) = {
.id = UCLASS_PINCTRL,
.of_match = stm32_pinctrl_ids,
.ops = &stm32_pinctrl_ops,
- .bind = dm_scan_fdt_dev,
+ .bind = stm32_pinctrl_bind,
.probe = stm32_pinctrl_probe,
.priv_auto_alloc_size = sizeof(struct stm32_pinctrl_priv),
};
diff --git a/drivers/power/pmic/stpmic1.c b/drivers/power/pmic/stpmic1.c
index 65296c5fc3..c3381489dd 100644
--- a/drivers/power/pmic/stpmic1.c
+++ b/drivers/power/pmic/stpmic1.c
@@ -221,7 +221,7 @@ static int stpmic1_sysreset_request(struct udevice *dev, enum sysreset_t type)
struct udevice *pmic_dev;
int ret;
- if (type != SYSRESET_POWER)
+ if (type != SYSRESET_POWER && type != SYSRESET_POWER_OFF)
return -EPROTONOSUPPORT;
ret = uclass_get_device_by_driver(UCLASS_PMIC,
@@ -235,8 +235,13 @@ static int stpmic1_sysreset_request(struct udevice *dev, enum sysreset_t type)
if (ret < 0)
return ret;
- ret = pmic_reg_write(pmic_dev, STPMIC1_MAIN_CR,
- ret | STPMIC1_SWOFF | STPMIC1_RREQ_EN);
+ ret |= STPMIC1_SWOFF;
+ ret &= ~STPMIC1_RREQ_EN;
+ /* request Power Cycle */
+ if (type == SYSRESET_POWER)
+ ret |= STPMIC1_RREQ_EN;
+
+ ret = pmic_reg_write(pmic_dev, STPMIC1_MAIN_CR, ret);
if (ret < 0)
return ret;
diff --git a/drivers/power/regulator/stm32-vrefbuf.c b/drivers/power/regulator/stm32-vrefbuf.c
index 0ad6833ed0..645528e84e 100644
--- a/drivers/power/regulator/stm32-vrefbuf.c
+++ b/drivers/power/regulator/stm32-vrefbuf.c
@@ -30,7 +30,7 @@ struct stm32_vrefbuf {
struct udevice *vdda_supply;
};
-static const unsigned int stm32_vrefbuf_voltages[] = {
+static const int stm32_vrefbuf_voltages[] = {
/* Matches resp. VRS = 000b, 001b, 010b, 011b */
2500000, 2048000, 1800000, 1500000,
};
diff --git a/drivers/power/regulator/stpmic1.c b/drivers/power/regulator/stpmic1.c
index 50ef2a21d1..1e3f96f3a0 100644
--- a/drivers/power/regulator/stpmic1.c
+++ b/drivers/power/regulator/stpmic1.c
@@ -422,6 +422,7 @@ static int stpmic1_ldo_set_mode(struct udevice *dev, int mode)
case STPMIC1_LDO_MODE_SINK_SOURCE:
ret &= ~STPMIC1_LDO12356_VOUT_MASK;
ret |= STPMIC1_LDO3_DDR_SEL << STPMIC1_LDO12356_VOUT_SHIFT;
+ /* fallthrough */
case STPMIC1_LDO_MODE_NORMAL:
ret &= ~STPMIC1_LDO3_MODE;
break;
diff --git a/drivers/ram/stm32mp1/stm32mp1_ram.c b/drivers/ram/stm32mp1/stm32mp1_ram.c
index 84e39d093b..a362cf98bf 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ram.c
+++ b/drivers/ram/stm32mp1/stm32mp1_ram.c
@@ -26,7 +26,7 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed)
unsigned long ddr_clk;
struct clk clk;
int ret;
- int idx;
+ unsigned int idx;
for (idx = 0; idx < ARRAY_SIZE(clkname); idx++) {
ret = clk_get_by_name(priv->dev, clkname[idx], &clk);
@@ -59,7 +59,8 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed)
static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
{
struct ddr_info *priv = dev_get_priv(dev);
- int ret, idx;
+ int ret;
+ unsigned int idx;
struct clk axidcg;
struct stm32mp1_ddr_config config;
diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c
index cca8b707ac..3ab536a52a 100644
--- a/drivers/serial/serial_stm32.c
+++ b/drivers/serial/serial_stm32.c
@@ -195,9 +195,9 @@ static int stm32_serial_probe(struct udevice *dev)
}
plat->clock_rate = clk_get_rate(&clk);
- if (plat->clock_rate < 0) {
+ if (!plat->clock_rate) {
clk_disable(&clk);
- return plat->clock_rate;
+ return -EINVAL;
};
_stm32_serial_init(plat->base, plat->uart_info);
diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c
index bb1067ff4a..8d612f22d6 100644
--- a/drivers/spi/stm32_qspi.c
+++ b/drivers/spi/stm32_qspi.c
@@ -361,9 +361,9 @@ static int stm32_qspi_probe(struct udevice *bus)
}
priv->clock_rate = clk_get_rate(&clk);
- if (priv->clock_rate < 0) {
+ if (!priv->clock_rate) {
clk_disable(&clk);
- return priv->clock_rate;
+ return -EINVAL;
}
ret = reset_get_by_index(bus, 0, &reset_ctl);
@@ -395,14 +395,15 @@ static int stm32_qspi_claim_bus(struct udevice *dev)
{
struct stm32_qspi_priv *priv = dev_get_priv(dev->parent);
struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+ int slave_cs = slave_plat->cs;
- if (slave_plat->cs >= STM32_QSPI_MAX_CHIP)
+ if (slave_cs >= STM32_QSPI_MAX_CHIP)
return -ENODEV;
- if (priv->cs_used != slave_plat->cs) {
- struct stm32_qspi_flash *flash = &priv->flash[slave_plat->cs];
+ if (priv->cs_used != slave_cs) {
+ struct stm32_qspi_flash *flash = &priv->flash[slave_cs];
- priv->cs_used = slave_plat->cs;
+ priv->cs_used = slave_cs;
if (flash->initialized) {
/* Set the configuration: speed + cs */
@@ -444,11 +445,12 @@ static int stm32_qspi_set_speed(struct udevice *bus, uint speed)
int ret;
if (speed > 0) {
- prescaler = DIV_ROUND_UP(qspi_clk, speed) - 1;
- if (prescaler > 255)
- prescaler = 255;
- else if (prescaler < 0)
- prescaler = 0;
+ prescaler = 0;
+ if (qspi_clk) {
+ prescaler = DIV_ROUND_UP(qspi_clk, speed) - 1;
+ if (prescaler > 255)
+ prescaler = 255;
+ }
}
csht = DIV_ROUND_UP((5 * qspi_clk) / (prescaler + 1), 100000000);
diff --git a/drivers/spi/stm32_spi.c b/drivers/spi/stm32_spi.c
index 34b217584d..75b6006b45 100644
--- a/drivers/spi/stm32_spi.c
+++ b/drivers/spi/stm32_spi.c
@@ -99,8 +99,8 @@ struct stm32_spi_priv {
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 */
+ unsigned int tx_len; /* number of data to be written in bytes */
+ unsigned 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;
@@ -322,7 +322,8 @@ static int stm32_spi_set_fthlv(struct udevice *dev, u32 xfer_len)
static int stm32_spi_set_speed(struct udevice *bus, uint hz)
{
struct stm32_spi_priv *priv = dev_get_priv(bus);
- u32 div, mbrdiv;
+ u32 mbrdiv;
+ long div;
debug("%s: hz=%d\n", __func__, hz);
@@ -341,7 +342,7 @@ static int stm32_spi_set_speed(struct udevice *bus, uint hz)
else
mbrdiv = fls(div) - 1;
- if ((mbrdiv - 1) < 0)
+ if (!mbrdiv)
return -EINVAL;
clrsetbits_le32(priv->base + STM32_SPI_CFG1, SPI_CFG1_MBR,
@@ -481,7 +482,7 @@ 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;
+ unsigned int i;
priv->base = dev_remap_addr(dev);
if (!priv->base)
diff --git a/drivers/sysreset/sysreset_syscon.c b/drivers/sysreset/sysreset_syscon.c
index 1028160247..d0e586f66f 100644
--- a/drivers/sysreset/sysreset_syscon.c
+++ b/drivers/sysreset/sysreset_syscon.c
@@ -23,8 +23,9 @@ struct syscon_reboot_priv {
static int syscon_reboot_request(struct udevice *dev, enum sysreset_t type)
{
struct syscon_reboot_priv *priv = dev_get_priv(dev);
+ ulong driver_data = dev_get_driver_data(dev);
- if (type == SYSRESET_POWER)
+ if (type != driver_data)
return -EPROTONOSUPPORT;
regmap_write(priv->regmap, priv->offset, priv->mask);
@@ -53,7 +54,8 @@ int syscon_reboot_probe(struct udevice *dev)
}
static const struct udevice_id syscon_reboot_ids[] = {
- { .compatible = "syscon-reboot" },
+ { .compatible = "syscon-reboot", .data = SYSRESET_COLD },
+ { .compatible = "syscon-poweroff", .data = SYSRESET_POWER_OFF },
{ /* sentinel */ }
};
diff --git a/env/Kconfig b/env/Kconfig
index d86a9bfa30..74db2f38cc 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -468,8 +468,7 @@ if ARCH_ROCKCHIP || ARCH_SUNXI || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL || ARC
config ENV_OFFSET
hex "Environment Offset"
- depends on !ENV_IS_IN_UBI
- depends on !ENV_IS_NOWHERE
+ depends on (!ENV_IS_IN_UBI && !ENV_IS_NOWHERE) || ARCH_STM32MP
default 0x3f8000 if ARCH_ROCKCHIP
default 0x88000 if ARCH_SUNXI
default 0xE0000 if ARCH_ZYNQ
@@ -492,7 +491,7 @@ config ENV_SIZE
config ENV_SECT_SIZE
hex "Environment Sector-Size"
- depends on !ENV_IS_NOWHERE && (ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_OMAP2PLUS || ARCH_AT91)
+ depends on (!ENV_IS_NOWHERE && (ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_OMAP2PLUS || ARCH_AT91) )|| ARCH_STM32MP
default 0x40000 if ARCH_ZYNQMP
default 0x20000 if ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91
help
diff --git a/include/configs/UCP1020.h b/include/configs/UCP1020.h
index 268a41c82c..6a01a90425 100644
--- a/include/configs/UCP1020.h
+++ b/include/configs/UCP1020.h
@@ -438,7 +438,6 @@
#ifdef CONFIG_MMC
#define CONFIG_SYS_FSL_ESDHC_ADDR CONFIG_SYS_MPC85xx_ESDHC_ADDR
-#define CONFIG_MMC_SPI
#endif
/* Misc Extra Settings */
diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h
index 0ce2fcb8b7..24f7b9d463 100644
--- a/include/configs/stm32mp1.h
+++ b/include/configs/stm32mp1.h
@@ -28,6 +28,10 @@
#define CONFIG_SYS_SDRAM_BASE STM32_DDR_BASE
#define CONFIG_SYS_INIT_SP_ADDR CONFIG_SYS_TEXT_BASE
+#ifdef CONFIG_STM32MP1_OPTEE
+#define CONFIG_SYS_MEM_TOP_HIDE SZ_32M
+#endif /* CONFIG_STM32MP1_OPTEE */
+
/*
* Console I/O buffer size
*/
@@ -38,11 +42,6 @@
*/
#define CONFIG_SYS_LOAD_ADDR STM32_DDR_BASE
-#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
@@ -73,6 +72,10 @@
/*MMC SD*/
#define CONFIG_SYS_MMC_MAX_DEVICE 3
+/* NAND support */
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+#define CONFIG_SYS_MAX_NAND_DEVICE 1
+
/* Ethernet need */
#ifdef CONFIG_DWC_ETH_QOS
#define CONFIG_SYS_NONCACHED_MEMORY (1 * SZ_1M) /* 1M */
@@ -81,17 +84,18 @@
#define CONFIG_SYS_AUTOLOAD "no"
#endif
+/* Dynamic MTD partition support */
+#define CONFIG_SYS_MTDPARTS_RUNTIME
+
/*****************************************************************************/
#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(UBIFS, ubifs, 0) \
func(MMC, mmc, 0) \
func(MMC, mmc, 2) \
func(PXE, pxe, na)
@@ -108,6 +112,7 @@
"if test ${boot_device} = serial || test ${boot_device} = usb;" \
"then stm32prog ${boot_device} ${boot_instance}; " \
"else " \
+ "run env_check;" \
"if test ${boot_device} = mmc;" \
"then env set boot_targets \"mmc${boot_instance}\"; fi;" \
"if test ${boot_device} = nand;" \
@@ -117,14 +122,24 @@
#include <config_distro_bootcmd.h>
-#if defined(CONFIG_STM32_QSPI) || defined(CONFIG_NAND_STM32_FMC)
-#define CONFIG_SYS_MTDPARTS_RUNTIME
-#endif
+#ifdef CONFIG_STM32MP1_OPTEE
+/* with OPTEE: define specific MTD partitions = teeh, teed, teex */
+#define STM32MP_MTDPARTS \
+ "mtdparts_nor0=256k(fsbl1),256k(fsbl2),2m(ssbl),256k(u-boot-env),256k(teeh),256k(teed),256k(teex),-(nor_user)\0" \
+ "mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),512k(teeh),512k(teed),512k(teex),-(UBI)\0"
+#else /* CONFIG_STM32MP1_OPTEE */
#define STM32MP_MTDPARTS \
"mtdparts_nor0=256k(fsbl1),256k(fsbl2),2m(ssbl),256k(u-boot-env),-(nor_user)\0" \
"mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),-(UBI)\0"
+#endif /* CONFIG_STM32MP1_OPTEE */
+
+#ifndef CONFIG_SYS_MTDPARTS_RUNTIME
+#undef STM32MP_MTDPARTS
+#define STM32MP_MTDPARTS
+#endif
+
/*
* memory layout for 32M uncompressed/compressed kernel,
* 1M fdt, 1M script, 1M pxe and 1M for splashimage
@@ -139,9 +154,13 @@
"ramdisk_addr_r=0xc4400000\0" \
"fdt_high=0xffffffff\0" \
"initrd_high=0xffffffff\0" \
+ "env_default=1\0" \
+ "env_check=if test $env_default -eq 1;"\
+ " then env set env_default 0;env save;fi\0" \
STM32MP_BOOTCMD \
STM32MP_MTDPARTS \
- BOOTENV
+ BOOTENV \
+ "boot_net_usb_start=true\0"
#endif /* ifndef CONFIG_SPL_BUILD */
#endif /* ifdef CONFIG_DISTRO_DEFAULTS*/
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 5056a084d2..f9300a64ce 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -58,6 +58,7 @@ enum uclass_id {
UCLASS_LPC, /* x86 'low pin count' interface */
UCLASS_MAILBOX, /* Mailbox controller */
UCLASS_MASS_STORAGE, /* Mass storage device */
+ UCLASS_MDIO, /* MDIO bus */
UCLASS_MISC, /* Miscellaneous device */
UCLASS_MMC, /* SD / MMC card or chip */
UCLASS_MOD_EXP, /* RSA Mod Exp device */
diff --git a/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h
index b5a2174a63..e6fb8ada3f 100644
--- a/include/dt-bindings/pinctrl/stm32-pinfunc.h
+++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h
@@ -32,5 +32,11 @@
#define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode))
+/* package information */
+#define STM32MP_PKG_AA 0x1
+#define STM32MP_PKG_AB 0x2
+#define STM32MP_PKG_AC 0x4
+#define STM32MP_PKG_AD 0x8
+
#endif /* _DT_BINDINGS_STM32_PINFUNC_H */
diff --git a/include/miiphy.h b/include/miiphy.h
index f11763affd..e6dd441983 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -118,4 +118,53 @@ int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
#define ESTATUS_1000XF 0x8000
#define ESTATUS_1000XH 0x4000
+#ifdef CONFIG_DM_MDIO
+
+/**
+ * struct mdio_perdev_priv - Per-device class data for MDIO DM
+ *
+ * @mii_bus: Supporting MII legacy bus
+ */
+struct mdio_perdev_priv {
+ struct mii_dev *mii_bus;
+};
+
+/**
+ * struct mdio_ops - MDIO bus operations
+ *
+ * @read: Read from a PHY register
+ * @write: Write to a PHY register
+ * @reset: Reset the MDIO bus, NULL if not supported
+ */
+struct mdio_ops {
+ int (*read)(struct udevice *mdio_dev, int addr, int devad, int reg);
+ int (*write)(struct udevice *mdio_dev, int addr, int devad, int reg,
+ u16 val);
+ int (*reset)(struct udevice *mdio_dev);
+};
+
+#define mdio_get_ops(dev) ((struct mdio_ops *)(dev)->driver->ops)
+
+/**
+ * dm_mdio_probe_devices - Call probe on all MII devices, currently used for
+ * MDIO console commands.
+ */
+void dm_mdio_probe_devices(void);
+
+/**
+ * dm_mdio_phy_connect - Wrapper over phy_connect for DM MDIO
+ *
+ * @dev: mdio dev
+ * @addr: PHY address on MDIO bus
+ * @ethdev: ethernet device to connect to the PHY
+ * @interface: MAC-PHY protocol
+ *
+ * @return pointer to phy_device, or 0 on error
+ */
+struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
+ struct udevice *ethdev,
+ phy_interface_t interface);
+
+#endif
+
#endif
diff --git a/include/mmc.h b/include/mmc.h
index 1f30f71d25..46422f41a4 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -65,6 +65,11 @@
#define MMC_MODE_DDR_52MHz MMC_CAP(MMC_DDR_52)
#define MMC_MODE_HS200 MMC_CAP(MMC_HS_200)
#define MMC_MODE_HS400 MMC_CAP(MMC_HS_400)
+#define MMC_MODE_HS400_ES MMC_CAP(MMC_HS_400_ES)
+
+#define MMC_CAP_NONREMOVABLE BIT(14)
+#define MMC_CAP_NEEDS_POLL BIT(15)
+#define MMC_CAP_CD_ACTIVE_HIGH BIT(16)
#define MMC_MODE_8BIT BIT(30)
#define MMC_MODE_4BIT BIT(29)
@@ -219,13 +224,16 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
#define EXT_CSD_BOOT_BUS_WIDTH 177
#define EXT_CSD_PART_CONF 179 /* R/W */
#define EXT_CSD_BUS_WIDTH 183 /* R/W */
+#define EXT_CSD_STROBE_SUPPORT 184 /* R/W */
#define EXT_CSD_HS_TIMING 185 /* R/W */
#define EXT_CSD_REV 192 /* RO */
#define EXT_CSD_CARD_TYPE 196 /* RO */
+#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */
#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */
#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
#define EXT_CSD_BOOT_MULT 226 /* RO */
+#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */
#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */
/*
@@ -260,11 +268,13 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
#define EXT_CSD_DDR_FLAG BIT(2) /* Flag for DDR mode */
+#define EXT_CSD_BUS_WIDTH_STROBE BIT(7) /* Enhanced strobe mode */
#define EXT_CSD_TIMING_LEGACY 0 /* no high speed */
#define EXT_CSD_TIMING_HS 1 /* HS */
#define EXT_CSD_TIMING_HS200 2 /* HS200 */
#define EXT_CSD_TIMING_HS400 3 /* HS400 */
+#define EXT_CSD_DRV_STR_SHIFT 4 /* Driver Strength shift */
#define EXT_CSD_BOOT_ACK_ENABLE (1 << 6)
#define EXT_CSD_BOOT_PARTITION_ENABLE (1 << 3)
@@ -415,14 +425,6 @@ struct dm_mmc_ops {
int (*set_ios)(struct udevice *dev);
/**
- * send_init_stream() - send the initialization stream: 74 clock cycles
- * This is used after power up before sending the first command
- *
- * @dev: Device to update
- */
- void (*send_init_stream)(struct udevice *dev);
-
- /**
* get_cd() - See whether a card is present
*
* @dev: Device to check
@@ -449,7 +451,6 @@ struct dm_mmc_ops {
int (*execute_tuning)(struct udevice *dev, uint opcode);
#endif
-#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
/**
* wait_dat0() - wait until dat0 is in the target state
* (CLK must be running during the wait)
@@ -460,6 +461,10 @@ struct dm_mmc_ops {
* @return 0 if dat0 is in the target state, -ve on error
*/
int (*wait_dat0)(struct udevice *dev, int state, int timeout);
+
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+ /* set_enhanced_strobe() - set HS400 enhanced strobe */
+ int (*set_enhanced_strobe)(struct udevice *dev);
#endif
};
@@ -468,7 +473,6 @@ struct dm_mmc_ops {
int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data);
int dm_mmc_set_ios(struct udevice *dev);
-void dm_mmc_send_init_stream(struct udevice *dev);
int dm_mmc_get_cd(struct udevice *dev);
int dm_mmc_get_wp(struct udevice *dev);
int dm_mmc_execute_tuning(struct udevice *dev, uint opcode);
@@ -476,11 +480,11 @@ int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout);
/* Transition functions for compatibility */
int mmc_set_ios(struct mmc *mmc);
-void mmc_send_init_stream(struct mmc *mmc);
int mmc_getcd(struct mmc *mmc);
int mmc_getwp(struct mmc *mmc);
int mmc_execute_tuning(struct mmc *mmc, uint opcode);
int mmc_wait_dat0(struct mmc *mmc, int state, int timeout);
+int mmc_set_enhanced_strobe(struct mmc *mmc);
#else
struct mmc_ops {
@@ -526,6 +530,7 @@ enum bus_mode {
UHS_SDR104,
MMC_HS_200,
MMC_HS_400,
+ MMC_HS_400_ES,
MMC_MODES_END
};
@@ -544,6 +549,10 @@ static inline bool mmc_is_mode_ddr(enum bus_mode mode)
else if (mode == MMC_HS_400)
return true;
#endif
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+ else if (mode == MMC_HS_400_ES)
+ return true;
+#endif
else
return false;
}
@@ -593,6 +602,8 @@ struct mmc {
u8 part_attr;
u8 wr_rel_set;
u8 part_config;
+ u8 gen_cmd6_time;
+ u8 part_switch_time;
uint tran_speed;
uint legacy_speed; /* speed for the legacy mode provided by the card */
uint read_bl_len;
@@ -828,7 +839,6 @@ void mmc_set_preinit(struct mmc *mmc, int preinit);
#else
#define mmc_host_is_spi(mmc) 0
#endif
-struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode);
void board_mmc_power_init(void);
int board_mmc_init(bd_t *bis);
@@ -839,6 +849,9 @@ extern uint mmc_get_env_part(struct mmc *mmc);
# endif
int mmc_get_env_dev(void);
+/* Minimum partition switch timeout in units of 10-milliseconds */
+#define MMC_MIN_PART_SWITCH_TIME 30 /* 300 ms */
+
/* Set block count limit because of 16 bit register limit on some hardware*/
#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
diff --git a/include/mvebu_mmc.h b/include/mvebu_mmc.h
index d51b1fe467..7397165f67 100644
--- a/include/mvebu_mmc.h
+++ b/include/mvebu_mmc.h
@@ -222,13 +222,9 @@
#define MMC_CAP_SDIO_IRQ (1 << 3)
/* Talks only SPI protocols */
#define MMC_CAP_SPI (1 << 4)
-/* Needs polling for card-detection */
-#define MMC_CAP_NEEDS_POLL (1 << 5)
/* Can the host do 8 bit transfers */
#define MMC_CAP_8_BIT_DATA (1 << 6)
-/* Nonremovable e.g. eMMC */
-#define MMC_CAP_NONREMOVABLE (1 << 8)
/* Waits while card is busy */
#define MMC_CAP_WAIT_WHILE_BUSY (1 << 9)
/* Allow erase/trim commands */
diff --git a/net/Makefile b/net/Makefile
index ce36362168..6251ff3991 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_NET) += eth-uclass.o
else
obj-$(CONFIG_NET) += eth_legacy.o
endif
+obj-$(CONFIG_DM_MDIO) += mdio-uclass.o
obj-$(CONFIG_NET) += eth_common.o
obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
obj-$(CONFIG_NET) += net.o
diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c
new file mode 100644
index 0000000000..36a404ff44
--- /dev/null
+++ b/net/mdio-uclass.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <miiphy.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+
+void dm_mdio_probe_devices(void)
+{
+ struct udevice *it;
+ struct uclass *uc;
+
+ uclass_get(UCLASS_MDIO, &uc);
+ uclass_foreach_dev(it, uc) {
+ device_probe(it);
+ }
+}
+
+static int dm_mdio_post_bind(struct udevice *dev)
+{
+ /*
+ * MDIO command doesn't like spaces in names, don't allow them to keep
+ * it happy
+ */
+ if (strchr(dev->name, ' ')) {
+ debug("\nError: MDIO device name \"%s\" has a space!\n",
+ dev->name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Following read/write/reset functions are registered with legacy MII code.
+ * These are called for PHY operations by upper layers and we further call the
+ * DM MDIO driver functions.
+ */
+static int mdio_read(struct mii_dev *mii_bus, int addr, int devad, int reg)
+{
+ struct udevice *dev = mii_bus->priv;
+
+ return mdio_get_ops(dev)->read(dev, addr, devad, reg);
+}
+
+static int mdio_write(struct mii_dev *mii_bus, int addr, int devad, int reg,
+ u16 val)
+{
+ struct udevice *dev = mii_bus->priv;
+
+ return mdio_get_ops(dev)->write(dev, addr, devad, reg, val);
+}
+
+static int mdio_reset(struct mii_dev *mii_bus)
+{
+ struct udevice *dev = mii_bus->priv;
+
+ if (mdio_get_ops(dev)->reset)
+ return mdio_get_ops(dev)->reset(dev);
+ else
+ return 0;
+}
+
+static int dm_mdio_post_probe(struct udevice *dev)
+{
+ struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
+
+ pdata->mii_bus = mdio_alloc();
+ pdata->mii_bus->read = mdio_read;
+ pdata->mii_bus->write = mdio_write;
+ pdata->mii_bus->reset = mdio_reset;
+ pdata->mii_bus->priv = dev;
+ strncpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN);
+
+ return mdio_register(pdata->mii_bus);
+}
+
+static int dm_mdio_pre_remove(struct udevice *dev)
+{
+ struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
+ struct mdio_ops *ops = mdio_get_ops(dev);
+
+ if (ops->reset)
+ ops->reset(dev);
+ mdio_unregister(pdata->mii_bus);
+ mdio_free(pdata->mii_bus);
+
+ return 0;
+}
+
+struct phy_device *dm_mdio_phy_connect(struct udevice *dev, int addr,
+ struct udevice *ethdev,
+ phy_interface_t interface)
+{
+ struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
+
+ if (device_probe(dev))
+ return 0;
+
+ return phy_connect(pdata->mii_bus, addr, ethdev, interface);
+}
+
+UCLASS_DRIVER(mdio) = {
+ .id = UCLASS_MDIO,
+ .name = "mdio",
+ .post_bind = dm_mdio_post_bind,
+ .post_probe = dm_mdio_post_probe,
+ .pre_remove = dm_mdio_pre_remove,
+ .per_device_auto_alloc_size = sizeof(struct mdio_perdev_priv),
+};
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 62bd882411..79872baeda 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -1165,12 +1165,6 @@ CONFIG_MMCBOOTCOMMAND
CONFIG_MMCROOT
CONFIG_MMC_DEFAULT_DEV
CONFIG_MMC_RPMB_TRACE
-CONFIG_MMC_SPI
-CONFIG_MMC_SPI_BUS
-CONFIG_MMC_SPI_CRC_ON
-CONFIG_MMC_SPI_CS
-CONFIG_MMC_SPI_MODE
-CONFIG_MMC_SPI_SPEED
CONFIG_MMC_SUNXI_SLOT
CONFIG_MMU
CONFIG_MONITOR_IS_IN_RAM
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 420bf81154..6a36cc0a32 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -62,4 +62,5 @@ obj-$(CONFIG_SOUND) += sound.o
obj-$(CONFIG_TEE) += tee.o
obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
obj-$(CONFIG_DMA) += dma.o
+obj-$(CONFIG_DM_MDIO) += mdio.o
endif
diff --git a/test/dm/mdio.c b/test/dm/mdio.c
new file mode 100644
index 0000000000..5b66255f7d
--- /dev/null
+++ b/test/dm/mdio.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019
+ * Alex Marginean, NXP
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <misc.h>
+#include <test/ut.h>
+#include <miiphy.h>
+
+/* macros copied over from mdio_sandbox.c */
+#define SANDBOX_PHY_ADDR 5
+#define SANDBOX_PHY_REG 0
+
+#define TEST_REG_VALUE 0xabcd
+
+static int dm_test_mdio(struct unit_test_state *uts)
+{
+ struct uclass *uc;
+ struct udevice *dev;
+ struct mdio_ops *ops;
+ u16 reg;
+
+ ut_assertok(uclass_get(UCLASS_MDIO, &uc));
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_MDIO, "mdio-test", &dev));
+
+ ops = mdio_get_ops(dev);
+ ut_assertnonnull(ops);
+ ut_assertnonnull(ops->read);
+ ut_assertnonnull(ops->write);
+
+ ut_assertok(ops->write(dev, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+ SANDBOX_PHY_REG, TEST_REG_VALUE));
+ reg = ops->read(dev, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+ SANDBOX_PHY_REG);
+ ut_asserteq(reg, TEST_REG_VALUE);
+
+ ut_assert(ops->read(dev, SANDBOX_PHY_ADDR + 1, MDIO_DEVAD_NONE,
+ SANDBOX_PHY_REG) != 0);
+
+ ut_assertok(ops->reset(dev));
+ reg = ops->read(dev, SANDBOX_PHY_ADDR, MDIO_DEVAD_NONE,
+ SANDBOX_PHY_REG);
+ ut_asserteq(reg, 0);
+
+ return 0;
+}
+
+DM_TEST(dm_test_mdio, DM_TESTF_SCAN_FDT);