diff --git a/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi b/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi index ba0c02489d..f004e9840a 100644 --- a/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi +++ b/arch/arm/dts/stm32mp135f-dk-u-boot.dtsi @@ -16,11 +16,26 @@ u-boot,mmc-env-partition = "u-boot-env"; }; + gpio-keys { + button-user-1 { + label = "User-1"; + linux,code = ; + gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + button-user { + /* update label to match the label requested in board_key_check() */ + label = "User-2"; + }; + }; + leds { + led-blue { + /delete-property/default-state; + }; + led-red { - color = ; gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - default-state = "off"; }; }; }; diff --git a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi index 20728f27ee..a5158fec7e 100644 --- a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi @@ -3,6 +3,7 @@ * Copyright : STMicroelectronics 2022 */ +#include #include "stm32mp15-scmi-u-boot.dtsi" / { @@ -12,20 +13,35 @@ }; config { - u-boot,boot-led = "heartbeat"; - u-boot,error-led = "error"; + u-boot,boot-led = "led-blue"; + u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "u-boot-env"; st,adc_usb_pd = <&adc1 18>, <&adc1 19>; - st,fastboot-gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - st,stm32prog-gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-user-1 { + label = "User-1"; + linux,code = ; + gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + button-user-2 { + label = "User-2"; + linux,code = ; + gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; }; led { - red { - label = "error"; + led-blue { + /delete-property/label; + }; + + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - default-state = "off"; - status = "okay"; }; }; }; diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index a16358266a..f97debaa0e 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -4,6 +4,7 @@ */ #include +#include #include "stm32mp15-u-boot.dtsi" #include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" @@ -14,12 +15,10 @@ }; config { - u-boot,boot-led = "heartbeat"; - u-boot,error-led = "error"; + u-boot,boot-led = "led-blue"; + u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "fip"; st,adc_usb_pd = <&adc1 18>, <&adc1 19>; - st,fastboot-gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - st,stm32prog-gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; }; #if defined(CONFIG_STM32MP15X_STM32IMAGE) || defined(CONFIG_SPL) @@ -48,12 +47,29 @@ }; #endif + gpio-keys { + compatible = "gpio-keys"; + + button-user-1 { + label = "User-1"; + linux,code = ; + gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + button-user-2 { + label = "User-2"; + linux,code = ; + gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + }; + led { - red { - label = "error"; + led-blue { + /delete-property/label; + }; + + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - default-state = "off"; - status = "okay"; }; }; }; diff --git a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi index 4d763bd3a2..7c0d1bab11 100644 --- a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi @@ -3,6 +3,7 @@ * Copyright : STMicroelectronics 2022 */ +#include #include "stm32mp15-scmi-u-boot.dtsi" / { @@ -11,19 +12,36 @@ }; config { - u-boot,boot-led = "heartbeat"; - u-boot,error-led = "error"; + u-boot,boot-led = "led-blue"; + u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "u-boot-env"; - st,fastboot-gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - st,stm32prog-gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-user-1 { + label = "User-1"; + linux,code = ; + gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + button-user-2 { + label = "User-2"; + linux,code = ; + gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; }; led { - red { - label = "error"; + compatible = "gpio-leds"; + + led-blue { + gpios = <&gpiod 9 GPIO_ACTIVE_HIGH>; + }; + + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - default-state = "off"; - status = "okay"; }; }; }; diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi index ef91088aa3..d93359f967 100644 --- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi @@ -4,6 +4,7 @@ */ #include +#include #include "stm32mp15-u-boot.dtsi" #include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" @@ -13,11 +14,9 @@ }; config { - u-boot,boot-led = "heartbeat"; - u-boot,error-led = "error"; + u-boot,boot-led = "led-blue"; + u-boot,error-led = "led-red"; u-boot,mmc-env-partition = "fip"; - st,fastboot-gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - st,stm32prog-gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; }; #if defined(CONFIG_STM32MP15X_STM32IMAGE) || defined(CONFIG_SPL) @@ -43,12 +42,31 @@ }; #endif + gpio-keys { + compatible = "gpio-keys"; + + button-user-1 { + label = "User-1"; + linux,code = ; + gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + button-user-2 { + label = "User-2"; + linux,code = ; + gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + }; + led { - red { - label = "error"; + compatible = "gpio-leds"; + + led-blue { + gpios = <&gpiod 9 GPIO_ACTIVE_HIGH>; + }; + + led-red { gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; - default-state = "off"; - status = "okay"; }; }; }; diff --git a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi index 139940bd5d..3515347e91 100644 --- a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi @@ -33,11 +33,11 @@ label = "fsbl1"; reg = <0x00000000 0x00040000>; }; - partition@80000 { + partition@40000 { label = "fsbl2"; reg = <0x00040000 0x00040000>; }; - partition@100000 { + partition@80000 { label = "ssbl"; reg = <0x00080000 0x00200000>; }; @@ -58,7 +58,7 @@ label = "fsbl2"; reg = <0x00040000 0x00040000>; }; - partition@100000 { + partition@80000 { label = "fip"; reg = <0x00080000 0x00400000>; }; @@ -112,7 +112,7 @@ label = "fip2"; reg = <0x00600000 0x00400000>; }; - partition@1200000 { + partition@a00000 { label = "UBI"; reg = <0x00a00000 0x3f600000>; }; diff --git a/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi b/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi index 2f70b0690d..1b44561932 100644 --- a/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi +++ b/arch/arm/dts/stm32mp15xx-dhcom-u-boot.dtsi @@ -106,15 +106,15 @@ label = "fsbl2"; reg = <0x00040000 0x00040000>; }; - partition@500000 { + partition@80000 { label = "uboot"; reg = <0x00080000 0x00160000>; }; - partition@900000 { + partition@1e0000 { label = "env1"; reg = <0x001E0000 0x00010000>; }; - partition@980000 { + partition@1f0000 { label = "env2"; reg = <0x001F0000 0x00010000>; }; diff --git a/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi b/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi index 552b35db3c..ba84db679e 100644 --- a/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi +++ b/arch/arm/dts/stm32mp15xx-dhcor-u-boot.dtsi @@ -42,15 +42,15 @@ label = "fsbl2"; reg = <0x00040000 0x00040000>; }; - partition@500000 { + partition@80000 { label = "uboot"; reg = <0x00080000 0x00160000>; }; - partition@900000 { + partition@1e0000 { label = "env1"; reg = <0x001E0000 0x00010000>; }; - partition@980000 { + partition@1f0000 { label = "env2"; reg = <0x001F0000 0x00010000>; }; diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig b/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig index 8f91db4b46..589276282e 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig @@ -17,6 +17,7 @@ config CMD_STM32PROG config CMD_STM32PROG_USB bool "support stm32prog over USB" depends on CMD_STM32PROG + depends on USB_GADGET_DOWNLOAD default y help activate the command "stm32prog usb" for STM32MP soc family diff --git a/arch/arm/mach-stm32mp/stm32mp1/Makefile b/arch/arm/mach-stm32mp/stm32mp1/Makefile index 857148747e..ebae50f66c 100644 --- a/arch/arm/mach-stm32mp/stm32mp1/Makefile +++ b/arch/arm/mach-stm32mp/stm32mp1/Makefile @@ -8,7 +8,6 @@ obj-y += cpu.o obj-$(CONFIG_STM32MP13X) += stm32mp13x.o obj-$(CONFIG_STM32MP15X) += stm32mp15x.o -obj-$(CONFIG_STM32_ECDSA_VERIFY) += ecdsa_romapi.o ifdef CONFIG_SPL_BUILD obj-y += spl.o obj-y += tzc400.o diff --git a/arch/arm/mach-stm32mp/stm32mp1/psci.c b/arch/arm/mach-stm32mp/stm32mp1/psci.c index 8cdeb0ab3f..4f2379df45 100644 --- a/arch/arm/mach-stm32mp/stm32mp1/psci.c +++ b/arch/arm/mach-stm32mp/stm32mp1/psci.c @@ -703,6 +703,8 @@ void __secure psci_system_suspend(u32 __always_unused function_id, { u32 saved_mcudivr, saved_pll3cr, saved_pll4cr, saved_mssckselr; u32 gicd_addr = stm32mp_get_gicd_base_address(); + u32 cpu = psci_get_cpu_id(); + u32 sp = (u32)__secure_stack_end - (cpu << ARM_PSCI_STACK_SHIFT); bool iwdg1_wake = false; bool iwdg2_wake = false; bool other_wake = false; @@ -805,4 +807,16 @@ void __secure psci_system_suspend(u32 __always_unused function_id, writel(SYSCFG_CMPENR_MPUEN, STM32_SYSCFG_BASE + SYSCFG_CMPENSETR); clrbits_le32(STM32_SYSCFG_BASE + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); + + /* + * The system has resumed successfully. Rewrite LR register stored + * on stack with 'ep' value, so that on return from this PSCI call, + * the code would jump to that 'ep' resume entry point code path + * instead of the previous 'lr' register content which (e.g. with + * Linux) points to resume failure code path. + * + * See arch/arm/cpu/armv7/psci.S _smc_psci: for the stack layout + * used here, SP-4 is PC, SP-8 is LR, SP-12 is R7, and so on. + */ + writel(ep, sp - 8); } diff --git a/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c b/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c index afc56b02ee..d75ec99d6a 100644 --- a/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c +++ b/arch/arm/mach-stm32mp/stm32mp1/stm32mp15x.c @@ -14,6 +14,7 @@ #include #include #include +#include /* RCC register */ #define RCC_TZCR (STM32_RCC_BASE + 0x00) @@ -41,6 +42,9 @@ #define TZC_REGION_ID_ACCESS0 (STM32_TZC_BASE + 0x114) #define TAMP_CR1 (STM32_TAMP_BASE + 0x00) +#define TAMP_SMCR (STM32_TAMP_BASE + 0x20) +#define TAMP_SMCR_BKPRWDPROT GENMASK(7, 0) +#define TAMP_SMCR_BKPWDPROT GENMASK(23, 16) #define PWR_CR1 (STM32_PWR_BASE + 0x00) #define PWR_MCUCR (STM32_PWR_BASE + 0x14) @@ -136,6 +140,18 @@ static void security_init(void) */ writel(0x0, TAMP_CR1); + /* + * TAMP: Configure non-zero secure protection settings. This is + * checked by BootROM function 35ac on OTP-CLOSED device during + * CPU core 1 release from endless loop. If secure protection + * fields are zero, the core 1 is not released from endless + * loop on second SGI0. + */ + clrsetbits_le32(TAMP_SMCR, + TAMP_SMCR_BKPRWDPROT | TAMP_SMCR_BKPWDPROT, + FIELD_PREP(TAMP_SMCR_BKPRWDPROT, 0x20) | + FIELD_PREP(TAMP_SMCR_BKPWDPROT, 0x20)); + /* GPIOZ: deactivate the security */ writel(BIT(0), RCC_MP_AHB5ENSETR); writel(0x0, GPIOZ_SECCFGR); @@ -322,8 +338,23 @@ void get_soc_name(char name[SOC_NAME_SIZE]) get_cpu_string_offsets(&type, &pkg, &rev); - snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s Rev.%s", - soc_type[type], soc_pkg[pkg], soc_rev[rev]); + if (bsec_dbgswenable()) { + snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s Rev.%s", + soc_type[type], soc_pkg[pkg], soc_rev[rev]); + } else { + /* + * SoC revision is only accessible via DBUMCU IDC register, + * which requires BSEC.DENABLE DBGSWENABLE bit to be set to + * make the register accessible, otherwise an access to the + * register triggers bus fault. As BSEC.DBGSWENABLE is zero + * in case of an OTP-CLOSED system, do NOT set DBGSWENABLE + * bit as this might open a brief window for timing attacks. + * Instead, report that this system is OTP-CLOSED and do not + * report any SoC revision to avoid confusing users. + */ + snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s SEC/C", + soc_type[type], soc_pkg[pkg]); + } } static void setup_soc_type_pkg_rev(void) diff --git a/board/dhelectronics/dh_stm32mp1/board.c b/board/dhelectronics/dh_stm32mp1/board.c index 079dfff038..22af423536 100644 --- a/board/dhelectronics/dh_stm32mp1/board.c +++ b/board/dhelectronics/dh_stm32mp1/board.c @@ -48,12 +48,10 @@ /* SYSCFG registers */ #define SYSCFG_BOOTR 0x00 -#define SYSCFG_PMCSETR 0x04 #define SYSCFG_IOCTRLSETR 0x18 #define SYSCFG_ICNR 0x1C #define SYSCFG_CMPCR 0x20 #define SYSCFG_CMPENSETR 0x24 -#define SYSCFG_PMCCLRR 0x44 #define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0) #define SYSCFG_BOOTR_BOOTPD_SHIFT 4 @@ -69,16 +67,6 @@ #define SYSCFG_CMPENSETR_MPU_EN BIT(0) -#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16) -#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17) - -#define SYSCFG_PMCSETR_ETH_SELMII BIT(20) - -#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21) -#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0 -#define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21) -#define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23) - #define KS_CCR 0x08 #define KS_CCR_EEPROM BIT(9) #define KS_BE0 BIT(12) @@ -685,76 +673,6 @@ void board_quiesce_devices(void) #endif } -/* eth init function : weak called in eqos driver */ -int board_interface_eth_init(struct udevice *dev, - phy_interface_t interface_type) -{ - u8 *syscfg; - u32 value; - bool eth_clk_sel_reg = false; - bool eth_ref_clk_sel_reg = false; - - /* Gigabit Ethernet 125MHz clock selection. */ - eth_clk_sel_reg = dev_read_bool(dev, "st,eth-clk-sel"); - - /* Ethernet 50Mhz RMII clock selection */ - eth_ref_clk_sel_reg = - dev_read_bool(dev, "st,eth-ref-clk-sel"); - - syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); - - if (!syscfg) - return -ENODEV; - - switch (interface_type) { - case PHY_INTERFACE_MODE_MII: - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - debug("%s: PHY_INTERFACE_MODE_MII\n", __func__); - break; - case PHY_INTERFACE_MODE_GMII: - if (eth_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | - SYSCFG_PMCSETR_ETH_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII; - debug("%s: PHY_INTERFACE_MODE_GMII\n", __func__); - break; - case PHY_INTERFACE_MODE_RMII: - if (eth_ref_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_RMII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_RMII; - debug("%s: PHY_INTERFACE_MODE_RMII\n", __func__); - break; - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: - if (eth_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_RGMII | - SYSCFG_PMCSETR_ETH_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_RGMII; - debug("%s: PHY_INTERFACE_MODE_RGMII\n", __func__); - break; - default: - debug("%s: Do not manage %d interface\n", - __func__, interface_type); - /* Do not manage others interfaces */ - return -EINVAL; - } - - /* clear and set ETH configuration bits */ - writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL, - syscfg + SYSCFG_PMCCLRR); - writel(value, syscfg + SYSCFG_PMCSETR); - - return 0; -} - #if defined(CONFIG_OF_BOARD_SETUP) int ft_board_setup(void *blob, struct bd_info *bd) { diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index a17c314dae..db15d78237 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -52,12 +54,10 @@ /* SYSCFG registers */ #define SYSCFG_BOOTR 0x00 -#define SYSCFG_PMCSETR 0x04 #define SYSCFG_IOCTRLSETR 0x18 #define SYSCFG_ICNR 0x1C #define SYSCFG_CMPCR 0x20 #define SYSCFG_CMPENSETR 0x24 -#define SYSCFG_PMCCLRR 0x44 #define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0) #define SYSCFG_BOOTR_BOOTPD_SHIFT 4 @@ -73,16 +73,6 @@ #define SYSCFG_CMPENSETR_MPU_EN BIT(0) -#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16) -#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17) - -#define SYSCFG_PMCSETR_ETH_SELMII BIT(20) - -#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21) -#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0 -#define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21) -#define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23) - #define USB_LOW_THRESHOLD_UV 200000 #define USB_WARNING_LOW_THRESHOLD_UV 660000 #define USB_START_LOW_THRESHOLD_UV 1230000 @@ -150,45 +140,55 @@ int checkboard(void) static void board_key_check(void) { - ofnode node; - struct gpio_desc gpio; + struct udevice *button1 = NULL, *button2 = NULL; enum forced_boot_mode boot_mode = BOOT_NORMAL; + int ret; + + if (!IS_ENABLED(CONFIG_BUTTON)) + return; if (!IS_ENABLED(CONFIG_FASTBOOT) && !IS_ENABLED(CONFIG_CMD_STM32PROG)) return; - node = ofnode_path("/config"); - if (!ofnode_valid(node)) { - log_debug("no /config node?\n"); - return; - } - if (IS_ENABLED(CONFIG_FASTBOOT)) { - if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0, - &gpio, GPIOD_IS_IN)) { - log_debug("could not find a /config/st,fastboot-gpios\n"); - } else { - udelay(20); - if (dm_gpio_get_value(&gpio)) { - log_notice("Fastboot key pressed, "); - boot_mode = BOOT_FASTBOOT; - } + if (IS_ENABLED(CONFIG_CMD_STM32PROG)) + button_get_by_label("User-1", &button1); - dm_gpio_free(NULL, &gpio); + if (IS_ENABLED(CONFIG_FASTBOOT)) + button_get_by_label("User-2", &button2); + + if (!button1 && !button2) + return; + + if (button2) { + if (button_get_state(button2) == BUTTON_ON) { + log_notice("Fastboot key pressed, "); + boot_mode = BOOT_FASTBOOT; } + /* + * On some boards, same gpio is shared betwwen gpio-keys and + * leds, remove the button device to free the gpio for led + * usage + */ + ret = device_remove(button2, DM_REMOVE_NORMAL); + if (ret) + log_err("Can't remove button2 (%d)\n", ret); } - if (IS_ENABLED(CONFIG_CMD_STM32PROG)) { - if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0, - &gpio, GPIOD_IS_IN)) { - log_debug("could not find a /config/st,stm32prog-gpios\n"); - } else { - udelay(20); - if (dm_gpio_get_value(&gpio)) { - log_notice("STM32Programmer key pressed, "); - boot_mode = BOOT_STM32PROG; - } - dm_gpio_free(NULL, &gpio); + + if (button1) { + if (button_get_state(button1) == BUTTON_ON) { + log_notice("STM32Programmer key pressed, "); + boot_mode = BOOT_STM32PROG; } + /* + * On some boards, same gpio is shared betwwen gpio-keys and + * leds, remove the button device to free the gpio for led + * usage + */ + ret = device_remove(button1, DM_REMOVE_NORMAL); + if (ret) + log_err("Can't remove button1 (%d)\n", ret); } + if (boot_mode != BOOT_NORMAL) { log_notice("entering download mode...\n"); clrsetbits_le32(TAMP_BOOT_CONTEXT, @@ -742,76 +742,6 @@ void board_quiesce_devices(void) setup_led(LEDST_OFF); } -/* eth init function : weak called in eqos driver */ -int board_interface_eth_init(struct udevice *dev, - phy_interface_t interface_type) -{ - u8 *syscfg; - u32 value; - bool eth_clk_sel_reg = false; - bool eth_ref_clk_sel_reg = false; - - /* Gigabit Ethernet 125MHz clock selection. */ - eth_clk_sel_reg = dev_read_bool(dev, "st,eth-clk-sel"); - - /* Ethernet 50Mhz RMII clock selection */ - eth_ref_clk_sel_reg = - dev_read_bool(dev, "st,eth-ref-clk-sel"); - - syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); - - if (!syscfg) - return -ENODEV; - - switch (interface_type) { - case PHY_INTERFACE_MODE_MII: - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - log_debug("PHY_INTERFACE_MODE_MII\n"); - break; - case PHY_INTERFACE_MODE_GMII: - if (eth_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | - SYSCFG_PMCSETR_ETH_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII; - log_debug("PHY_INTERFACE_MODE_GMII\n"); - break; - case PHY_INTERFACE_MODE_RMII: - if (eth_ref_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_RMII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_RMII; - log_debug("PHY_INTERFACE_MODE_RMII\n"); - break; - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: - if (eth_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_RGMII | - SYSCFG_PMCSETR_ETH_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_RGMII; - log_debug("PHY_INTERFACE_MODE_RGMII\n"); - break; - default: - log_debug("Do not manage %d interface\n", - interface_type); - /* Do not manage others interfaces */ - return -EINVAL; - } - - /* clear and set ETH configuration bits */ - writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL, - syscfg + SYSCFG_PMCCLRR); - writel(value, syscfg + SYSCFG_PMCSETR); - - return 0; -} - enum env_location env_get_location(enum env_operation op, int prio) { u32 bootmode = get_bootmode(); diff --git a/configs/stm32mp13_defconfig b/configs/stm32mp13_defconfig index c893e272db..caaabf39ef 100644 --- a/configs/stm32mp13_defconfig +++ b/configs/stm32mp13_defconfig @@ -15,6 +15,7 @@ CONFIG_CMD_STM32PROG=y CONFIG_SYS_LOAD_ADDR=0xc2000000 CONFIG_SYS_MEMTEST_START=0xc0000000 CONFIG_SYS_MEMTEST_END=0xc4000000 +# CONFIG_ANDROID_BOOT_IMAGE is not set CONFIG_FIT=y CONFIG_SYS_BOOTM_LEN=0x2000000 CONFIG_DISTRO_DEFAULTS=y @@ -51,8 +52,17 @@ CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_SYS_MMC_ENV_DEV=-1 CONFIG_ENV_MMC_USE_DT=y +CONFIG_BUTTON=y +CONFIG_BUTTON_GPIO=y CONFIG_CLK_SCMI=y CONFIG_SET_DFU_ALT_INFO=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_FASTBOOT_BUF_ADDR=0xc0000000 +CONFIG_FASTBOOT_BUF_SIZE=0x02000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_FASTBOOT_CMD_OEM_FORMAT=y +CONFIG_FASTBOOT_CMD_OEM_PARTCONF=y CONFIG_GPIO_HOG=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_STM32F7=y @@ -92,7 +102,6 @@ CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_VENDOR_NUM=0x0483 CONFIG_USB_GADGET_PRODUCT_NUM=0x5720 CONFIG_USB_GADGET_DWC2_OTG=y -CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_ERRNO_STR=y # CONFIG_LMB_USE_MAX_REGIONS is not set CONFIG_LMB_MEMORY_REGIONS=2 diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index 005f1d55f8..2e22bf8600 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -97,6 +97,8 @@ CONFIG_TFTP_TSIZE=y CONFIG_USE_SERVERIP=y CONFIG_SERVERIP="192.168.1.1" CONFIG_STM32_ADC=y +CONFIG_BUTTON=y +CONFIG_BUTTON_GPIO=y CONFIG_SET_DFU_ALT_INFO=y CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0xC0000000 diff --git a/configs/stm32mp15_defconfig b/configs/stm32mp15_defconfig index 3302b30699..ffe7512650 100644 --- a/configs/stm32mp15_defconfig +++ b/configs/stm32mp15_defconfig @@ -69,6 +69,8 @@ CONFIG_TFTP_TSIZE=y CONFIG_USE_SERVERIP=y CONFIG_SERVERIP="192.168.1.1" CONFIG_STM32_ADC=y +CONFIG_BUTTON=y +CONFIG_BUTTON_GPIO=y CONFIG_CLK_SCMI=y CONFIG_SET_DFU_ALT_INFO=y CONFIG_USB_FUNCTION_FASTBOOT=y diff --git a/configs/stm32mp15_dhcom_basic_defconfig b/configs/stm32mp15_dhcom_basic_defconfig index eb6e367b90..8442f0bfe9 100644 --- a/configs/stm32mp15_dhcom_basic_defconfig +++ b/configs/stm32mp15_dhcom_basic_defconfig @@ -164,6 +164,8 @@ CONFIG_DM_USB_GADGET=y CONFIG_SPL_DM_USB_GADGET=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y CONFIG_USB_DWC2=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_ASIX=y diff --git a/configs/stm32mp15_dhcor_basic_defconfig b/configs/stm32mp15_dhcor_basic_defconfig index ab92924a9b..91b64f7537 100644 --- a/configs/stm32mp15_dhcor_basic_defconfig +++ b/configs/stm32mp15_dhcor_basic_defconfig @@ -164,6 +164,8 @@ CONFIG_DM_USB_GADGET=y CONFIG_SPL_DM_USB_GADGET=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y CONFIG_USB_DWC2=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_ASIX=y diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig index 84b0854b55..74deaaba2e 100644 --- a/configs/stm32mp15_trusted_defconfig +++ b/configs/stm32mp15_trusted_defconfig @@ -70,6 +70,8 @@ CONFIG_TFTP_TSIZE=y CONFIG_USE_SERVERIP=y CONFIG_SERVERIP="192.168.1.1" CONFIG_STM32_ADC=y +CONFIG_BUTTON=y +CONFIG_BUTTON_GPIO=y CONFIG_CLK_SCMI=y CONFIG_SET_DFU_ALT_INFO=y CONFIG_USB_FUNCTION_FASTBOOT=y diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c index a722a3836f..1ce9607785 100644 --- a/drivers/memory/stm32-fmc2-ebi.c +++ b/drivers/memory/stm32-fmc2-ebi.c @@ -22,8 +22,15 @@ #define FMC2_BCR(x) ((x) * 0x8 + FMC2_BCR1) #define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1) #define FMC2_PCSCNTR 0x20 +#define FMC2_CFGR 0x20 +#define FMC2_SR 0x84 #define FMC2_BWTR1 0x104 #define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1) +#define FMC2_SECCFGR 0x300 +#define FMC2_CIDCFGR0 0x30c +#define FMC2_CIDCFGR(x) ((x) * 0x8 + FMC2_CIDCFGR0) +#define FMC2_SEMCR0 0x310 +#define FMC2_SEMCR(x) ((x) * 0x8 + FMC2_SEMCR0) /* Register: FMC2_BCR1 */ #define FMC2_BCR1_CCLKEN BIT(20) @@ -44,6 +51,7 @@ #define FMC2_BCR_ASYNCWAIT BIT(15) #define FMC2_BCR_CPSIZE GENMASK(18, 16) #define FMC2_BCR_CBURSTRW BIT(19) +#define FMC2_BCR_CSCOUNT GENMASK(21, 20) #define FMC2_BCR_NBLSET GENMASK(23, 22) /* Register: FMC2_BTRx/FMC2_BWTRx */ @@ -60,8 +68,28 @@ #define FMC2_PCSCNTR_CSCOUNT GENMASK(15, 0) #define FMC2_PCSCNTR_CNTBEN(x) BIT((x) + 16) +/* Register: FMC2_CFGR */ +#define FMC2_CFGR_CLKDIV GENMASK(19, 16) +#define FMC2_CFGR_CCLKEN BIT(20) +#define FMC2_CFGR_FMC2EN BIT(31) + +/* Register: FMC2_SR */ +#define FMC2_SR_ISOST GENMASK(1, 0) + +/* Register: FMC2_CIDCFGR */ +#define FMC2_CIDCFGR_CFEN BIT(0) +#define FMC2_CIDCFGR_SEMEN BIT(1) +#define FMC2_CIDCFGR_SCID GENMASK(6, 4) +#define FMC2_CIDCFGR_SEMWLC1 BIT(17) + +/* Register: FMC2_SEMCR */ +#define FMC2_SEMCR_SEM_MUTEX BIT(0) +#define FMC2_SEMCR_SEMCID GENMASK(6, 4) + #define FMC2_MAX_EBI_CE 4 #define FMC2_MAX_BANKS 5 +#define FMC2_MAX_RESOURCES 6 +#define FMC2_CID1 1 #define FMC2_BCR_CPSIZE_0 0x0 #define FMC2_BCR_CPSIZE_128 0x1 @@ -76,6 +104,11 @@ #define FMC2_BCR_MTYP_PSRAM 0x1 #define FMC2_BCR_MTYP_NOR 0x2 +#define FMC2_BCR_CSCOUNT_0 0x0 +#define FMC2_BCR_CSCOUNT_1 0x1 +#define FMC2_BCR_CSCOUNT_64 0x2 +#define FMC2_BCR_CSCOUNT_256 0x3 + #define FMC2_BXTR_EXTMOD_A 0x0 #define FMC2_BXTR_EXTMOD_B 0x1 #define FMC2_BXTR_EXTMOD_C 0x2 @@ -90,6 +123,7 @@ #define FMC2_BTR_CLKDIV_MAX 0xf #define FMC2_BTR_DATLAT_MAX 0xf #define FMC2_PCSCNTR_CSCOUNT_MAX 0xff +#define FMC2_CFGR_CLKDIV_MAX 0xf enum stm32_fmc2_ebi_bank { FMC2_EBI1 = 0, @@ -103,7 +137,8 @@ enum stm32_fmc2_ebi_register_type { FMC2_REG_BCR = 1, FMC2_REG_BTR, FMC2_REG_BWTR, - FMC2_REG_PCSCNTR + FMC2_REG_PCSCNTR, + FMC2_REG_CFGR }; enum stm32_fmc2_ebi_transaction_type { @@ -134,10 +169,30 @@ enum stm32_fmc2_ebi_cpsize { FMC2_CPSIZE_1024 = 1024 }; +enum stm32_fmc2_ebi_cscount { + FMC2_CSCOUNT_0 = 0, + FMC2_CSCOUNT_1 = 1, + FMC2_CSCOUNT_64 = 64, + FMC2_CSCOUNT_256 = 256 +}; + +struct stm32_fmc2_ebi; + +struct stm32_fmc2_ebi_data { + const struct stm32_fmc2_prop *child_props; + unsigned int nb_child_props; + u32 fmc2_enable_reg; + u32 fmc2_enable_bit; + int (*nwait_used_by_ctrls)(struct stm32_fmc2_ebi *ebi); + int (*check_rif)(struct stm32_fmc2_ebi *ebi, u32 resource); +}; + struct stm32_fmc2_ebi { struct clk clk; fdt_addr_t io_base; + const struct stm32_fmc2_ebi_data *data; u8 bank_assigned; + bool access_granted; }; /* @@ -209,6 +264,28 @@ static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi, return -EINVAL; } +static int stm32_fmc2_ebi_mp25_check_cclk(struct stm32_fmc2_ebi *ebi, + const struct stm32_fmc2_prop *prop, + int cs) +{ + if (!ebi->access_granted) + return -EACCES; + + return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs); +} + +static int stm32_fmc2_ebi_mp25_check_clk_period(struct stm32_fmc2_ebi *ebi, + const struct stm32_fmc2_prop *prop, + int cs) +{ + u32 cfgr = readl(ebi->io_base + FMC2_CFGR); + + if (cfgr & FMC2_CFGR_CCLKEN && !ebi->access_granted) + return -EACCES; + + return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs); +} + static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi, const struct stm32_fmc2_prop *prop, int cs) @@ -296,6 +373,24 @@ static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi, return DIV_ROUND_UP(nb_clk_cycles, clk_period); } +static u32 stm32_fmc2_ebi_mp25_ns_to_clk_period(struct stm32_fmc2_ebi *ebi, + int cs, u32 setup) +{ + u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup); + u32 cfgr = readl(ebi->io_base + FMC2_CFGR); + u32 clk_period; + + if (cfgr & FMC2_CFGR_CCLKEN) { + clk_period = FIELD_GET(FMC2_CFGR_CLKDIV, cfgr) + 1; + } else { + u32 btr = readl(ebi->io_base + FMC2_BTR(cs)); + + clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1; + } + + return DIV_ROUND_UP(nb_clk_cycles, clk_period); +} + static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg) { switch (reg_type) { @@ -311,6 +406,9 @@ static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg) case FMC2_REG_PCSCNTR: *reg = FMC2_PCSCNTR; break; + case FMC2_REG_CFGR: + *reg = FMC2_CFGR; + break; default: return -EINVAL; } @@ -649,6 +747,26 @@ static int stm32_fmc2_ebi_set_clk_period(struct stm32_fmc2_ebi *ebi, return 0; } +static int stm32_fmc2_ebi_mp25_set_clk_period(struct stm32_fmc2_ebi *ebi, + const struct stm32_fmc2_prop *prop, + int cs, u32 setup) +{ + u32 cfgr = readl(ebi->io_base + FMC2_CFGR); + u32 val; + + if (cfgr & FMC2_CFGR_CCLKEN) { + val = setup ? clamp_val(setup - 1, 1, FMC2_CFGR_CLKDIV_MAX) : 1; + val = FIELD_PREP(FMC2_CFGR_CLKDIV, val); + clrsetbits_le32(ebi->io_base + FMC2_CFGR, FMC2_CFGR_CLKDIV, val); + } else { + val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1; + val = FIELD_PREP(FMC2_BTR_CLKDIV, val); + clrsetbits_le32(ebi->io_base + FMC2_BTR(cs), FMC2_BTR_CLKDIV, val); + } + + return 0; +} + static int stm32_fmc2_ebi_set_data_latency(struct stm32_fmc2_ebi *ebi, const struct stm32_fmc2_prop *prop, int cs, u32 setup) @@ -689,6 +807,27 @@ static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi, return 0; } +static int stm32_fmc2_ebi_mp25_set_max_low_pulse(struct stm32_fmc2_ebi *ebi, + const struct stm32_fmc2_prop *prop, + int cs, u32 setup) +{ + u32 val; + + if (setup == FMC2_CSCOUNT_0) + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_0); + else if (setup == FMC2_CSCOUNT_1) + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_1); + else if (setup <= FMC2_CSCOUNT_64) + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_64); + else + val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_256); + + clrsetbits_le32(ebi->io_base + FMC2_BCR(cs), + FMC2_BCR_CSCOUNT, val); + + return 0; +} + static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = { /* st,fmc2-ebi-cs-trans-type must be the first property */ { @@ -854,6 +993,235 @@ static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = { }, }; +static const struct stm32_fmc2_prop stm32_fmc2_mp25_child_props[] = { + /* st,fmc2-ebi-cs-trans-type must be the first property */ + { + .name = "st,fmc2-ebi-cs-transaction-type", + .mprop = true, + .set = stm32_fmc2_ebi_set_trans_type, + }, + { + .name = "st,fmc2-ebi-cs-cclk-enable", + .bprop = true, + .reg_type = FMC2_REG_CFGR, + .reg_mask = FMC2_CFGR_CCLKEN, + .check = stm32_fmc2_ebi_mp25_check_cclk, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-mux-enable", + .bprop = true, + .reg_type = FMC2_REG_BCR, + .reg_mask = FMC2_BCR_MUXEN, + .check = stm32_fmc2_ebi_check_mux, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-buswidth", + .reset_val = FMC2_BUSWIDTH_16, + .set = stm32_fmc2_ebi_set_buswidth, + }, + { + .name = "st,fmc2-ebi-cs-waitpol-high", + .bprop = true, + .reg_type = FMC2_REG_BCR, + .reg_mask = FMC2_BCR_WAITPOL, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-waitcfg-enable", + .bprop = true, + .reg_type = FMC2_REG_BCR, + .reg_mask = FMC2_BCR_WAITCFG, + .check = stm32_fmc2_ebi_check_waitcfg, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-wait-enable", + .bprop = true, + .reg_type = FMC2_REG_BCR, + .reg_mask = FMC2_BCR_WAITEN, + .check = stm32_fmc2_ebi_check_sync_trans, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-asyncwait-enable", + .bprop = true, + .reg_type = FMC2_REG_BCR, + .reg_mask = FMC2_BCR_ASYNCWAIT, + .check = stm32_fmc2_ebi_check_async_trans, + .set = stm32_fmc2_ebi_set_bit_field, + }, + { + .name = "st,fmc2-ebi-cs-cpsize", + .check = stm32_fmc2_ebi_check_cpsize, + .set = stm32_fmc2_ebi_set_cpsize, + }, + { + .name = "st,fmc2-ebi-cs-byte-lane-setup-ns", + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_bl_setup, + }, + { + .name = "st,fmc2-ebi-cs-address-setup-ns", + .reg_type = FMC2_REG_BTR, + .reset_val = FMC2_BXTR_ADDSET_MAX, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_address_setup, + }, + { + .name = "st,fmc2-ebi-cs-address-hold-ns", + .reg_type = FMC2_REG_BTR, + .reset_val = FMC2_BXTR_ADDHLD_MAX, + .check = stm32_fmc2_ebi_check_address_hold, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_address_hold, + }, + { + .name = "st,fmc2-ebi-cs-data-setup-ns", + .reg_type = FMC2_REG_BTR, + .reset_val = FMC2_BXTR_DATAST_MAX, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_data_setup, + }, + { + .name = "st,fmc2-ebi-cs-bus-turnaround-ns", + .reg_type = FMC2_REG_BTR, + .reset_val = FMC2_BXTR_BUSTURN_MAX + 1, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_bus_turnaround, + }, + { + .name = "st,fmc2-ebi-cs-data-hold-ns", + .reg_type = FMC2_REG_BTR, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_data_hold, + }, + { + .name = "st,fmc2-ebi-cs-clk-period-ns", + .reset_val = FMC2_CFGR_CLKDIV_MAX + 1, + .check = stm32_fmc2_ebi_mp25_check_clk_period, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_mp25_set_clk_period, + }, + { + .name = "st,fmc2-ebi-cs-data-latency-ns", + .check = stm32_fmc2_ebi_check_sync_trans, + .calculate = stm32_fmc2_ebi_mp25_ns_to_clk_period, + .set = stm32_fmc2_ebi_set_data_latency, + }, + { + .name = "st,fmc2-ebi-cs-write-address-setup-ns", + .reg_type = FMC2_REG_BWTR, + .reset_val = FMC2_BXTR_ADDSET_MAX, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_address_setup, + }, + { + .name = "st,fmc2-ebi-cs-write-address-hold-ns", + .reg_type = FMC2_REG_BWTR, + .reset_val = FMC2_BXTR_ADDHLD_MAX, + .check = stm32_fmc2_ebi_check_address_hold, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_address_hold, + }, + { + .name = "st,fmc2-ebi-cs-write-data-setup-ns", + .reg_type = FMC2_REG_BWTR, + .reset_val = FMC2_BXTR_DATAST_MAX, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_data_setup, + }, + { + .name = "st,fmc2-ebi-cs-write-bus-turnaround-ns", + .reg_type = FMC2_REG_BWTR, + .reset_val = FMC2_BXTR_BUSTURN_MAX + 1, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_bus_turnaround, + }, + { + .name = "st,fmc2-ebi-cs-write-data-hold-ns", + .reg_type = FMC2_REG_BWTR, + .check = stm32_fmc2_ebi_check_async_trans, + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_set_data_hold, + }, + { + .name = "st,fmc2-ebi-cs-max-low-pulse-ns", + .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, + .set = stm32_fmc2_ebi_mp25_set_max_low_pulse, + }, +}; + +static int stm32_fmc2_ebi_mp25_check_rif(struct stm32_fmc2_ebi *ebi, u32 resource) +{ + u32 seccfgr, cidcfgr, semcr; + int cid; + + if (resource >= FMC2_MAX_RESOURCES) + return -EINVAL; + + seccfgr = readl(ebi->io_base + FMC2_SECCFGR); + if (seccfgr & BIT(resource)) { + if (resource) + log_err("resource %d is configured as secure\n", + resource); + + return -EACCES; + } + + cidcfgr = readl(ebi->io_base + FMC2_CIDCFGR(resource)); + if (!(cidcfgr & FMC2_CIDCFGR_CFEN)) + /* CID filtering is turned off: access granted */ + return 0; + + if (!(cidcfgr & FMC2_CIDCFGR_SEMEN)) { + /* Static CID mode */ + cid = FIELD_GET(FMC2_CIDCFGR_SCID, cidcfgr); + if (cid != FMC2_CID1) { + if (resource) + log_err("static CID%d set for resource %d\n", + cid, resource); + + return -EACCES; + } + + return 0; + } + + /* Pass-list with semaphore mode */ + if (!(cidcfgr & FMC2_CIDCFGR_SEMWLC1)) { + if (resource) + log_err("CID1 is block-listed for resource %d\n", + resource); + + return -EACCES; + } + + semcr = readl(ebi->io_base + FMC2_SEMCR(resource)); + if (!(semcr & FMC2_SEMCR_SEM_MUTEX)) { + setbits_le32(ebi->io_base + FMC2_SEMCR(resource), + FMC2_SEMCR_SEM_MUTEX); + semcr = readl(ebi->io_base + FMC2_SEMCR(resource)); + } + + cid = FIELD_GET(FMC2_SEMCR_SEMCID, semcr); + if (cid != FMC2_CID1) { + if (resource) + log_err("resource %d is already used by CID%d\n", + resource, cid); + + return -EACCES; + } + + return 0; +} + static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi, ofnode node, const struct stm32_fmc2_prop *prop, @@ -915,7 +1283,7 @@ static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs) } /* NWAIT signal can not be connected to EBI controller and NAND controller */ -static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi) +static int stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi) { unsigned int cs; u32 bcr; @@ -926,16 +1294,22 @@ static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi) bcr = readl(ebi->io_base + FMC2_BCR(cs)); if ((bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT) && - ebi->bank_assigned & BIT(FMC2_NAND)) - return true; + ebi->bank_assigned & BIT(FMC2_NAND)) { + log_err("NWAIT signal connected to EBI and NAND controllers\n"); + return -EINVAL; + } } - return false; + return 0; } static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi) { - setbits_le32(ebi->io_base + FMC2_BCR1, FMC2_BCR1_FMC2EN); + if (!ebi->access_granted) + return; + + setbits_le32(ebi->io_base + ebi->data->fmc2_enable_reg, + ebi->data->fmc2_enable_bit); } static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi, @@ -946,8 +1320,8 @@ static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi, stm32_fmc2_ebi_disable_bank(ebi, cs); - for (i = 0; i < ARRAY_SIZE(stm32_fmc2_child_props); i++) { - const struct stm32_fmc2_prop *p = &stm32_fmc2_child_props[i]; + for (i = 0; i < ebi->data->nb_child_props; i++) { + const struct stm32_fmc2_prop *p = &ebi->data->child_props[i]; ret = stm32_fmc2_ebi_parse_prop(ebi, node, p, cs); if (ret) { @@ -987,6 +1361,14 @@ static int stm32_fmc2_ebi_parse_dt(struct udevice *dev, return -EINVAL; } + if (ebi->data->check_rif) { + ret = ebi->data->check_rif(ebi, bank + 1); + if (ret) { + dev_err(dev, "bank access failed: %d\n", bank); + return ret; + } + } + if (bank < FMC2_MAX_EBI_CE) { ret = stm32_fmc2_ebi_setup_cs(ebi, child, bank); if (ret) { @@ -1004,9 +1386,10 @@ static int stm32_fmc2_ebi_parse_dt(struct udevice *dev, return -ENODEV; } - if (stm32_fmc2_ebi_nwait_used_by_ctrls(ebi)) { - dev_err(dev, "NWAIT signal connected to EBI and NAND controllers\n"); - return -EINVAL; + if (ebi->data->nwait_used_by_ctrls) { + ret = ebi->data->nwait_used_by_ctrls(ebi); + if (ret) + return ret; } stm32_fmc2_ebi_enable(ebi); @@ -1020,6 +1403,10 @@ static int stm32_fmc2_ebi_probe(struct udevice *dev) struct reset_ctl reset; int ret; + ebi->data = (void *)dev_get_driver_data(dev); + if (!ebi->data) + return -EINVAL; + ebi->io_base = dev_read_addr(dev); if (ebi->io_base == FDT_ADDR_T_NONE) return -EINVAL; @@ -1039,11 +1426,49 @@ static int stm32_fmc2_ebi_probe(struct udevice *dev) reset_deassert(&reset); } + /* Check if CFGR register can be modified */ + ebi->access_granted = true; + if (ebi->data->check_rif) { + ret = ebi->data->check_rif(ebi, 0); + if (ret) { + ebi->access_granted = false; + + /* In case of CFGR is secure, just check that the FMC2 is enabled */ + if (readl(ebi->io_base + FMC2_SR) & FMC2_SR_ISOST) { + dev_err(dev, "FMC2 is not ready to be used.\n"); + return -EACCES; + } + } + } + return stm32_fmc2_ebi_parse_dt(dev, ebi); } +static const struct stm32_fmc2_ebi_data stm32_fmc2_ebi_mp1_data = { + .child_props = stm32_fmc2_child_props, + .nb_child_props = ARRAY_SIZE(stm32_fmc2_child_props), + .fmc2_enable_reg = FMC2_BCR1, + .fmc2_enable_bit = FMC2_BCR1_FMC2EN, + .nwait_used_by_ctrls = stm32_fmc2_ebi_nwait_used_by_ctrls, +}; + +static const struct stm32_fmc2_ebi_data stm32_fmc2_ebi_mp25_data = { + .child_props = stm32_fmc2_mp25_child_props, + .nb_child_props = ARRAY_SIZE(stm32_fmc2_mp25_child_props), + .fmc2_enable_reg = FMC2_CFGR, + .fmc2_enable_bit = FMC2_CFGR_FMC2EN, + .check_rif = stm32_fmc2_ebi_mp25_check_rif, +}; + static const struct udevice_id stm32_fmc2_ebi_match[] = { - {.compatible = "st,stm32mp1-fmc2-ebi"}, + { + .compatible = "st,stm32mp1-fmc2-ebi", + .data = (ulong)&stm32_fmc2_ebi_mp1_data, + }, + { + .compatible = "st,stm32mp25-fmc2-ebi", + .data = (ulong)&stm32_fmc2_ebi_mp25_data, + }, { /* Sentinel */ } }; diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c index a2b111a843..39ae79ba12 100644 --- a/drivers/mmc/stm32_sdmmc2.c +++ b/drivers/mmc/stm32_sdmmc2.c @@ -220,9 +220,9 @@ static void stm32_sdmmc2_start_data(struct udevice *dev, if (data->flags & MMC_DATA_READ) { data_ctrl |= SDMMC_DCTRL_DTDIR; - idmabase0 = (u32)data->dest; + idmabase0 = (u32)(long)data->dest; } else { - idmabase0 = (u32)data->src; + idmabase0 = (u32)(long)data->src; } /* Set the SDMMC DataLength value */ @@ -463,8 +463,8 @@ retry_cmd: stm32_sdmmc2_start_cmd(dev, cmd, cmdat, &ctx); - dev_dbg(dev, "send cmd %d data: 0x%x @ 0x%x\n", - cmd->cmdidx, data ? ctx.data_length : 0, (unsigned int)data); + dev_dbg(dev, "send cmd %d data: 0x%x @ 0x%p\n", + cmd->cmdidx, data ? ctx.data_length : 0, data); ret = stm32_sdmmc2_end_cmd(dev, cmd, &ctx); @@ -789,6 +789,7 @@ static int stm32_sdmmc2_bind(struct udevice *dev) static const struct udevice_id stm32_sdmmc2_ids[] = { { .compatible = "st,stm32-sdmmc2" }, + { .compatible = "st,stm32mp25-sdmmc2" }, { } }; diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index 3528824575..d284b8cbb1 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -34,7 +34,7 @@ #define FMC2_RB_DELAY_US 30 /* Max chip enable */ -#define FMC2_MAX_CE 2 +#define FMC2_MAX_CE 4 /* Timings */ #define FMC2_THIZ 1 @@ -160,6 +160,11 @@ static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip) return container_of(chip, struct stm32_fmc2_nand, chip); } +struct stm32_fmc2_nfc_data { + int max_ncs; + struct udevice *(*get_cdev)(struct udevice *dev); +}; + struct stm32_fmc2_nfc { struct nand_hw_control base; struct stm32_fmc2_nand nand; @@ -169,6 +174,7 @@ struct stm32_fmc2_nfc { fdt_addr_t cmd_base[FMC2_MAX_CE]; fdt_addr_t addr_base[FMC2_MAX_CE]; struct clk clk; + const struct stm32_fmc2_nfc_data *data; u8 cs_assigned; int cs_sel; @@ -815,7 +821,7 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, ofnode node) } for (i = 0; i < nand->ncs; i++) { - if (cs[i] >= FMC2_MAX_CE) { + if (cs[i] >= nfc->data->max_ncs) { log_err("Invalid reg value: %d\n", nand->cs_used[i]); return -EINVAL; } @@ -906,10 +912,18 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev) spin_lock_init(&nfc->controller.lock); init_waitqueue_head(&nfc->controller.wq); - cdev = stm32_fmc2_nfc_get_cdev(dev); - if (!cdev) + nfc->data = (void *)dev_get_driver_data(dev); + if (!nfc->data) return -EINVAL; + if (nfc->data->get_cdev) { + cdev = nfc->data->get_cdev(dev); + if (!cdev) + return -EINVAL; + } else { + cdev = dev->parent; + } + ret = stm32_fmc2_nfc_parse_dt(dev, nfc); if (ret) return ret; @@ -921,7 +935,7 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev) if (dev == cdev) start_region = 1; - for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE; + for (chip_cs = 0, mem_region = start_region; chip_cs < nfc->data->max_ncs; chip_cs++, mem_region += 3) { if (!(nfc->cs_assigned & BIT(chip_cs))) continue; @@ -1033,9 +1047,28 @@ static int stm32_fmc2_nfc_probe(struct udevice *dev) return nand_register(0, mtd); } +static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp1_data = { + .max_ncs = 2, + .get_cdev = stm32_fmc2_nfc_get_cdev, +}; + +static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp25_data = { + .max_ncs = 4, +}; + static const struct udevice_id stm32_fmc2_nfc_match[] = { - { .compatible = "st,stm32mp15-fmc2" }, - { .compatible = "st,stm32mp1-fmc2-nfc" }, + { + .compatible = "st,stm32mp15-fmc2", + .data = (ulong)&stm32_fmc2_nfc_mp1_data, + }, + { + .compatible = "st,stm32mp1-fmc2-nfc", + .data = (ulong)&stm32_fmc2_nfc_mp1_data, + }, + { + .compatible = "st,stm32mp25-fmc2-nfc", + .data = (ulong)&stm32_fmc2_nfc_mp25_data, + }, { /* Sentinel */ } }; diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6677366ebd..dc3404519d 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o +obj-$(CONFIG_DWC_ETH_QOS_STM32) += dwc_eth_qos_stm32.o obj-$(CONFIG_E1000) += e1000.o obj-$(CONFIG_E1000_SPI) += e1000_spi.o obj-$(CONFIG_EEPRO100) += eepro100.o diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 67d80d987f..32a5d52165 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -295,58 +295,6 @@ err: #endif } -static int eqos_start_clks_stm32(struct udevice *dev) -{ -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(dev); - int ret; - - debug("%s(dev=%p):\n", __func__, dev); - - ret = clk_enable(&eqos->clk_master_bus); - if (ret < 0) { - pr_err("clk_enable(clk_master_bus) failed: %d\n", ret); - goto err; - } - - ret = clk_enable(&eqos->clk_rx); - if (ret < 0) { - pr_err("clk_enable(clk_rx) failed: %d\n", ret); - goto err_disable_clk_master_bus; - } - - ret = clk_enable(&eqos->clk_tx); - if (ret < 0) { - pr_err("clk_enable(clk_tx) failed: %d\n", ret); - goto err_disable_clk_rx; - } - - if (clk_valid(&eqos->clk_ck) && !eqos->clk_ck_enabled) { - ret = clk_enable(&eqos->clk_ck); - if (ret < 0) { - pr_err("clk_enable(clk_ck) failed: %d\n", ret); - goto err_disable_clk_tx; - } - eqos->clk_ck_enabled = true; - } -#endif - - debug("%s: OK\n", __func__); - return 0; - -#ifdef CONFIG_CLK -err_disable_clk_tx: - clk_disable(&eqos->clk_tx); -err_disable_clk_rx: - clk_disable(&eqos->clk_rx); -err_disable_clk_master_bus: - clk_disable(&eqos->clk_master_bus); -err: - debug("%s: FAILED: %d\n", __func__, ret); - return ret; -#endif -} - static int eqos_stop_clks_tegra186(struct udevice *dev) { #ifdef CONFIG_CLK @@ -365,22 +313,6 @@ static int eqos_stop_clks_tegra186(struct udevice *dev) return 0; } -static int eqos_stop_clks_stm32(struct udevice *dev) -{ -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(dev); - - debug("%s(dev=%p):\n", __func__, dev); - - clk_disable(&eqos->clk_tx); - clk_disable(&eqos->clk_rx); - clk_disable(&eqos->clk_master_bus); -#endif - - debug("%s: OK\n", __func__); - return 0; -} - static int eqos_start_resets_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -493,17 +425,6 @@ static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev) #endif } -static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) -{ -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(dev); - - return clk_get_rate(&eqos->clk_master_bus); -#else - return 0; -#endif -} - static int eqos_set_full_duplex(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -1415,57 +1336,6 @@ err_free_reset_eqos: return ret; } -static int eqos_probe_resources_stm32(struct udevice *dev) -{ - struct eqos_priv *eqos = dev_get_priv(dev); - int ret; - phy_interface_t interface; - - debug("%s(dev=%p):\n", __func__, dev); - - interface = eqos->config->interface(dev); - - if (interface == PHY_INTERFACE_MODE_NA) { - pr_err("Invalid PHY interface\n"); - return -EINVAL; - } - - ret = board_interface_eth_init(dev, interface); - if (ret) - return -EINVAL; - - ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); - if (ret) { - pr_err("clk_get_by_name(master_bus) failed: %d\n", ret); - goto err_probe; - } - - ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); - if (ret) { - pr_err("clk_get_by_name(rx) failed: %d\n", ret); - goto err_probe; - } - - ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); - if (ret) { - pr_err("clk_get_by_name(tx) failed: %d\n", ret); - goto err_probe; - } - - /* Get ETH_CLK clocks (optional) */ - ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); - if (ret) - pr_warn("No phy clock provided %d", ret); - - debug("%s: OK\n", __func__); - return 0; - -err_probe: - - debug("%s: returns %d\n", __func__, ret); - return ret; -} - static phy_interface_t eqos_get_interface_tegra186(const struct udevice *dev) { return PHY_INTERFACE_MODE_MII; @@ -1484,12 +1354,6 @@ static int eqos_remove_resources_tegra186(struct udevice *dev) return 0; } -static int eqos_remove_resources_stm32(struct udevice *dev) -{ - debug("%s(dev=%p):\n", __func__, dev); - return 0; -} - static int eqos_probe(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -1633,35 +1497,6 @@ static const struct eqos_config __maybe_unused eqos_tegra186_config = { .ops = &eqos_tegra186_ops }; -static struct eqos_ops eqos_stm32_ops = { - .eqos_inval_desc = eqos_inval_desc_generic, - .eqos_flush_desc = eqos_flush_desc_generic, - .eqos_inval_buffer = eqos_inval_buffer_generic, - .eqos_flush_buffer = eqos_flush_buffer_generic, - .eqos_probe_resources = eqos_probe_resources_stm32, - .eqos_remove_resources = eqos_remove_resources_stm32, - .eqos_stop_resets = eqos_null_ops, - .eqos_start_resets = eqos_null_ops, - .eqos_stop_clks = eqos_stop_clks_stm32, - .eqos_start_clks = eqos_start_clks_stm32, - .eqos_calibrate_pads = eqos_null_ops, - .eqos_disable_calibration = eqos_null_ops, - .eqos_set_tx_clk_speed = eqos_null_ops, - .eqos_get_enetaddr = eqos_null_ops, - .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 -}; - -static const struct eqos_config __maybe_unused eqos_stm32_config = { - .reg_access_always_ok = false, - .mdio_wait = 10000, - .swr_wait = 50, - .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, - .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, - .axi_bus_width = EQOS_AXI_WIDTH_64, - .interface = dev_read_phy_mode, - .ops = &eqos_stm32_ops -}; - static const struct udevice_id eqos_ids[] = { #if IS_ENABLED(CONFIG_DWC_ETH_QOS_TEGRA186) { @@ -1670,9 +1505,13 @@ static const struct udevice_id eqos_ids[] = { }, #endif #if IS_ENABLED(CONFIG_DWC_ETH_QOS_STM32) + { + .compatible = "st,stm32mp13-dwmac", + .data = (ulong)&eqos_stm32mp13_config + }, { .compatible = "st,stm32mp1-dwmac", - .data = (ulong)&eqos_stm32_config + .data = (ulong)&eqos_stm32mp15_config }, #endif #if IS_ENABLED(CONFIG_DWC_ETH_QOS_IMX) diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h index e3222e1e17..8b3d0d464d 100644 --- a/drivers/net/dwc_eth_qos.h +++ b/drivers/net/dwc_eth_qos.h @@ -290,4 +290,6 @@ int eqos_null_ops(struct udevice *dev); extern struct eqos_config eqos_imx_config; extern struct eqos_config eqos_rockchip_config; extern struct eqos_config eqos_qcom_config; +extern struct eqos_config eqos_stm32mp13_config; +extern struct eqos_config eqos_stm32mp15_config; extern struct eqos_config eqos_jh7110_config; diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c new file mode 100644 index 0000000000..fbc08bba1d --- /dev/null +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024, Marek Vasut + * + * This is code moved from drivers/net/dwc_eth_qos.c , which is: + * Copyright (c) 2016, NVIDIA CORPORATION. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dwc_eth_qos.h" + +/* SYSCFG registers */ +#define SYSCFG_PMCSETR 0x04 +#define SYSCFG_PMCCLRR_MP13 0x08 +#define SYSCFG_PMCCLRR_MP15 0x44 + +#define SYSCFG_PMCSETR_ETH1_MASK GENMASK(23, 16) +#define SYSCFG_PMCSETR_ETH2_MASK GENMASK(31, 24) + +#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16) +#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17) + +/* STM32MP15xx specific bit */ +#define SYSCFG_PMCSETR_ETH_SELMII BIT(20) + +#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21) +#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0x0 +#define SYSCFG_PMCSETR_ETH_SEL_RGMII 0x1 +#define SYSCFG_PMCSETR_ETH_SEL_RMII 0x4 + +static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) +{ + struct eqos_priv __maybe_unused *eqos = dev_get_priv(dev); + + if (!CONFIG_IS_ENABLED(CLK)) + return 0; + + return clk_get_rate(&eqos->clk_master_bus); +} + +static int eqos_start_clks_stm32(struct udevice *dev) +{ + struct eqos_priv __maybe_unused *eqos = dev_get_priv(dev); + int ret; + + if (!CONFIG_IS_ENABLED(CLK)) + return 0; + + dev_dbg(dev, "%s:\n", __func__); + + ret = clk_enable(&eqos->clk_master_bus); + if (ret < 0) { + dev_err(dev, "clk_enable(clk_master_bus) failed: %d\n", ret); + goto err; + } + + ret = clk_enable(&eqos->clk_rx); + if (ret < 0) { + dev_err(dev, "clk_enable(clk_rx) failed: %d\n", ret); + goto err_disable_clk_master_bus; + } + + ret = clk_enable(&eqos->clk_tx); + if (ret < 0) { + dev_err(dev, "clk_enable(clk_tx) failed: %d\n", ret); + goto err_disable_clk_rx; + } + + if (clk_valid(&eqos->clk_ck) && !eqos->clk_ck_enabled) { + ret = clk_enable(&eqos->clk_ck); + if (ret < 0) { + dev_err(dev, "clk_enable(clk_ck) failed: %d\n", ret); + goto err_disable_clk_tx; + } + eqos->clk_ck_enabled = true; + } + + dev_dbg(dev, "%s: OK\n", __func__); + return 0; + +err_disable_clk_tx: + clk_disable(&eqos->clk_tx); +err_disable_clk_rx: + clk_disable(&eqos->clk_rx); +err_disable_clk_master_bus: + clk_disable(&eqos->clk_master_bus); +err: + dev_dbg(dev, "%s: FAILED: %d\n", __func__, ret); + + return ret; +} + +static int eqos_stop_clks_stm32(struct udevice *dev) +{ + struct eqos_priv __maybe_unused *eqos = dev_get_priv(dev); + + if (!CONFIG_IS_ENABLED(CLK)) + return 0; + + dev_dbg(dev, "%s:\n", __func__); + + clk_disable(&eqos->clk_tx); + clk_disable(&eqos->clk_rx); + clk_disable(&eqos->clk_master_bus); + + dev_dbg(dev, "%s: OK\n", __func__); + + return 0; +} + +static int eqos_probe_syscfg_stm32(struct udevice *dev, + phy_interface_t interface_type) +{ + /* Ethernet 50MHz RMII clock selection. */ + const bool eth_ref_clk_sel = dev_read_bool(dev, "st,eth-ref-clk-sel"); + /* SoC is STM32MP13xx with two ethernet MACs */ + const bool is_mp13 = device_is_compatible(dev, "st,stm32mp13-dwmac"); + /* Gigabit Ethernet 125MHz clock selection. */ + const bool eth_clk_sel = dev_read_bool(dev, "st,eth-clk-sel"); + /* Ethernet clock source is RCC. */ + const bool ext_phyclk = dev_read_bool(dev, "st,ext-phyclk"); + struct regmap *regmap; + u32 regmap_mask; + u32 value; + + regmap = syscon_regmap_lookup_by_phandle(dev, "st,syscon"); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + regmap_mask = dev_read_u32_index_default(dev, "st,syscon", 2, + SYSCFG_PMCSETR_ETH1_MASK); + + switch (interface_type) { + case PHY_INTERFACE_MODE_MII: + dev_dbg(dev, "PHY_INTERFACE_MODE_MII\n"); + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_GMII_MII); + /* + * STM32MP15xx supports both MII and GMII, STM32MP13xx MII only. + * SYSCFG_PMCSETR ETH_SELMII is present only on STM32MP15xx and + * acts as a selector between 0:GMII and 1:MII. As STM32MP13xx + * supports only MII, ETH_SELMII is not present. + */ + if (!is_mp13) /* Select MII mode on STM32MP15xx */ + value |= SYSCFG_PMCSETR_ETH_SELMII; + break; + case PHY_INTERFACE_MODE_GMII: /* STM32MP15xx only */ + dev_dbg(dev, "PHY_INTERFACE_MODE_GMII\n"); + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_GMII_MII); + /* + * If eth_clk_sel is set, use internal ETH_CLKx clock from RCC, + * otherwise use external clock from IO pin (requires matching + * GPIO block AF setting of that pin). + */ + if (eth_clk_sel || ext_phyclk) + value |= SYSCFG_PMCSETR_ETH_CLK_SEL; + break; + case PHY_INTERFACE_MODE_RMII: + dev_dbg(dev, "PHY_INTERFACE_MODE_RMII\n"); + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_RMII); + /* + * If eth_ref_clk_sel is set, use internal clock from RCC, + * otherwise use external clock from ETHn_RX_CLK/ETHn_REF_CLK + * IO pin (requires matching GPIO block AF setting of that + * pin). + */ + if (eth_ref_clk_sel || ext_phyclk) + value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + dev_dbg(dev, "PHY_INTERFACE_MODE_RGMII\n"); + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_RGMII); + /* + * If eth_clk_sel is set, use internal ETH_CLKx clock from RCC, + * otherwise use external clock from ETHx_CLK125 pin (requires + * matching GPIO block AF setting of that pin). + */ + if (eth_clk_sel || ext_phyclk) + value |= SYSCFG_PMCSETR_ETH_CLK_SEL; + break; + default: + dev_dbg(dev, "Do not manage %d interface\n", + interface_type); + /* Do not manage others interfaces */ + return -EINVAL; + } + + /* Shift value at correct ethernet MAC offset in SYSCFG_PMCSETR */ + value <<= ffs(regmap_mask) - ffs(SYSCFG_PMCSETR_ETH1_MASK); + + /* Update PMCCLRR (clear register) */ + regmap_write(regmap, is_mp13 ? + SYSCFG_PMCCLRR_MP13 : SYSCFG_PMCCLRR_MP15, + regmap_mask); + + return regmap_update_bits(regmap, SYSCFG_PMCSETR, regmap_mask, value); +} + +static int eqos_probe_resources_stm32(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + phy_interface_t interface; + int ret; + + dev_dbg(dev, "%s:\n", __func__); + + interface = eqos->config->interface(dev); + + if (interface == PHY_INTERFACE_MODE_NA) { + dev_err(dev, "Invalid PHY interface\n"); + return -EINVAL; + } + + ret = eqos_probe_syscfg_stm32(dev, interface); + if (ret) + return -EINVAL; + + ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); + if (ret) { + dev_err(dev, "clk_get_by_name(master_bus) failed: %d\n", ret); + goto err_probe; + } + + ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); + if (ret) { + dev_err(dev, "clk_get_by_name(rx) failed: %d\n", ret); + goto err_probe; + } + + ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); + if (ret) { + dev_err(dev, "clk_get_by_name(tx) failed: %d\n", ret); + goto err_probe; + } + + /* Get ETH_CLK clocks (optional) */ + ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); + if (ret) + dev_warn(dev, "No phy clock provided %d\n", ret); + + dev_dbg(dev, "%s: OK\n", __func__); + + return 0; + +err_probe: + + dev_dbg(dev, "%s: returns %d\n", __func__, ret); + + return ret; +} + +static int eqos_remove_resources_stm32(struct udevice *dev) +{ + dev_dbg(dev, "%s:\n", __func__); + + return 0; +} + +static struct eqos_ops eqos_stm32_ops = { + .eqos_inval_desc = eqos_inval_desc_generic, + .eqos_flush_desc = eqos_flush_desc_generic, + .eqos_inval_buffer = eqos_inval_buffer_generic, + .eqos_flush_buffer = eqos_flush_buffer_generic, + .eqos_probe_resources = eqos_probe_resources_stm32, + .eqos_remove_resources = eqos_remove_resources_stm32, + .eqos_stop_resets = eqos_null_ops, + .eqos_start_resets = eqos_null_ops, + .eqos_stop_clks = eqos_stop_clks_stm32, + .eqos_start_clks = eqos_start_clks_stm32, + .eqos_calibrate_pads = eqos_null_ops, + .eqos_disable_calibration = eqos_null_ops, + .eqos_set_tx_clk_speed = eqos_null_ops, + .eqos_get_enetaddr = eqos_null_ops, + .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 +}; + +struct eqos_config __maybe_unused eqos_stm32mp13_config = { + .reg_access_always_ok = false, + .mdio_wait = 10000, + .swr_wait = 50, + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, + .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, + .axi_bus_width = EQOS_AXI_WIDTH_32, + .interface = dev_read_phy_mode, + .ops = &eqos_stm32_ops +}; + +struct eqos_config __maybe_unused eqos_stm32mp15_config = { + .reg_access_always_ok = false, + .mdio_wait = 10000, + .swr_wait = 50, + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, + .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, + .axi_bus_width = EQOS_AXI_WIDTH_64, + .interface = dev_read_phy_mode, + .ops = &eqos_stm32_ops +};