_ Add OHCI HCD support for STM32MP15xx DHSOM
  _ Report OTP-CLOSED instead of rev.? on closed STM32MP15xx
  _ Initialize TAMP_SMCR BKP..PROT fields on STM32MP15xx
  _ Jump to ep on successful resume in PSCI suspend code
  _ Add FASTBOOT support for STM32MP13
  _ Fix/Rework key and leds management for STM32MP13/15
  _ net: dwc_eth_qos: Clean up STM32 glue code and add STM32MP13xx support
 
 MP2:
  _ Add stm32-fmc-ebi support
  _ Add: sdmmc2 support and fix AARCH64 compilation
 -----BEGIN PGP SIGNATURE-----
 
 iQJQBAABCgA6FiEEXyrViUccKBz9c35Jysd4L3sz/6YFAmYiQ/EcHHBhdHJpY2Uu
 Y2hvdGFyZEBmb3NzLnN0LmNvbQAKCRDKx3gvezP/ph+3D/4qsN+tYQYzBfCnhCjA
 eEHMHGS6wBUg4riF5bjvk68CEVDIxm7NARFJi0RodvYsOZF7kLLyELm9yyNcWb+1
 gkqLNcLLWFRhLyAIfCTnl88+luR6F48TPdVIXw17Vb3n4Fc99ICaS2PHYbHeRbR+
 d/oga0DBz2N21+scYrUjPQoeczdk/fui84AXF7u8/7zFdYY0p50wHItKQHt4KXMv
 TnM9KbeHGlxRdIiVR2Jvv5Q51mhwv8XczgOZdmGLDYBV3xKexacHsLgfVcwSM2C8
 1YHFA6VWVAOcJyQ+VFKmQw0JoTUWueJCY21T6H6fsAnpMTc9tksu3nLJO0P8CCN0
 IbI50trzLWPy/BZtqJwV67durp6ZA6hT5wQOTo7NHAFocql9hJKtDuhvTVHqmx6R
 6SWpTWD24Mkgd9FrXk/yMEUOmihOB8U6q+GkyPf/yfWyZK93mUwiRStFkBwEz8QY
 AX5gNoQ7+zJhkfZ4VdsCsFaVJV7Y9vlN3hnNhqLVEhXJ9GvFOszAZOTuuO8rLAv7
 i7HE8Hk7zv6j15qSUPKOQv8BO0eVFlLPzTXS9F/uzSlpjfpNIs7At3TyQ4pAukRo
 uHc7KjHpVAkC+7YeMuVR3VFQ/p2+5EyxMclKIvGlOxqD/+m1Keu+C4/gTkWYlIgx
 mWqsvZCAi2RmDcUWBBB2mHpswQ==
 =up9Y
 -----END PGP SIGNATURE-----

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

MP1:
 _ Add OHCI HCD support for STM32MP15xx DHSOM
 _ Report OTP-CLOSED instead of rev.? on closed STM32MP15xx
 _ Initialize TAMP_SMCR BKP..PROT fields on STM32MP15xx
 _ Jump to ep on successful resume in PSCI suspend code
 _ Add FASTBOOT support for STM32MP13
 _ Fix/Rework key and leds management for STM32MP13/15
 _ net: dwc_eth_qos: Clean up STM32 glue code and add STM32MP13xx support

MP2:
 _ Add stm32-fmc-ebi support
 _ Add: sdmmc2 support and fix AARCH64 compilation
This commit is contained in:
Tom Rini 2024-04-19 07:28:43 -06:00
commit af04f37a78
27 changed files with 1051 additions and 430 deletions

View File

@ -16,11 +16,26 @@
u-boot,mmc-env-partition = "u-boot-env";
};
gpio-keys {
button-user-1 {
label = "User-1";
linux,code = <BTN_2>;
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 = <LED_COLOR_ID_RED>;
gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
default-state = "off";
};
};
};

View File

@ -3,6 +3,7 @@
* Copyright : STMicroelectronics 2022
*/
#include <dt-bindings/input/linux-event-codes.h>
#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 = <BTN_1>;
gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
};
button-user-2 {
label = "User-2";
linux,code = <BTN_2>;
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";
};
};
};

View File

@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include <dt-bindings/input/linux-event-codes.h>
#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 = <BTN_1>;
gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
};
button-user-2 {
label = "User-2";
linux,code = <BTN_2>;
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";
};
};
};

View File

@ -3,6 +3,7 @@
* Copyright : STMicroelectronics 2022
*/
#include <dt-bindings/input/linux-event-codes.h>
#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 = <BTN_1>;
gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
};
button-user-2 {
label = "User-2";
linux,code = <BTN_2>;
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";
};
};
};

View File

@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include <dt-bindings/input/linux-event-codes.h>
#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 = <BTN_1>;
gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
};
button-user-2 {
label = "User-2";
linux,code = <BTN_2>;
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";
};
};
};

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -14,6 +14,7 @@
#include <asm/arch/sys_proto.h>
#include <dm/device.h>
#include <dm/uclass.h>
#include <linux/bitfield.h>
/* 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)

View File

@ -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)
{

View File

@ -8,6 +8,7 @@
#include <common.h>
#include <adc.h>
#include <bootm.h>
#include <button.h>
#include <clk.h>
#include <config.h>
#include <dm.h>
@ -38,6 +39,7 @@
#include <asm/gpio.h>
#include <asm/arch/stm32.h>
#include <asm/arch/sys_proto.h>
#include <dm/device-internal.h>
#include <dm/ofnode.h>
#include <jffs2/load_kernel.h>
#include <linux/bitops.h>
@ -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();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */ }
};

View File

@ -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" },
{ }
};

View File

@ -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 */ }
};

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -0,0 +1,325 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2024, Marek Vasut <marex@denx.de>
*
* This is code moved from drivers/net/dwc_eth_qos.c , which is:
* Copyright (c) 2016, NVIDIA CORPORATION.
*/
#include <asm/cache.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <clk.h>
#include <cpu_func.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <errno.h>
#include <eth_phy.h>
#include <log.h>
#include <malloc.h>
#include <memalign.h>
#include <miiphy.h>
#include <net.h>
#include <netdev.h>
#include <phy.h>
#include <regmap.h>
#include <reset.h>
#include <syscon.h>
#include <wait_bit.h>
#include <linux/bitfield.h>
#include <linux/delay.h>
#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
};