From 343742661b0500b1873a6e4fcb7bff9d16f955a4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:22 +0100 Subject: net: dwc_eth_qos: Split STM32 glue into separate file Move STM32 glue code into separate file to contain the STM32 specific code outside of the DWMAC core code. No functional change. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut Reviewed-by: Christophe ROULLIER --- drivers/net/Makefile | 1 + drivers/net/dwc_eth_qos.c | 165 --------------------------------- drivers/net/dwc_eth_qos.h | 1 + drivers/net/dwc_eth_qos_stm32.c | 196 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+), 165 deletions(-) create mode 100644 drivers/net/dwc_eth_qos_stm32.c (limited to 'drivers/net') diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6677366ebd6..dc3404519d6 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 67d80d987ff..aa4f815eb41 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) { diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h index e3222e1e17e..a6087f191ab 100644 --- a/drivers/net/dwc_eth_qos.h +++ b/drivers/net/dwc_eth_qos.h @@ -290,4 +290,5 @@ 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_stm32_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 00000000000..cfda757133e --- /dev/null +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -0,0 +1,196 @@ +// 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 "dwc_eth_qos.h" + +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_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", ret); + goto err; + } + + ret = clk_enable(&eqos->clk_rx); + if (ret < 0) { + pr_err("clk_enable(clk_rx) failed: %d", ret); + goto err_disable_clk_master_bus; + } + + ret = clk_enable(&eqos->clk_tx); + if (ret < 0) { + pr_err("clk_enable(clk_tx) failed: %d", ret); + goto err_disable_clk_rx; + } + + if (clk_valid(&eqos->clk_ck) && !eqos->clk_ck_enabled) { + ret = clk_enable(&eqos->clk_ck); + if (ret < 0) { + pr_err("clk_enable(clk_ck) failed: %d", 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_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_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", ret); + goto err_probe; + } + + ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); + if (ret) { + pr_err("clk_get_by_name(rx) failed: %d", ret); + goto err_probe; + } + + ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); + if (ret) { + pr_err("clk_get_by_name(tx) failed: %d", ret); + goto err_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 int eqos_remove_resources_stm32(struct udevice *dev) +{ + debug("%s(dev=%p):\n", __func__, dev); + + 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_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 +}; -- cgit v1.3.1 From 85d1de9a1f39a0ff393cd90aec46ce47d40be60c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:23 +0100 Subject: net: dwc_eth_qos: Rename eqos_stm32_config to eqos_stm32mp15_config The current glue code is specific to STM32MP15xx, the upcoming STM32MP13xx will introduce another entry specific to the STM32MP13xx. Rename the current entry to eqos_stm32mp15_config in preparation for STM32MP13xx addition. No functional change. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut Reviewed-by: Christophe ROULLIER --- drivers/net/dwc_eth_qos.c | 2 +- drivers/net/dwc_eth_qos.h | 2 +- drivers/net/dwc_eth_qos_stm32.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index aa4f815eb41..8d106ec0d0d 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1507,7 +1507,7 @@ static const struct udevice_id eqos_ids[] = { #if IS_ENABLED(CONFIG_DWC_ETH_QOS_STM32) { .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 a6087f191ab..bafd0d339fb 100644 --- a/drivers/net/dwc_eth_qos.h +++ b/drivers/net/dwc_eth_qos.h @@ -290,5 +290,5 @@ 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_stm32_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 index cfda757133e..fd29a604987 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -184,7 +184,7 @@ static struct eqos_ops eqos_stm32_ops = { .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 }; -struct eqos_config __maybe_unused eqos_stm32_config = { +struct eqos_config __maybe_unused eqos_stm32mp15_config = { .reg_access_always_ok = false, .mdio_wait = 10000, .swr_wait = 50, -- cgit v1.3.1 From d100c1abb778f408691f983c9bf34ed9b4869493 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:24 +0100 Subject: net: dwc_eth_qos: Fold board_interface_eth_init into STM32 glue code Move board_interface_eth_init() into eqos_probe_syscfg_stm32() in STM32 driver glue code. The eqos_probe_syscfg_stm32() parses STM32 specific DT properties of this MAC and configures SYSCFG registers accordingly, there is nothing board specific happening in this function, move it into generic driver code instead. Drop the now unused duplicates from board files. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut --- board/dhelectronics/dh_stm32mp1/board.c | 82 ------------------------------- board/st/stm32mp1/stm32mp1.c | 82 ------------------------------- drivers/net/dwc_eth_qos_stm32.c | 86 ++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 166 deletions(-) (limited to 'drivers/net') diff --git a/board/dhelectronics/dh_stm32mp1/board.c b/board/dhelectronics/dh_stm32mp1/board.c index 079dfff0389..22af423536d 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 a17c314daeb..f284b0dfd28 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -52,12 +52,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 +71,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 @@ -742,76 +730,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/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index fd29a604987..7520a136ed0 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -24,11 +24,26 @@ #include #include #include +#include #include #include #include "dwc_eth_qos.h" +/* SYSCFG registers */ +#define SYSCFG_PMCSETR 0x04 +#define SYSCFG_PMCCLRR 0x44 + +#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) + static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) { #ifdef CONFIG_CLK @@ -108,11 +123,78 @@ static int eqos_stop_clks_stm32(struct udevice *dev) return 0; } +static int eqos_probe_syscfg_stm32(struct udevice *dev, + phy_interface_t interface_type) +{ + bool eth_ref_clk_sel_reg = false; + bool eth_clk_sel_reg = false; + u8 *syscfg; + u32 value; + + /* 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; +} + static int eqos_probe_resources_stm32(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); - int ret; phy_interface_t interface; + int ret; debug("%s(dev=%p):\n", __func__, dev); @@ -123,7 +205,7 @@ static int eqos_probe_resources_stm32(struct udevice *dev) return -EINVAL; } - ret = board_interface_eth_init(dev, interface); + ret = eqos_probe_syscfg_stm32(dev, interface); if (ret) return -EINVAL; -- cgit v1.3.1 From b204c2a9ae7adc3dc65a51df2254d8abc7ae07a3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:25 +0100 Subject: net: dwc_eth_qos: Scrub ifdeffery Replace ifdef CONFIG_CLK with if (CONFIG_IS_ENABLED(CLK)) to improve code build coverage. Some of the functions printed debug("%s: OK\n", __func__); on exit with and without CLK enabled, some did not, make it consistent and print nothing if CLK is disabled. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut Reviewed-by: Christophe ROULLIER --- drivers/net/dwc_eth_qos_stm32.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 7520a136ed0..d7ec0c9be36 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -46,21 +46,22 @@ static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) { -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(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); -#else - return 0; -#endif } static int eqos_start_clks_stm32(struct udevice *dev) { -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(dev); + struct eqos_priv __maybe_unused *eqos = dev_get_priv(dev); int ret; + if (!CONFIG_IS_ENABLED(CLK)) + return 0; + debug("%s(dev=%p):\n", __func__, dev); ret = clk_enable(&eqos->clk_master_bus); @@ -89,12 +90,10 @@ static int eqos_start_clks_stm32(struct udevice *dev) } 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: @@ -104,20 +103,20 @@ err_disable_clk_master_bus: err: debug("%s: FAILED: %d\n", __func__, ret); return ret; -#endif } static int eqos_stop_clks_stm32(struct udevice *dev) { -#ifdef CONFIG_CLK - struct eqos_priv *eqos = dev_get_priv(dev); + struct eqos_priv __maybe_unused *eqos = dev_get_priv(dev); + + if (!CONFIG_IS_ENABLED(CLK)) + return 0; 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; -- cgit v1.3.1 From 416592e26506f7ff44922b0547b297f5f7e52ad3 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:26 +0100 Subject: net: dwc_eth_qos: Use FIELD_PREP for ETH_SEL bitfield Use FIELD_PREP to configure content of ETH_SEL bitfield in SYSCFG_PMCSETR register. No functional change. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut --- drivers/net/dwc_eth_qos_stm32.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index d7ec0c9be36..7545026b158 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "dwc_eth_qos.h" @@ -40,9 +41,9 @@ #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 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) { @@ -142,35 +143,33 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, switch (interface_type) { case PHY_INTERFACE_MODE_MII: - value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | - SYSCFG_PMCSETR_ETH_REF_CLK_SEL; + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_GMII_MII); + value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; log_debug("PHY_INTERFACE_MODE_MII\n"); break; case PHY_INTERFACE_MODE_GMII: + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_GMII_MII); 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; + value |= SYSCFG_PMCSETR_ETH_CLK_SEL; log_debug("PHY_INTERFACE_MODE_GMII\n"); break; case PHY_INTERFACE_MODE_RMII: + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_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; + value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; 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: + value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, + SYSCFG_PMCSETR_ETH_SEL_RGMII); if (eth_clk_sel_reg) - value = SYSCFG_PMCSETR_ETH_SEL_RGMII | - SYSCFG_PMCSETR_ETH_CLK_SEL; - else - value = SYSCFG_PMCSETR_ETH_SEL_RGMII; + value |= SYSCFG_PMCSETR_ETH_CLK_SEL; log_debug("PHY_INTERFACE_MODE_RGMII\n"); break; default: -- cgit v1.3.1 From a810aa8da792d2af56c36e70afd9d451cf21fb2d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:27 +0100 Subject: net: dwc_eth_qos: Move log_debug statements on top of case block Move the log_debug() calls on top of the bit manipulation code. No functional change. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut --- drivers/net/dwc_eth_qos_stm32.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 7545026b158..38037c47954 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -143,34 +143,34 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, switch (interface_type) { case PHY_INTERFACE_MODE_MII: + log_debug("PHY_INTERFACE_MODE_MII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - log_debug("PHY_INTERFACE_MODE_MII\n"); break; case PHY_INTERFACE_MODE_GMII: + log_debug("PHY_INTERFACE_MODE_GMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); if (eth_clk_sel_reg) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; - log_debug("PHY_INTERFACE_MODE_GMII\n"); break; case PHY_INTERFACE_MODE_RMII: + log_debug("PHY_INTERFACE_MODE_RMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_RMII); if (eth_ref_clk_sel_reg) value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; - 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: + log_debug("PHY_INTERFACE_MODE_RGMII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_RGMII); if (eth_clk_sel_reg) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; - log_debug("PHY_INTERFACE_MODE_RGMII\n"); break; default: log_debug("Do not manage %d interface\n", -- cgit v1.3.1 From 2e8f75be62bafb7113a4135c278a681c066d8e5a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:28 +0100 Subject: net: dwc_eth_qos: Use consistent logging prints Use dev_*() only to print all the logs from this glue code, instead of mixing dev_*(), log_*(), pr_*() all in one code. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut --- drivers/net/dwc_eth_qos_stm32.c | 52 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 38037c47954..72f65f80540 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -63,36 +63,36 @@ static int eqos_start_clks_stm32(struct udevice *dev) if (!CONFIG_IS_ENABLED(CLK)) return 0; - debug("%s(dev=%p):\n", __func__, dev); + dev_dbg(dev, "%s:\n", __func__); ret = clk_enable(&eqos->clk_master_bus); if (ret < 0) { - pr_err("clk_enable(clk_master_bus) failed: %d", ret); + dev_err(dev, "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", ret); + 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) { - pr_err("clk_enable(clk_tx) failed: %d", ret); + 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) { - pr_err("clk_enable(clk_ck) failed: %d", ret); + dev_err(dev, "clk_enable(clk_ck) failed: %d\n", ret); goto err_disable_clk_tx; } eqos->clk_ck_enabled = true; } - debug("%s: OK\n", __func__); + dev_dbg(dev, "%s: OK\n", __func__); return 0; err_disable_clk_tx: @@ -102,7 +102,8 @@ err_disable_clk_rx: err_disable_clk_master_bus: clk_disable(&eqos->clk_master_bus); err: - debug("%s: FAILED: %d\n", __func__, ret); + dev_dbg(dev, "%s: FAILED: %d\n", __func__, ret); + return ret; } @@ -113,13 +114,14 @@ static int eqos_stop_clks_stm32(struct udevice *dev) if (!CONFIG_IS_ENABLED(CLK)) return 0; - debug("%s(dev=%p):\n", __func__, dev); + dev_dbg(dev, "%s:\n", __func__); clk_disable(&eqos->clk_tx); clk_disable(&eqos->clk_rx); clk_disable(&eqos->clk_master_bus); - debug("%s: OK\n", __func__); + dev_dbg(dev, "%s: OK\n", __func__); + return 0; } @@ -143,20 +145,20 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, switch (interface_type) { case PHY_INTERFACE_MODE_MII: - log_debug("PHY_INTERFACE_MODE_MII\n"); + dev_dbg(dev, "PHY_INTERFACE_MODE_MII\n"); value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK, SYSCFG_PMCSETR_ETH_SEL_GMII_MII); value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; break; case PHY_INTERFACE_MODE_GMII: - log_debug("PHY_INTERFACE_MODE_GMII\n"); + 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_reg) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; break; case PHY_INTERFACE_MODE_RMII: - log_debug("PHY_INTERFACE_MODE_RMII\n"); + 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_reg) @@ -166,15 +168,15 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: - log_debug("PHY_INTERFACE_MODE_RGMII\n"); + 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_reg) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; break; default: - log_debug("Do not manage %d interface\n", - interface_type); + dev_dbg(dev, "Do not manage %d interface\n", + interface_type); /* Do not manage others interfaces */ return -EINVAL; } @@ -194,12 +196,12 @@ static int eqos_probe_resources_stm32(struct udevice *dev) phy_interface_t interface; int ret; - debug("%s(dev=%p):\n", __func__, dev); + dev_dbg(dev, "%s:\n", __func__); interface = eqos->config->interface(dev); if (interface == PHY_INTERFACE_MODE_NA) { - pr_err("Invalid PHY interface\n"); + dev_err(dev, "Invalid PHY interface\n"); return -EINVAL; } @@ -209,39 +211,41 @@ static int eqos_probe_resources_stm32(struct udevice *dev) ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); if (ret) { - pr_err("clk_get_by_name(master_bus) failed: %d", 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) { - pr_err("clk_get_by_name(rx) failed: %d", 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) { - pr_err("clk_get_by_name(tx) failed: %d", 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) - pr_warn("No phy clock provided %d", ret); + dev_warn(dev, "No phy clock provided %d\n", ret); + + dev_dbg(dev, "%s: OK\n", __func__); - debug("%s: OK\n", __func__); return 0; err_probe: - debug("%s: returns %d\n", __func__, ret); + dev_dbg(dev, "%s: returns %d\n", __func__, ret); + return ret; } static int eqos_remove_resources_stm32(struct udevice *dev) { - debug("%s(dev=%p):\n", __func__, dev); + dev_dbg(dev, "%s:\n", __func__); return 0; } -- cgit v1.3.1 From 22265e236538f29e38df2411a12103aeefb3138b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:29 +0100 Subject: net: dwc_eth_qos: Constify st, eth-* values parsed out of DT Use const bool for the values parsed out of DT. Drop the duplicate assignment of false into those bool variables, assign them directly with the content parsed out of DT. Abbreviate the variable name too. Reviewed-by: Patrice Chotard Signed-off-by: Marek Vasut --- drivers/net/dwc_eth_qos_stm32.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 72f65f80540..0b13d01346b 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -128,17 +128,13 @@ static int eqos_stop_clks_stm32(struct udevice *dev) static int eqos_probe_syscfg_stm32(struct udevice *dev, phy_interface_t interface_type) { - bool eth_ref_clk_sel_reg = false; - bool eth_clk_sel_reg = false; + /* Ethernet 50MHz RMII clock selection. */ + const bool eth_ref_clk_sel = dev_read_bool(dev, "st,eth-ref-clk-sel"); + /* Gigabit Ethernet 125MHz clock selection. */ + const bool eth_clk_sel = dev_read_bool(dev, "st,eth-clk-sel"); u8 *syscfg; u32 value; - /* 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; @@ -154,14 +150,14 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, 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_reg) + if (eth_clk_sel) 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_reg) + if (eth_ref_clk_sel) value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; break; case PHY_INTERFACE_MODE_RGMII: @@ -171,7 +167,7 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, 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_reg) + if (eth_clk_sel) value |= SYSCFG_PMCSETR_ETH_CLK_SEL; break; default: -- cgit v1.3.1 From a440d19c6c91938190b329be65e0986e01007304 Mon Sep 17 00:00:00 2001 From: Christophe Roullier Date: Tue, 26 Mar 2024 13:07:30 +0100 Subject: net: dwc_eth_qos: Add DT parsing for STM32MP13xx platform Manage 2 ethernet instances, select which instance to configure with mask If mask is not present in DT, it is stm32mp15 platform. Signed-off-by: Christophe Roullier Signed-off-by: Marek Vasut # Rework the code Reviewed-by: Christophe ROULLIER --- drivers/net/dwc_eth_qos_stm32.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 0b13d01346b..5a20fe5bea2 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -33,11 +34,16 @@ /* SYSCFG registers */ #define SYSCFG_PMCSETR 0x04 -#define SYSCFG_PMCCLRR 0x44 +#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) @@ -130,23 +136,30 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, { /* 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"); - u8 *syscfg; + struct regmap *regmap; + u32 regmap_mask; u32 value; - syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); - if (!syscfg) - return -ENODEV; + 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); - value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL; + if (!is_mp13) /* Select MII mode on STM32MP15xx */ + value |= SYSCFG_PMCSETR_ETH_SELMII; break; - case PHY_INTERFACE_MODE_GMII: + 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); @@ -177,13 +190,15 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, 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); + /* Shift value at correct ethernet MAC offset in SYSCFG_PMCSETR */ + value <<= ffs(regmap_mask) - ffs(SYSCFG_PMCSETR_ETH1_MASK); - return 0; + /* 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) -- cgit v1.3.1 From 882b2287a654cb1c86bde24175385220ffeb0cc8 Mon Sep 17 00:00:00 2001 From: Christophe Roullier Date: Tue, 26 Mar 2024 13:07:31 +0100 Subject: net: dwc_eth_qos: Add support of STM32MP13xx platform Add compatible "st,stm32mp13-dwmac" to manage STM32MP13 boards. Reviewed-by: Patrice Chotard Signed-off-by: Christophe Roullier Signed-off-by: Marek Vasut # Rebase, reshuffle, squash code Reviewed-by: Christophe ROULLIER --- drivers/net/dwc_eth_qos.c | 4 ++++ drivers/net/dwc_eth_qos.h | 1 + drivers/net/dwc_eth_qos_stm32.c | 11 +++++++++++ 3 files changed, 16 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 8d106ec0d0d..32a5d52165a 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1505,6 +1505,10 @@ 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_stm32mp15_config diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h index bafd0d339fb..8b3d0d464d3 100644 --- a/drivers/net/dwc_eth_qos.h +++ b/drivers/net/dwc_eth_qos.h @@ -290,5 +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 index 5a20fe5bea2..435473f99a6 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -279,6 +279,17 @@ static struct eqos_ops eqos_stm32_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, -- cgit v1.3.1 From 1ef28c58d2dbd8c7d65e28ef500bfd359c66c07f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 26 Mar 2024 13:07:32 +0100 Subject: net: dwc_eth_qos: Add support for st, ext-phyclk property The "st,ext-phyclk" property is a unification of "st,eth-clk-sel" and "st,eth-ref-clk-sel" properties. All three properties define ETH CK clock direction, however: - "st,eth-clk-sel" selects clock direction for GMII/RGMII mode - "st,eth-ref-clk-sel" selects clock direction for RMII mode - "st,ext-phyclk" selects clock direction for all RMII/GMII/RGMII modes The "st,ext-phyclk" is the preferrable property to use. Signed-off-by: Marek Vasut Reviewed-by: Christophe ROULLIER --- drivers/net/dwc_eth_qos_stm32.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dwc_eth_qos_stm32.c b/drivers/net/dwc_eth_qos_stm32.c index 435473f99a6..9ee82b54c62 100644 --- a/drivers/net/dwc_eth_qos_stm32.c +++ b/drivers/net/dwc_eth_qos_stm32.c @@ -140,6 +140,8 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, 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; @@ -156,6 +158,12 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, 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; @@ -163,14 +171,25 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, 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) + /* + * 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) + /* + * 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: @@ -180,7 +199,12 @@ static int eqos_probe_syscfg_stm32(struct udevice *dev, 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) + /* + * 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: -- cgit v1.3.1