[U-Boot] [PATCH 0/5] - Add Ethernet support for stm32mpu

Support all PHY config: PHY_MODE (MII,GMII, RMII, RGMII) Phy wo crystal (25Mhz and 50 Mhz), No 125Mhz from PHY config
Christophe Roullier (5): board: stm32mp1: Add board_interface_eth_init net: dwc_eth_qos: add Ethernet stm32mp1 support ARM: dts: stm32: Add Ethernet support on stm32mp1 stm32mp1: Add Ethernet support for stm32mp1 board configs: stm32mp15: Enable Ethernet feature
arch/arm/dts/stm32mp157-pinctrl.dtsi | 31 ++ arch/arm/dts/stm32mp157c-ev1.dts | 21 ++ arch/arm/dts/stm32mp157c.dtsi | 35 +++ board/st/stm32mp1/stm32mp1.c | 77 +++++ configs/stm32mp15_basic_defconfig | 2 + drivers/net/dwc_eth_qos.c | 435 +++++++++++++++++++++++---- include/configs/stm32mp1.h | 11 +- 7 files changed, 559 insertions(+), 53 deletions(-)

Called to configure Ethernet PHY interface selection and configure clock selection in RCC Ethernet clock tree.
Signed-off-by: Christophe Roullier christophe.roullier@st.com ---
board/st/stm32mp1/stm32mp1.c | 77 ++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+)
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 54feca0ecff..7c37018d871 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -10,12 +10,27 @@ #include <generic-phy.h> #include <phy.h> #include <reset.h> +#include <syscon.h> #include <usb.h> #include <asm/arch/stm32.h> #include <asm/io.h> #include <power/regulator.h> #include <usb/dwc2_udc.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) + /* * Get a global data pointer */ @@ -196,3 +211,65 @@ int board_init(void)
return 0; } + +/* board interface eth init */ +/* this is a weak define that we are overriding */ +int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg, + bool eth_ref_clk_sel_reg) +{ + u8 *syscfg; + u32 value; + + syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); + + if (!syscfg) + return -ENODEV; + + switch (interface_type) { + case PHY_INTERFACE_MODE_MII: + value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | + SYSCFG_PMCSETR_ETH_REF_CLK_SEL; + debug("%s: PHY_INTERFACE_MODE_MII\n", __func__); + break; + case PHY_INTERFACE_MODE_GMII: + if (eth_clk_sel_reg) + value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | + SYSCFG_PMCSETR_ETH_CLK_SEL; + else + value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII; + debug("%s: PHY_INTERFACE_MODE_GMII\n", __func__); + break; + case PHY_INTERFACE_MODE_RMII: + if (eth_ref_clk_sel_reg) + value = SYSCFG_PMCSETR_ETH_SEL_RMII | + SYSCFG_PMCSETR_ETH_REF_CLK_SEL; + else + value = SYSCFG_PMCSETR_ETH_SEL_RMII; + debug("%s: PHY_INTERFACE_MODE_RMII\n", __func__); + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + if (eth_clk_sel_reg) + value = SYSCFG_PMCSETR_ETH_SEL_RGMII | + SYSCFG_PMCSETR_ETH_CLK_SEL; + else + value = SYSCFG_PMCSETR_ETH_SEL_RGMII; + debug("%s: PHY_INTERFACE_MODE_RGMII\n", __func__); + break; + default: + debug("%s: Do not manage %d interface\n", + __func__, interface_type); + /* Do not manage others interfaces */ + return -EINVAL; + } + + /* clear and set ETH configuration bits */ + writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII | + SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL, + syscfg + SYSCFG_PMCCLRR); + writel(value, syscfg + SYSCFG_PMCSETR); + + return 0; +}

Synopsys GMAC 4.20 is used. And Phy mode for eval and disco is RMII with PHY Realtek RTL8211 (RGMII) We also support some other PHY config on stm32mp157c PHY_MODE (MII,GMII, RMII, RGMII) and in normal, PHY wo crystal (25Mhz and 50Mhz), No 125Mhz from PHY config
Signed-off-by: Christophe Roullier christophe.roullier@st.com ---
drivers/net/dwc_eth_qos.c | 435 +++++++++++++++++++++++++++++++++----- 1 file changed, 383 insertions(+), 52 deletions(-)
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 9f1c5af46e9..a6546d5e5ce 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -26,7 +26,6 @@ * supports a single RGMII PHY. This configuration also has SW control over * all clock and reset signals to the HW block. */ - #include <common.h> #include <clk.h> #include <dm.h> @@ -95,6 +94,7 @@ struct eqos_mac_regs { #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK 3 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED 0 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB 2 +#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV 1
#define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0 #define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK 0xff @@ -108,6 +108,7 @@ struct eqos_mac_regs { #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT 16 #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT 8 #define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2 +#define EQOS_MAC_MDIO_ADDRESS_CR_250_300 5 #define EQOS_MAC_MDIO_ADDRESS_SKAP BIT(4) #define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT 2 #define EQOS_MAC_MDIO_ADDRESS_GOC_READ 3 @@ -260,6 +261,29 @@ struct eqos_desc {
struct eqos_config { bool reg_access_always_ok; + int mdio_wait; + int swr_wait; + int config_mac; + int config_mac_mdio; + int (*interface)(struct udevice *dev); + struct eqos_ops *ops; +}; + +struct eqos_ops { + void (*eqos_inval_desc)(void *desc); + void (*eqos_flush_desc)(void *desc); + void (*eqos_inval_buffer)(void *buf, size_t size); + void (*eqos_flush_buffer)(void *buf, size_t size); + int (*eqos_probe_resources)(struct udevice *dev); + int (*eqos_remove_resources)(struct udevice *dev); + int (*eqos_stop_resets)(struct udevice *dev); + int (*eqos_start_resets)(struct udevice *dev); + void (*eqos_stop_clks)(struct udevice *dev); + int (*eqos_start_clks)(struct udevice *dev); + int (*eqos_calibrate_pads)(struct udevice *dev); + int (*eqos_disable_calibration)(struct udevice *dev); + int (*eqos_set_tx_clk_speed)(struct udevice *dev); + ulong (*eqos_get_tick_clk_rate)(struct udevice *dev); };
struct eqos_priv { @@ -276,6 +300,7 @@ struct eqos_priv { struct clk clk_rx; struct clk clk_ptp_ref; struct clk clk_tx; + struct clk clk_ck; struct clk clk_slave_bus; struct mii_dev *mii; struct phy_device *phy; @@ -327,7 +352,7 @@ static void eqos_free_descs(void *descs) #endif }
-static void eqos_inval_desc(void *desc) +static void eqos_inval_desc_tegra186(void *desc) { #ifndef CONFIG_SYS_NONCACHED_MEMORY unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); @@ -338,14 +363,36 @@ static void eqos_inval_desc(void *desc) #endif }
-static void eqos_flush_desc(void *desc) +static void eqos_inval_desc_stm32(void *desc) +{ +#ifndef CONFIG_SYS_NONCACHED_MEMORY + unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); + unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, + ARCH_DMA_MINALIGN); + + invalidate_dcache_range(start, end); +#endif +} + +static void eqos_flush_desc_tegra186(void *desc) { #ifndef CONFIG_SYS_NONCACHED_MEMORY flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE); #endif }
-static void eqos_inval_buffer(void *buf, size_t size) +static void eqos_flush_desc_stm32(void *desc) +{ +#ifndef CONFIG_SYS_NONCACHED_MEMORY + unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); + unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE, + ARCH_DMA_MINALIGN); + + flush_dcache_range(start, end); +#endif +} + +static void eqos_inval_buffer_tegra186(void *buf, size_t size) { unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1); unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN); @@ -353,11 +400,29 @@ static void eqos_inval_buffer(void *buf, size_t size) invalidate_dcache_range(start, end); }
-static void eqos_flush_buffer(void *buf, size_t size) +static void eqos_inval_buffer_stm32(void *buf, size_t size) +{ + unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); + unsigned long end = roundup((unsigned long)buf + size, + ARCH_DMA_MINALIGN); + + invalidate_dcache_range(start, end); +} + +static void eqos_flush_buffer_tegra186(void *buf, size_t size) { flush_cache((unsigned long)buf, size); }
+static void eqos_flush_buffer_stm32(void *buf, size_t size) +{ + unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); + unsigned long end = roundup((unsigned long)buf + size, + ARCH_DMA_MINALIGN); + + flush_dcache_range(start, end); +} + static int eqos_mdio_wait_idle(struct eqos_priv *eqos) { return wait_for_bit_le32(&eqos->mac_regs->mdio_address, @@ -386,14 +451,14 @@ static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad, EQOS_MAC_MDIO_ADDRESS_C45E; val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) | - (EQOS_MAC_MDIO_ADDRESS_CR_20_35 << + (eqos->config->config_mac_mdio << EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | (EQOS_MAC_MDIO_ADDRESS_GOC_READ << EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | EQOS_MAC_MDIO_ADDRESS_GB; writel(val, &eqos->mac_regs->mdio_address);
- udelay(10); + udelay(eqos->config->mdio_wait);
ret = eqos_mdio_wait_idle(eqos); if (ret) { @@ -432,14 +497,14 @@ static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad, EQOS_MAC_MDIO_ADDRESS_C45E; val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) | - (EQOS_MAC_MDIO_ADDRESS_CR_20_35 << + (eqos->config->config_mac_mdio << EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | (EQOS_MAC_MDIO_ADDRESS_GOC_WRITE << EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | EQOS_MAC_MDIO_ADDRESS_GB; writel(val, &eqos->mac_regs->mdio_address);
- udelay(10); + udelay(eqos->config->mdio_wait);
ret = eqos_mdio_wait_idle(eqos); if (ret) { @@ -509,6 +574,53 @@ err: return ret; }
+static int eqos_start_clks_stm32(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + int ret; + + debug("%s(dev=%p):\n", __func__, dev); + + ret = clk_enable(&eqos->clk_master_bus); + if (ret < 0) { + pr_err("clk_enable(clk_master_bus) failed: %d", ret); + goto err; + } + + ret = clk_enable(&eqos->clk_rx); + if (ret < 0) { + pr_err("clk_enable(clk_rx) failed: %d", ret); + goto err_disable_clk_master_bus; + } + + ret = clk_enable(&eqos->clk_tx); + if (ret < 0) { + pr_err("clk_enable(clk_tx) failed: %d", ret); + goto err_disable_clk_rx; + } + + if (clk_valid(&eqos->clk_ck)) { + ret = clk_enable(&eqos->clk_ck); + if (ret < 0) { + pr_err("clk_enable(clk_ck) failed: %d", ret); + goto err_disable_clk_tx; + } + } + + debug("%s: OK\n", __func__); + return 0; + +err_disable_clk_tx: + clk_disable(&eqos->clk_tx); +err_disable_clk_rx: + clk_disable(&eqos->clk_rx); +err_disable_clk_master_bus: + clk_disable(&eqos->clk_master_bus); +err: + debug("%s: FAILED: %d\n", __func__, ret); + return ret; +} + void eqos_stop_clks_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -524,6 +636,21 @@ void eqos_stop_clks_tegra186(struct udevice *dev) debug("%s: OK\n", __func__); }
+void eqos_stop_clks_stm32(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + + debug("%s(dev=%p):\n", __func__, dev); + + clk_disable(&eqos->clk_tx); + clk_disable(&eqos->clk_rx); + clk_disable(&eqos->clk_master_bus); + if (clk_valid(&eqos->clk_ck)) + clk_disable(&eqos->clk_ck); + + debug("%s: OK\n", __func__); +} + static int eqos_start_resets_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -563,6 +690,11 @@ static int eqos_start_resets_tegra186(struct udevice *dev) return 0; }
+static int eqos_start_resets_stm32(struct udevice *dev) +{ + return 0; +} + static int eqos_stop_resets_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -573,6 +705,11 @@ static int eqos_stop_resets_tegra186(struct udevice *dev) return 0; }
+static int eqos_stop_resets_stm32(struct udevice *dev) +{ + return 0; +} + static int eqos_calibrate_pads_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -632,6 +769,23 @@ static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev) return clk_get_rate(&eqos->clk_slave_bus); }
+static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + + return clk_get_rate(&eqos->clk_master_bus); +} + +static int eqos_calibrate_pads_stm32(struct udevice *dev) +{ + return 0; +} + +static int eqos_disable_calibration_stm32(struct udevice *dev) +{ + return 0; +} + static int eqos_set_full_duplex(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -726,6 +880,11 @@ static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev) return 0; }
+static int eqos_set_tx_clk_speed_stm32(struct udevice *dev) +{ + return 0; +} + static int eqos_adjust_link(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -766,23 +925,23 @@ static int eqos_adjust_link(struct udevice *dev) }
if (en_calibration) { - ret = eqos_calibrate_pads_tegra186(dev); + ret = eqos->config->ops->eqos_calibrate_pads(dev); if (ret < 0) { - pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret); + pr_err("eqos_calibrate_pads() failed: %d", + ret); return ret; } } else { - ret = eqos_disable_calibration_tegra186(dev); + ret = eqos->config->ops->eqos_disable_calibration(dev); if (ret < 0) { - pr_err("eqos_disable_calibration_tegra186() failed: %d", - ret); + pr_err("eqos_disable_calibration() failed: %d", + ret); return ret; } } - - ret = eqos_set_tx_clk_speed_tegra186(dev); + ret = eqos->config->ops->eqos_set_tx_clk_speed(dev); if (ret < 0) { - pr_err("eqos_set_tx_clk_speed_tegra186() failed: %d", ret); + pr_err("eqos_set_tx_clk_speed() failed: %d", ret); return ret; }
@@ -846,15 +1005,15 @@ static int eqos_start(struct udevice *dev) eqos->tx_desc_idx = 0; eqos->rx_desc_idx = 0;
- ret = eqos_start_clks_tegra186(dev); + ret = eqos->config->ops->eqos_start_clks(dev); if (ret < 0) { - pr_err("eqos_start_clks_tegra186() failed: %d", ret); + pr_err("eqos_start_clks() failed: %d", ret); goto err; }
- ret = eqos_start_resets_tegra186(dev); + ret = eqos->config->ops->eqos_start_resets(dev); if (ret < 0) { - pr_err("eqos_start_resets_tegra186() failed: %d", ret); + pr_err("eqos_start_resets() failed: %d", ret); goto err_stop_clks; }
@@ -863,32 +1022,41 @@ static int eqos_start(struct udevice *dev) eqos->reg_access_ok = true;
ret = wait_for_bit_le32(&eqos->dma_regs->mode, - EQOS_DMA_MODE_SWR, false, 10, false); + EQOS_DMA_MODE_SWR, false, + eqos->config->swr_wait, false); if (ret) { pr_err("EQOS_DMA_MODE_SWR stuck"); goto err_stop_resets; }
- ret = eqos_calibrate_pads_tegra186(dev); + ret = eqos->config->ops->eqos_calibrate_pads(dev); if (ret < 0) { - pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret); + pr_err("eqos_calibrate_pads() failed: %d", ret); goto err_stop_resets; } + rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
- rate = eqos_get_tick_clk_rate_tegra186(dev); val = (rate / 1000000) - 1; writel(val, &eqos->mac_regs->us_tic_counter);
- eqos->phy = phy_connect(eqos->mii, 0, dev, 0); + /* + * if PHY was already connected and configured, + * don't need to reconnect/reconfigure again + */ if (!eqos->phy) { - pr_err("phy_connect() failed"); - goto err_stop_resets; - } - ret = phy_config(eqos->phy); - if (ret < 0) { - pr_err("phy_config() failed: %d", ret); - goto err_shutdown_phy; + eqos->phy = phy_connect(eqos->mii, 0, dev, + eqos->config->interface(dev)); + if (!eqos->phy) { + pr_err("phy_connect() failed"); + goto err_stop_resets; + } + ret = phy_config(eqos->phy); + if (ret < 0) { + pr_err("phy_config() failed: %d", ret); + goto err_shutdown_phy; + } } + ret = phy_startup(eqos->phy); if (ret < 0) { pr_err("phy_startup() failed: %d", ret); @@ -993,7 +1161,7 @@ static int eqos_start(struct udevice *dev) clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT, - EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB << + eqos->config->config_mac << EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT);
/* Set TX flow control parameters */ @@ -1074,7 +1242,7 @@ static int eqos_start(struct udevice *dev) (i * EQOS_MAX_PACKET_SIZE)); rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; } - flush_cache((unsigned long)eqos->descs, EQOS_DESCRIPTORS_SIZE); + eqos->config->ops->eqos_flush_desc(eqos->descs);
writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address); @@ -1113,11 +1281,10 @@ static int eqos_start(struct udevice *dev)
err_shutdown_phy: phy_shutdown(eqos->phy); - eqos->phy = NULL; err_stop_resets: - eqos_stop_resets_tegra186(dev); + eqos->config->ops->eqos_stop_resets(dev); err_stop_clks: - eqos_stop_clks_tegra186(dev); + eqos->config->ops->eqos_stop_clks(dev); err: pr_err("FAILED: %d", ret); return ret; @@ -1170,10 +1337,9 @@ void eqos_stop(struct udevice *dev)
if (eqos->phy) { phy_shutdown(eqos->phy); - eqos->phy = NULL; } - eqos_stop_resets_tegra186(dev); - eqos_stop_clks_tegra186(dev); + eqos->config->ops->eqos_stop_resets(dev); + eqos->config->ops->eqos_stop_clks(dev);
debug("%s: OK\n", __func__); } @@ -1188,7 +1354,7 @@ int eqos_send(struct udevice *dev, void *packet, int length) length);
memcpy(eqos->tx_dma_buf, packet, length); - eqos_flush_buffer(eqos->tx_dma_buf, length); + eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length);
tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]); eqos->tx_desc_idx++; @@ -1203,12 +1369,12 @@ int eqos_send(struct udevice *dev, void *packet, int length) */ mb(); tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length; - eqos_flush_desc(tx_desc); + eqos->config->ops->eqos_flush_desc(tx_desc);
writel((ulong)(tx_desc + 1), &eqos->dma_regs->ch0_txdesc_tail_pointer);
for (i = 0; i < 1000000; i++) { - eqos_inval_desc(tx_desc); + eqos->config->ops->eqos_inval_desc(tx_desc); if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN)) return 0; udelay(1); @@ -1238,7 +1404,7 @@ int eqos_recv(struct udevice *dev, int flags, uchar **packetp) length = rx_desc->des3 & 0x7fff; debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length);
- eqos_inval_buffer(*packetp, length); + eqos->config->ops->eqos_inval_buffer(*packetp, length);
return length; } @@ -1269,7 +1435,7 @@ int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) */ mb(); rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; - eqos_flush_desc(rx_desc); + eqos->config->ops->eqos_flush_desc(rx_desc);
writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
@@ -1304,7 +1470,7 @@ static int eqos_probe_resources_core(struct udevice *dev) ret = -ENOMEM; goto err_free_descs; } - debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf); + debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE); if (!eqos->rx_dma_buf) { @@ -1312,7 +1478,7 @@ static int eqos_probe_resources_core(struct udevice *dev) ret = -ENOMEM; goto err_free_tx_dma_buf; } - debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf); + debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE); if (!eqos->rx_pkt) { @@ -1424,6 +1590,98 @@ err_free_reset_eqos: return ret; }
+/* board-specific Ethernet Interface initializations. */ +__weak int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg, + bool eth_ref_clk_sel_reg) +{ + return 0; +} + +static int eqos_probe_resources_stm32(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + int ret; + int interface; + bool eth_clk_sel_reg = false; + bool eth_ref_clk_sel_reg = false; + + debug("%s(dev=%p):\n", __func__, dev); + + interface = eqos->config->interface(dev); + + if (interface == -1) { + pr_err("Invalid PHY interface\n"); + return -EINVAL; + } + + /* Gigabit Ethernet 125MHz clock selection. */ + eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel"); + + /* Ethernet 50Mhz RMII clock selection */ + eth_ref_clk_sel_reg = + dev_read_bool(dev, "st,eth_ref_clk_sel"); + + ret = board_interface_eth_init(interface, eth_clk_sel_reg, + eth_ref_clk_sel_reg); + if (ret) + return -EINVAL; + + ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); + if (ret) { + pr_err("clk_get_by_name(master_bus) failed: %d", ret); + goto err_probe; + } + + ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); + if (ret) { + pr_err("clk_get_by_name(rx) failed: %d", ret); + goto err_free_clk_master_bus; + } + + ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); + if (ret) { + pr_err("clk_get_by_name(tx) failed: %d", ret); + goto err_free_clk_rx; + } + + /* Get ETH_CLK clocks (optional) */ + ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck); + if (ret) + pr_warn("No phy clock provided %d", ret); + + debug("%s: OK\n", __func__); + return 0; + +err_free_clk_rx: + clk_free(&eqos->clk_rx); +err_free_clk_master_bus: + clk_free(&eqos->clk_master_bus); +err_probe: + + debug("%s: returns %d\n", __func__, ret); + return ret; +} + +static int eqos_get_interface_stm32(struct udevice *dev) +{ + const char *phy_mode; + int interface = -1; + + debug("%s(dev=%p):\n", __func__, dev); + + phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", + NULL); + if (phy_mode) + interface = phy_get_interface_by_name(phy_mode); + + return interface; +} + +static int eqos_get_interface_tegra186(struct udevice *dev) +{ + return 0; +} + static int eqos_remove_resources_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -1442,6 +1700,22 @@ static int eqos_remove_resources_tegra186(struct udevice *dev) return 0; }
+static int eqos_remove_resources_stm32(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + + debug("%s(dev=%p):\n", __func__, dev); + + clk_free(&eqos->clk_tx); + clk_free(&eqos->clk_rx); + clk_free(&eqos->clk_master_bus); + if (clk_valid(&eqos->clk_ck)) + clk_free(&eqos->clk_ck); + + debug("%s: OK\n", __func__); + return 0; +} + static int eqos_probe(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -1468,15 +1742,16 @@ static int eqos_probe(struct udevice *dev) return ret; }
- ret = eqos_probe_resources_tegra186(dev); + ret = eqos->config->ops->eqos_probe_resources(dev); if (ret < 0) { - pr_err("eqos_probe_resources_tegra186() failed: %d", ret); + pr_err("eqos_probe_resources() failed: %d", ret); goto err_remove_resources_core; }
eqos->mii = mdio_alloc(); if (!eqos->mii) { pr_err("mdio_alloc() failed"); + ret = -ENOMEM; goto err_remove_resources_tegra; } eqos->mii->read = eqos_mdio_read; @@ -1496,7 +1771,7 @@ static int eqos_probe(struct udevice *dev) err_free_mdio: mdio_free(eqos->mii); err_remove_resources_tegra: - eqos_remove_resources_tegra186(dev); + eqos->config->ops->eqos_remove_resources(dev); err_remove_resources_core: eqos_remove_resources_core(dev);
@@ -1512,7 +1787,8 @@ static int eqos_remove(struct udevice *dev)
mdio_unregister(eqos->mii); mdio_free(eqos->mii); - eqos_remove_resources_tegra186(dev); + eqos->config->ops->eqos_remove_resources(dev); + eqos_probe_resources_core(dev);
debug("%s: OK\n", __func__); @@ -1528,8 +1804,58 @@ static const struct eth_ops eqos_ops = { .write_hwaddr = eqos_write_hwaddr, };
+static struct eqos_ops eqos_tegra186_ops = { + .eqos_inval_desc = eqos_inval_desc_tegra186, + .eqos_flush_desc = eqos_flush_desc_tegra186, + .eqos_inval_buffer = eqos_inval_buffer_tegra186, + .eqos_flush_buffer = eqos_flush_buffer_tegra186, + .eqos_probe_resources = eqos_probe_resources_tegra186, + .eqos_remove_resources = eqos_remove_resources_tegra186, + .eqos_stop_resets = eqos_stop_resets_tegra186, + .eqos_start_resets = eqos_start_resets_tegra186, + .eqos_stop_clks = eqos_stop_clks_tegra186, + .eqos_start_clks = eqos_start_clks_tegra186, + .eqos_calibrate_pads = eqos_calibrate_pads_tegra186, + .eqos_disable_calibration = eqos_disable_calibration_tegra186, + .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186, + .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186 +}; + static const struct eqos_config eqos_tegra186_config = { .reg_access_always_ok = false, + .mdio_wait = 10, + .swr_wait = 10, + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, + .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35, + .interface = eqos_get_interface_tegra186, + .ops = &eqos_tegra186_ops +}; + +static struct eqos_ops eqos_stm32_ops = { + .eqos_inval_desc = eqos_inval_desc_stm32, + .eqos_flush_desc = eqos_flush_desc_stm32, + .eqos_inval_buffer = eqos_inval_buffer_stm32, + .eqos_flush_buffer = eqos_flush_buffer_stm32, + .eqos_probe_resources = eqos_probe_resources_stm32, + .eqos_remove_resources = eqos_remove_resources_stm32, + .eqos_stop_resets = eqos_stop_resets_stm32, + .eqos_start_resets = eqos_start_resets_stm32, + .eqos_stop_clks = eqos_stop_clks_stm32, + .eqos_start_clks = eqos_start_clks_stm32, + .eqos_calibrate_pads = eqos_calibrate_pads_stm32, + .eqos_disable_calibration = eqos_disable_calibration_stm32, + .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32, + .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 +}; + +static const struct eqos_config eqos_stm32_config = { + .reg_access_always_ok = false, + .mdio_wait = 10000, + .swr_wait = 50, + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV, + .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, + .interface = eqos_get_interface_stm32, + .ops = &eqos_stm32_ops };
static const struct udevice_id eqos_ids[] = { @@ -1537,6 +1863,11 @@ static const struct udevice_id eqos_ids[] = { .compatible = "nvidia,tegra186-eqos", .data = (ulong)&eqos_tegra186_config }, + { + .compatible = "snps,dwmac-4.20a", + .data = (ulong)&eqos_stm32_config + }, + { } };

On Fri, Apr 26, 2019 at 6:16 AM Christophe Roullier christophe.roullier@st.com wrote:
Synopsys GMAC 4.20 is used. And Phy mode for eval and disco is RMII with PHY Realtek RTL8211 (RGMII) We also support some other PHY config on stm32mp157c PHY_MODE (MII,GMII, RMII, RGMII) and in normal, PHY wo crystal (25Mhz and 50Mhz), No 125Mhz from PHY config
Can you split this into separate logical patches?
Thanks, -Joe
Signed-off-by: Christophe Roullier christophe.roullier@st.com
drivers/net/dwc_eth_qos.c | 435 +++++++++++++++++++++++++++++++++----- 1 file changed, 383 insertions(+), 52 deletions(-)
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 9f1c5af46e9..a6546d5e5ce 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -26,7 +26,6 @@
- supports a single RGMII PHY. This configuration also has SW control over
- all clock and reset signals to the HW block.
*/
#include <common.h> #include <clk.h> #include <dm.h> @@ -95,6 +94,7 @@ struct eqos_mac_regs { #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK 3 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED 0 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB 2 +#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV 1
#define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0 #define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK 0xff @@ -108,6 +108,7 @@ struct eqos_mac_regs { #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT 16 #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT 8 #define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2 +#define EQOS_MAC_MDIO_ADDRESS_CR_250_300 5 #define EQOS_MAC_MDIO_ADDRESS_SKAP BIT(4) #define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT 2 #define EQOS_MAC_MDIO_ADDRESS_GOC_READ 3 @@ -260,6 +261,29 @@ struct eqos_desc {
struct eqos_config { bool reg_access_always_ok;
int mdio_wait;
int swr_wait;
int config_mac;
int config_mac_mdio;
int (*interface)(struct udevice *dev);
struct eqos_ops *ops;
+};
+struct eqos_ops {
void (*eqos_inval_desc)(void *desc);
void (*eqos_flush_desc)(void *desc);
void (*eqos_inval_buffer)(void *buf, size_t size);
void (*eqos_flush_buffer)(void *buf, size_t size);
int (*eqos_probe_resources)(struct udevice *dev);
int (*eqos_remove_resources)(struct udevice *dev);
int (*eqos_stop_resets)(struct udevice *dev);
int (*eqos_start_resets)(struct udevice *dev);
void (*eqos_stop_clks)(struct udevice *dev);
int (*eqos_start_clks)(struct udevice *dev);
int (*eqos_calibrate_pads)(struct udevice *dev);
int (*eqos_disable_calibration)(struct udevice *dev);
int (*eqos_set_tx_clk_speed)(struct udevice *dev);
ulong (*eqos_get_tick_clk_rate)(struct udevice *dev);
};
struct eqos_priv { @@ -276,6 +300,7 @@ struct eqos_priv { struct clk clk_rx; struct clk clk_ptp_ref; struct clk clk_tx;
struct clk clk_ck; struct clk clk_slave_bus; struct mii_dev *mii; struct phy_device *phy;
@@ -327,7 +352,7 @@ static void eqos_free_descs(void *descs) #endif }
-static void eqos_inval_desc(void *desc) +static void eqos_inval_desc_tegra186(void *desc) { #ifndef CONFIG_SYS_NONCACHED_MEMORY unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); @@ -338,14 +363,36 @@ static void eqos_inval_desc(void *desc) #endif }
-static void eqos_flush_desc(void *desc) +static void eqos_inval_desc_stm32(void *desc) +{ +#ifndef CONFIG_SYS_NONCACHED_MEMORY
unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
ARCH_DMA_MINALIGN);
invalidate_dcache_range(start, end);
+#endif +}
+static void eqos_flush_desc_tegra186(void *desc) { #ifndef CONFIG_SYS_NONCACHED_MEMORY flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE); #endif }
-static void eqos_inval_buffer(void *buf, size_t size) +static void eqos_flush_desc_stm32(void *desc) +{ +#ifndef CONFIG_SYS_NONCACHED_MEMORY
unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
ARCH_DMA_MINALIGN);
flush_dcache_range(start, end);
+#endif +}
+static void eqos_inval_buffer_tegra186(void *buf, size_t size) { unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1); unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN); @@ -353,11 +400,29 @@ static void eqos_inval_buffer(void *buf, size_t size) invalidate_dcache_range(start, end); }
-static void eqos_flush_buffer(void *buf, size_t size) +static void eqos_inval_buffer_stm32(void *buf, size_t size) +{
unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)buf + size,
ARCH_DMA_MINALIGN);
invalidate_dcache_range(start, end);
+}
+static void eqos_flush_buffer_tegra186(void *buf, size_t size) { flush_cache((unsigned long)buf, size); }
+static void eqos_flush_buffer_stm32(void *buf, size_t size) +{
unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)buf + size,
ARCH_DMA_MINALIGN);
flush_dcache_range(start, end);
+}
static int eqos_mdio_wait_idle(struct eqos_priv *eqos) { return wait_for_bit_le32(&eqos->mac_regs->mdio_address, @@ -386,14 +451,14 @@ static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad, EQOS_MAC_MDIO_ADDRESS_C45E; val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
(EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
(eqos->config->config_mac_mdio << EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | (EQOS_MAC_MDIO_ADDRESS_GOC_READ << EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | EQOS_MAC_MDIO_ADDRESS_GB; writel(val, &eqos->mac_regs->mdio_address);
udelay(10);
udelay(eqos->config->mdio_wait); ret = eqos_mdio_wait_idle(eqos); if (ret) {
@@ -432,14 +497,14 @@ static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad, EQOS_MAC_MDIO_ADDRESS_C45E; val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
(EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
(eqos->config->config_mac_mdio << EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | (EQOS_MAC_MDIO_ADDRESS_GOC_WRITE << EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | EQOS_MAC_MDIO_ADDRESS_GB; writel(val, &eqos->mac_regs->mdio_address);
udelay(10);
udelay(eqos->config->mdio_wait); ret = eqos_mdio_wait_idle(eqos); if (ret) {
@@ -509,6 +574,53 @@ err: return ret; }
+static int eqos_start_clks_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
int ret;
debug("%s(dev=%p):\n", __func__, dev);
ret = clk_enable(&eqos->clk_master_bus);
if (ret < 0) {
pr_err("clk_enable(clk_master_bus) failed: %d", ret);
goto err;
}
ret = clk_enable(&eqos->clk_rx);
if (ret < 0) {
pr_err("clk_enable(clk_rx) failed: %d", ret);
goto err_disable_clk_master_bus;
}
ret = clk_enable(&eqos->clk_tx);
if (ret < 0) {
pr_err("clk_enable(clk_tx) failed: %d", ret);
goto err_disable_clk_rx;
}
if (clk_valid(&eqos->clk_ck)) {
ret = clk_enable(&eqos->clk_ck);
if (ret < 0) {
pr_err("clk_enable(clk_ck) failed: %d", ret);
goto err_disable_clk_tx;
}
}
debug("%s: OK\n", __func__);
return 0;
+err_disable_clk_tx:
clk_disable(&eqos->clk_tx);
+err_disable_clk_rx:
clk_disable(&eqos->clk_rx);
+err_disable_clk_master_bus:
clk_disable(&eqos->clk_master_bus);
+err:
debug("%s: FAILED: %d\n", __func__, ret);
return ret;
+}
void eqos_stop_clks_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -524,6 +636,21 @@ void eqos_stop_clks_tegra186(struct udevice *dev) debug("%s: OK\n", __func__); }
+void eqos_stop_clks_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
clk_disable(&eqos->clk_tx);
clk_disable(&eqos->clk_rx);
clk_disable(&eqos->clk_master_bus);
if (clk_valid(&eqos->clk_ck))
clk_disable(&eqos->clk_ck);
debug("%s: OK\n", __func__);
+}
static int eqos_start_resets_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -563,6 +690,11 @@ static int eqos_start_resets_tegra186(struct udevice *dev) return 0; }
+static int eqos_start_resets_stm32(struct udevice *dev) +{
return 0;
+}
static int eqos_stop_resets_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -573,6 +705,11 @@ static int eqos_stop_resets_tegra186(struct udevice *dev) return 0; }
+static int eqos_stop_resets_stm32(struct udevice *dev) +{
return 0;
+}
static int eqos_calibrate_pads_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -632,6 +769,23 @@ static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev) return clk_get_rate(&eqos->clk_slave_bus); }
+static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
return clk_get_rate(&eqos->clk_master_bus);
+}
+static int eqos_calibrate_pads_stm32(struct udevice *dev) +{
return 0;
+}
+static int eqos_disable_calibration_stm32(struct udevice *dev) +{
return 0;
+}
static int eqos_set_full_duplex(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -726,6 +880,11 @@ static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev) return 0; }
+static int eqos_set_tx_clk_speed_stm32(struct udevice *dev) +{
return 0;
+}
static int eqos_adjust_link(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -766,23 +925,23 @@ static int eqos_adjust_link(struct udevice *dev) }
if (en_calibration) {
ret = eqos_calibrate_pads_tegra186(dev);
ret = eqos->config->ops->eqos_calibrate_pads(dev); if (ret < 0) {
pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
pr_err("eqos_calibrate_pads() failed: %d",
ret); return ret; } } else {
ret = eqos_disable_calibration_tegra186(dev);
ret = eqos->config->ops->eqos_disable_calibration(dev); if (ret < 0) {
pr_err("eqos_disable_calibration_tegra186() failed: %d",
ret);
pr_err("eqos_disable_calibration() failed: %d",
ret); return ret; } }
ret = eqos_set_tx_clk_speed_tegra186(dev);
ret = eqos->config->ops->eqos_set_tx_clk_speed(dev); if (ret < 0) {
pr_err("eqos_set_tx_clk_speed_tegra186() failed: %d", ret);
pr_err("eqos_set_tx_clk_speed() failed: %d", ret); return ret; }
@@ -846,15 +1005,15 @@ static int eqos_start(struct udevice *dev) eqos->tx_desc_idx = 0; eqos->rx_desc_idx = 0;
ret = eqos_start_clks_tegra186(dev);
ret = eqos->config->ops->eqos_start_clks(dev); if (ret < 0) {
pr_err("eqos_start_clks_tegra186() failed: %d", ret);
pr_err("eqos_start_clks() failed: %d", ret); goto err; }
ret = eqos_start_resets_tegra186(dev);
ret = eqos->config->ops->eqos_start_resets(dev); if (ret < 0) {
pr_err("eqos_start_resets_tegra186() failed: %d", ret);
pr_err("eqos_start_resets() failed: %d", ret); goto err_stop_clks; }
@@ -863,32 +1022,41 @@ static int eqos_start(struct udevice *dev) eqos->reg_access_ok = true;
ret = wait_for_bit_le32(&eqos->dma_regs->mode,
EQOS_DMA_MODE_SWR, false, 10, false);
EQOS_DMA_MODE_SWR, false,
eqos->config->swr_wait, false); if (ret) { pr_err("EQOS_DMA_MODE_SWR stuck"); goto err_stop_resets; }
ret = eqos_calibrate_pads_tegra186(dev);
ret = eqos->config->ops->eqos_calibrate_pads(dev); if (ret < 0) {
pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
pr_err("eqos_calibrate_pads() failed: %d", ret); goto err_stop_resets; }
rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
rate = eqos_get_tick_clk_rate_tegra186(dev); val = (rate / 1000000) - 1; writel(val, &eqos->mac_regs->us_tic_counter);
eqos->phy = phy_connect(eqos->mii, 0, dev, 0);
/*
* if PHY was already connected and configured,
* don't need to reconnect/reconfigure again
*/ if (!eqos->phy) {
pr_err("phy_connect() failed");
goto err_stop_resets;
}
ret = phy_config(eqos->phy);
if (ret < 0) {
pr_err("phy_config() failed: %d", ret);
goto err_shutdown_phy;
eqos->phy = phy_connect(eqos->mii, 0, dev,
eqos->config->interface(dev));
if (!eqos->phy) {
pr_err("phy_connect() failed");
goto err_stop_resets;
}
ret = phy_config(eqos->phy);
if (ret < 0) {
pr_err("phy_config() failed: %d", ret);
goto err_shutdown_phy;
} }
ret = phy_startup(eqos->phy); if (ret < 0) { pr_err("phy_startup() failed: %d", ret);
@@ -993,7 +1161,7 @@ static int eqos_start(struct udevice *dev) clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT,
EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB <<
eqos->config->config_mac << EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); /* Set TX flow control parameters */
@@ -1074,7 +1242,7 @@ static int eqos_start(struct udevice *dev) (i * EQOS_MAX_PACKET_SIZE)); rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; }
flush_cache((unsigned long)eqos->descs, EQOS_DESCRIPTORS_SIZE);
eqos->config->ops->eqos_flush_desc(eqos->descs); writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address);
@@ -1113,11 +1281,10 @@ static int eqos_start(struct udevice *dev)
err_shutdown_phy: phy_shutdown(eqos->phy);
eqos->phy = NULL;
err_stop_resets:
eqos_stop_resets_tegra186(dev);
eqos->config->ops->eqos_stop_resets(dev);
err_stop_clks:
eqos_stop_clks_tegra186(dev);
eqos->config->ops->eqos_stop_clks(dev);
err: pr_err("FAILED: %d", ret); return ret; @@ -1170,10 +1337,9 @@ void eqos_stop(struct udevice *dev)
if (eqos->phy) { phy_shutdown(eqos->phy);
eqos->phy = NULL; }
eqos_stop_resets_tegra186(dev);
eqos_stop_clks_tegra186(dev);
eqos->config->ops->eqos_stop_resets(dev);
eqos->config->ops->eqos_stop_clks(dev); debug("%s: OK\n", __func__);
} @@ -1188,7 +1354,7 @@ int eqos_send(struct udevice *dev, void *packet, int length) length);
memcpy(eqos->tx_dma_buf, packet, length);
eqos_flush_buffer(eqos->tx_dma_buf, length);
eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length); tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]); eqos->tx_desc_idx++;
@@ -1203,12 +1369,12 @@ int eqos_send(struct udevice *dev, void *packet, int length) */ mb(); tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length;
eqos_flush_desc(tx_desc);
eqos->config->ops->eqos_flush_desc(tx_desc); writel((ulong)(tx_desc + 1), &eqos->dma_regs->ch0_txdesc_tail_pointer); for (i = 0; i < 1000000; i++) {
eqos_inval_desc(tx_desc);
eqos->config->ops->eqos_inval_desc(tx_desc); if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN)) return 0; udelay(1);
@@ -1238,7 +1404,7 @@ int eqos_recv(struct udevice *dev, int flags, uchar **packetp) length = rx_desc->des3 & 0x7fff; debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length);
eqos_inval_buffer(*packetp, length);
eqos->config->ops->eqos_inval_buffer(*packetp, length); return length;
} @@ -1269,7 +1435,7 @@ int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) */ mb(); rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
eqos_flush_desc(rx_desc);
eqos->config->ops->eqos_flush_desc(rx_desc); writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
@@ -1304,7 +1470,7 @@ static int eqos_probe_resources_core(struct udevice *dev) ret = -ENOMEM; goto err_free_descs; }
debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf); eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE); if (!eqos->rx_dma_buf) {
@@ -1312,7 +1478,7 @@ static int eqos_probe_resources_core(struct udevice *dev) ret = -ENOMEM; goto err_free_tx_dma_buf; }
debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf); eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE); if (!eqos->rx_pkt) {
@@ -1424,6 +1590,98 @@ err_free_reset_eqos: return ret; }
+/* board-specific Ethernet Interface initializations. */ +__weak int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg,
bool eth_ref_clk_sel_reg)
+{
return 0;
+}
+static int eqos_probe_resources_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
int ret;
int interface;
bool eth_clk_sel_reg = false;
bool eth_ref_clk_sel_reg = false;
debug("%s(dev=%p):\n", __func__, dev);
interface = eqos->config->interface(dev);
if (interface == -1) {
pr_err("Invalid PHY interface\n");
return -EINVAL;
}
/* Gigabit Ethernet 125MHz clock selection. */
eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
/* Ethernet 50Mhz RMII clock selection */
eth_ref_clk_sel_reg =
dev_read_bool(dev, "st,eth_ref_clk_sel");
ret = board_interface_eth_init(interface, eth_clk_sel_reg,
eth_ref_clk_sel_reg);
if (ret)
return -EINVAL;
ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
if (ret) {
pr_err("clk_get_by_name(master_bus) failed: %d", ret);
goto err_probe;
}
ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx);
if (ret) {
pr_err("clk_get_by_name(rx) failed: %d", ret);
goto err_free_clk_master_bus;
}
ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx);
if (ret) {
pr_err("clk_get_by_name(tx) failed: %d", ret);
goto err_free_clk_rx;
}
/* Get ETH_CLK clocks (optional) */
ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck);
if (ret)
pr_warn("No phy clock provided %d", ret);
debug("%s: OK\n", __func__);
return 0;
+err_free_clk_rx:
clk_free(&eqos->clk_rx);
+err_free_clk_master_bus:
clk_free(&eqos->clk_master_bus);
+err_probe:
debug("%s: returns %d\n", __func__, ret);
return ret;
+}
+static int eqos_get_interface_stm32(struct udevice *dev) +{
const char *phy_mode;
int interface = -1;
debug("%s(dev=%p):\n", __func__, dev);
phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
NULL);
if (phy_mode)
interface = phy_get_interface_by_name(phy_mode);
return interface;
+}
+static int eqos_get_interface_tegra186(struct udevice *dev) +{
return 0;
+}
static int eqos_remove_resources_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -1442,6 +1700,22 @@ static int eqos_remove_resources_tegra186(struct udevice *dev) return 0; }
+static int eqos_remove_resources_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
clk_free(&eqos->clk_tx);
clk_free(&eqos->clk_rx);
clk_free(&eqos->clk_master_bus);
if (clk_valid(&eqos->clk_ck))
clk_free(&eqos->clk_ck);
debug("%s: OK\n", __func__);
return 0;
+}
static int eqos_probe(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev); @@ -1468,15 +1742,16 @@ static int eqos_probe(struct udevice *dev) return ret; }
ret = eqos_probe_resources_tegra186(dev);
ret = eqos->config->ops->eqos_probe_resources(dev); if (ret < 0) {
pr_err("eqos_probe_resources_tegra186() failed: %d", ret);
pr_err("eqos_probe_resources() failed: %d", ret); goto err_remove_resources_core; } eqos->mii = mdio_alloc(); if (!eqos->mii) { pr_err("mdio_alloc() failed");
ret = -ENOMEM; goto err_remove_resources_tegra; } eqos->mii->read = eqos_mdio_read;
@@ -1496,7 +1771,7 @@ static int eqos_probe(struct udevice *dev) err_free_mdio: mdio_free(eqos->mii); err_remove_resources_tegra:
eqos_remove_resources_tegra186(dev);
eqos->config->ops->eqos_remove_resources(dev);
err_remove_resources_core: eqos_remove_resources_core(dev);
@@ -1512,7 +1787,8 @@ static int eqos_remove(struct udevice *dev)
mdio_unregister(eqos->mii); mdio_free(eqos->mii);
eqos_remove_resources_tegra186(dev);
eqos->config->ops->eqos_remove_resources(dev);
eqos_probe_resources_core(dev); debug("%s: OK\n", __func__);
@@ -1528,8 +1804,58 @@ static const struct eth_ops eqos_ops = { .write_hwaddr = eqos_write_hwaddr, };
+static struct eqos_ops eqos_tegra186_ops = {
.eqos_inval_desc = eqos_inval_desc_tegra186,
.eqos_flush_desc = eqos_flush_desc_tegra186,
.eqos_inval_buffer = eqos_inval_buffer_tegra186,
.eqos_flush_buffer = eqos_flush_buffer_tegra186,
.eqos_probe_resources = eqos_probe_resources_tegra186,
.eqos_remove_resources = eqos_remove_resources_tegra186,
.eqos_stop_resets = eqos_stop_resets_tegra186,
.eqos_start_resets = eqos_start_resets_tegra186,
.eqos_stop_clks = eqos_stop_clks_tegra186,
.eqos_start_clks = eqos_start_clks_tegra186,
.eqos_calibrate_pads = eqos_calibrate_pads_tegra186,
.eqos_disable_calibration = eqos_disable_calibration_tegra186,
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186,
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186
+};
static const struct eqos_config eqos_tegra186_config = { .reg_access_always_ok = false,
.mdio_wait = 10,
.swr_wait = 10,
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35,
.interface = eqos_get_interface_tegra186,
.ops = &eqos_tegra186_ops
+};
+static struct eqos_ops eqos_stm32_ops = {
.eqos_inval_desc = eqos_inval_desc_stm32,
.eqos_flush_desc = eqos_flush_desc_stm32,
.eqos_inval_buffer = eqos_inval_buffer_stm32,
.eqos_flush_buffer = eqos_flush_buffer_stm32,
.eqos_probe_resources = eqos_probe_resources_stm32,
.eqos_remove_resources = eqos_remove_resources_stm32,
.eqos_stop_resets = eqos_stop_resets_stm32,
.eqos_start_resets = eqos_start_resets_stm32,
.eqos_stop_clks = eqos_stop_clks_stm32,
.eqos_start_clks = eqos_start_clks_stm32,
.eqos_calibrate_pads = eqos_calibrate_pads_stm32,
.eqos_disable_calibration = eqos_disable_calibration_stm32,
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32,
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32
+};
+static const struct eqos_config eqos_stm32_config = {
.reg_access_always_ok = false,
.mdio_wait = 10000,
.swr_wait = 50,
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
.interface = eqos_get_interface_stm32,
.ops = &eqos_stm32_ops
};
static const struct udevice_id eqos_ids[] = { @@ -1537,6 +1863,11 @@ static const struct udevice_id eqos_ids[] = { .compatible = "nvidia,tegra186-eqos", .data = (ulong)&eqos_tegra186_config },
{
.compatible = "snps,dwmac-4.20a",
.data = (ulong)&eqos_stm32_config
},
{ }
};
-- 2.17.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

Hi Joe,
On 09/05/2019 23:07, Joe Hershberger wrote:
On Fri, Apr 26, 2019 at 6:16 AM Christophe Roullier christophe.roullier@st.com wrote:
Synopsys GMAC 4.20 is used. And Phy mode for eval and disco is RMII with PHY Realtek RTL8211 (RGMII) We also support some other PHY config on stm32mp157c PHY_MODE (MII,GMII, RMII, RGMII) and in normal, PHY wo crystal (25Mhz and 50Mhz), No 125Mhz from PHY config
Can you split this into separate logical patches?
If it is possible, I would like to keep this in same patch.
Because the choice to select phy-mode and with or without crystal is only in eqos_probe_resources_stm32 and it is managed by DT properties.
Thanks in advance.
Christophe
Thanks, -Joe
Signed-off-by: Christophe Roullierchristophe.roullier@st.com
drivers/net/dwc_eth_qos.c | 435 +++++++++++++++++++++++++++++++++----- 1 file changed, 383 insertions(+), 52 deletions(-)
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 9f1c5af46e9..a6546d5e5ce 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -26,7 +26,6 @@
- supports a single RGMII PHY. This configuration also has SW control over
- all clock and reset signals to the HW block.
*/
- #include <common.h> #include <clk.h> #include <dm.h>
@@ -95,6 +94,7 @@ struct eqos_mac_regs { #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK 3 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED 0 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB 2 +#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV 1
#define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0 #define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK 0xff @@ -108,6 +108,7 @@ struct eqos_mac_regs { #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT 16 #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT 8 #define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2 +#define EQOS_MAC_MDIO_ADDRESS_CR_250_300 5 #define EQOS_MAC_MDIO_ADDRESS_SKAP BIT(4) #define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT 2 #define EQOS_MAC_MDIO_ADDRESS_GOC_READ 3 @@ -260,6 +261,29 @@ struct eqos_desc {
struct eqos_config { bool reg_access_always_ok;
int mdio_wait;
int swr_wait;
int config_mac;
int config_mac_mdio;
int (*interface)(struct udevice *dev);
struct eqos_ops *ops;
+};
+struct eqos_ops {
void (*eqos_inval_desc)(void *desc);
void (*eqos_flush_desc)(void *desc);
void (*eqos_inval_buffer)(void *buf, size_t size);
void (*eqos_flush_buffer)(void *buf, size_t size);
int (*eqos_probe_resources)(struct udevice *dev);
int (*eqos_remove_resources)(struct udevice *dev);
int (*eqos_stop_resets)(struct udevice *dev);
int (*eqos_start_resets)(struct udevice *dev);
void (*eqos_stop_clks)(struct udevice *dev);
int (*eqos_start_clks)(struct udevice *dev);
int (*eqos_calibrate_pads)(struct udevice *dev);
int (*eqos_disable_calibration)(struct udevice *dev);
int (*eqos_set_tx_clk_speed)(struct udevice *dev);
ulong (*eqos_get_tick_clk_rate)(struct udevice *dev);
};
struct eqos_priv {
@@ -276,6 +300,7 @@ struct eqos_priv { struct clk clk_rx; struct clk clk_ptp_ref; struct clk clk_tx;
struct clk clk_ck; struct clk clk_slave_bus; struct mii_dev *mii; struct phy_device *phy;
@@ -327,7 +352,7 @@ static void eqos_free_descs(void *descs) #endif }
-static void eqos_inval_desc(void *desc) +static void eqos_inval_desc_tegra186(void *desc) { #ifndef CONFIG_SYS_NONCACHED_MEMORY unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); @@ -338,14 +363,36 @@ static void eqos_inval_desc(void *desc) #endif }
-static void eqos_flush_desc(void *desc) +static void eqos_inval_desc_stm32(void *desc) +{ +#ifndef CONFIG_SYS_NONCACHED_MEMORY
unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
ARCH_DMA_MINALIGN);
invalidate_dcache_range(start, end);
+#endif +}
+static void eqos_flush_desc_tegra186(void *desc) { #ifndef CONFIG_SYS_NONCACHED_MEMORY flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE); #endif }
-static void eqos_inval_buffer(void *buf, size_t size) +static void eqos_flush_desc_stm32(void *desc) +{ +#ifndef CONFIG_SYS_NONCACHED_MEMORY
unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
ARCH_DMA_MINALIGN);
flush_dcache_range(start, end);
+#endif +}
+static void eqos_inval_buffer_tegra186(void *buf, size_t size) { unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1); unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN); @@ -353,11 +400,29 @@ static void eqos_inval_buffer(void *buf, size_t size) invalidate_dcache_range(start, end); }
-static void eqos_flush_buffer(void *buf, size_t size) +static void eqos_inval_buffer_stm32(void *buf, size_t size) +{
unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)buf + size,
ARCH_DMA_MINALIGN);
invalidate_dcache_range(start, end);
+}
+static void eqos_flush_buffer_tegra186(void *buf, size_t size) { flush_cache((unsigned long)buf, size); }
+static void eqos_flush_buffer_stm32(void *buf, size_t size) +{
unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)buf + size,
ARCH_DMA_MINALIGN);
flush_dcache_range(start, end);
+}
- static int eqos_mdio_wait_idle(struct eqos_priv *eqos) { return wait_for_bit_le32(&eqos->mac_regs->mdio_address,
@@ -386,14 +451,14 @@ static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad, EQOS_MAC_MDIO_ADDRESS_C45E; val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
(EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
(eqos->config->config_mac_mdio << EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | (EQOS_MAC_MDIO_ADDRESS_GOC_READ << EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | EQOS_MAC_MDIO_ADDRESS_GB; writel(val, &eqos->mac_regs->mdio_address);
udelay(10);
udelay(eqos->config->mdio_wait); ret = eqos_mdio_wait_idle(eqos); if (ret) {
@@ -432,14 +497,14 @@ static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad, EQOS_MAC_MDIO_ADDRESS_C45E; val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
(EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
(eqos->config->config_mac_mdio << EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | (EQOS_MAC_MDIO_ADDRESS_GOC_WRITE << EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | EQOS_MAC_MDIO_ADDRESS_GB; writel(val, &eqos->mac_regs->mdio_address);
udelay(10);
udelay(eqos->config->mdio_wait); ret = eqos_mdio_wait_idle(eqos); if (ret) {
@@ -509,6 +574,53 @@ err: return ret; }
+static int eqos_start_clks_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
int ret;
debug("%s(dev=%p):\n", __func__, dev);
ret = clk_enable(&eqos->clk_master_bus);
if (ret < 0) {
pr_err("clk_enable(clk_master_bus) failed: %d", ret);
goto err;
}
ret = clk_enable(&eqos->clk_rx);
if (ret < 0) {
pr_err("clk_enable(clk_rx) failed: %d", ret);
goto err_disable_clk_master_bus;
}
ret = clk_enable(&eqos->clk_tx);
if (ret < 0) {
pr_err("clk_enable(clk_tx) failed: %d", ret);
goto err_disable_clk_rx;
}
if (clk_valid(&eqos->clk_ck)) {
ret = clk_enable(&eqos->clk_ck);
if (ret < 0) {
pr_err("clk_enable(clk_ck) failed: %d", ret);
goto err_disable_clk_tx;
}
}
debug("%s: OK\n", __func__);
return 0;
+err_disable_clk_tx:
clk_disable(&eqos->clk_tx);
+err_disable_clk_rx:
clk_disable(&eqos->clk_rx);
+err_disable_clk_master_bus:
clk_disable(&eqos->clk_master_bus);
+err:
debug("%s: FAILED: %d\n", __func__, ret);
return ret;
+}
- void eqos_stop_clks_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -524,6 +636,21 @@ void eqos_stop_clks_tegra186(struct udevice *dev) debug("%s: OK\n", __func__); }
+void eqos_stop_clks_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
clk_disable(&eqos->clk_tx);
clk_disable(&eqos->clk_rx);
clk_disable(&eqos->clk_master_bus);
if (clk_valid(&eqos->clk_ck))
clk_disable(&eqos->clk_ck);
debug("%s: OK\n", __func__);
+}
- static int eqos_start_resets_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -563,6 +690,11 @@ static int eqos_start_resets_tegra186(struct udevice *dev) return 0; }
+static int eqos_start_resets_stm32(struct udevice *dev) +{
return 0;
+}
- static int eqos_stop_resets_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -573,6 +705,11 @@ static int eqos_stop_resets_tegra186(struct udevice *dev) return 0; }
+static int eqos_stop_resets_stm32(struct udevice *dev) +{
return 0;
+}
- static int eqos_calibrate_pads_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -632,6 +769,23 @@ static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev) return clk_get_rate(&eqos->clk_slave_bus); }
+static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
return clk_get_rate(&eqos->clk_master_bus);
+}
+static int eqos_calibrate_pads_stm32(struct udevice *dev) +{
return 0;
+}
+static int eqos_disable_calibration_stm32(struct udevice *dev) +{
return 0;
+}
- static int eqos_set_full_duplex(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -726,6 +880,11 @@ static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev) return 0; }
+static int eqos_set_tx_clk_speed_stm32(struct udevice *dev) +{
return 0;
+}
- static int eqos_adjust_link(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -766,23 +925,23 @@ static int eqos_adjust_link(struct udevice *dev) }
if (en_calibration) {
ret = eqos_calibrate_pads_tegra186(dev);
ret = eqos->config->ops->eqos_calibrate_pads(dev); if (ret < 0) {
pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
pr_err("eqos_calibrate_pads() failed: %d",
ret); return ret; } } else {
ret = eqos_disable_calibration_tegra186(dev);
ret = eqos->config->ops->eqos_disable_calibration(dev); if (ret < 0) {
pr_err("eqos_disable_calibration_tegra186() failed: %d",
ret);
pr_err("eqos_disable_calibration() failed: %d",
ret); return ret; } }
ret = eqos_set_tx_clk_speed_tegra186(dev);
ret = eqos->config->ops->eqos_set_tx_clk_speed(dev); if (ret < 0) {
pr_err("eqos_set_tx_clk_speed_tegra186() failed: %d", ret);
pr_err("eqos_set_tx_clk_speed() failed: %d", ret); return ret; }
@@ -846,15 +1005,15 @@ static int eqos_start(struct udevice *dev) eqos->tx_desc_idx = 0; eqos->rx_desc_idx = 0;
ret = eqos_start_clks_tegra186(dev);
ret = eqos->config->ops->eqos_start_clks(dev); if (ret < 0) {
pr_err("eqos_start_clks_tegra186() failed: %d", ret);
pr_err("eqos_start_clks() failed: %d", ret); goto err; }
ret = eqos_start_resets_tegra186(dev);
ret = eqos->config->ops->eqos_start_resets(dev); if (ret < 0) {
pr_err("eqos_start_resets_tegra186() failed: %d", ret);
pr_err("eqos_start_resets() failed: %d", ret); goto err_stop_clks; }
@@ -863,32 +1022,41 @@ static int eqos_start(struct udevice *dev) eqos->reg_access_ok = true;
ret = wait_for_bit_le32(&eqos->dma_regs->mode,
EQOS_DMA_MODE_SWR, false, 10, false);
EQOS_DMA_MODE_SWR, false,
eqos->config->swr_wait, false); if (ret) { pr_err("EQOS_DMA_MODE_SWR stuck"); goto err_stop_resets; }
ret = eqos_calibrate_pads_tegra186(dev);
ret = eqos->config->ops->eqos_calibrate_pads(dev); if (ret < 0) {
pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
pr_err("eqos_calibrate_pads() failed: %d", ret); goto err_stop_resets; }
rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
rate = eqos_get_tick_clk_rate_tegra186(dev); val = (rate / 1000000) - 1; writel(val, &eqos->mac_regs->us_tic_counter);
eqos->phy = phy_connect(eqos->mii, 0, dev, 0);
/*
* if PHY was already connected and configured,
* don't need to reconnect/reconfigure again
*/ if (!eqos->phy) {
pr_err("phy_connect() failed");
goto err_stop_resets;
}
ret = phy_config(eqos->phy);
if (ret < 0) {
pr_err("phy_config() failed: %d", ret);
goto err_shutdown_phy;
eqos->phy = phy_connect(eqos->mii, 0, dev,
eqos->config->interface(dev));
if (!eqos->phy) {
pr_err("phy_connect() failed");
goto err_stop_resets;
}
ret = phy_config(eqos->phy);
if (ret < 0) {
pr_err("phy_config() failed: %d", ret);
goto err_shutdown_phy;
} }
ret = phy_startup(eqos->phy); if (ret < 0) { pr_err("phy_startup() failed: %d", ret);
@@ -993,7 +1161,7 @@ static int eqos_start(struct udevice *dev) clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT,
EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB <<
eqos->config->config_mac << EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); /* Set TX flow control parameters */
@@ -1074,7 +1242,7 @@ static int eqos_start(struct udevice *dev) (i * EQOS_MAX_PACKET_SIZE)); rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; }
flush_cache((unsigned long)eqos->descs, EQOS_DESCRIPTORS_SIZE);
eqos->config->ops->eqos_flush_desc(eqos->descs); writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address);
@@ -1113,11 +1281,10 @@ static int eqos_start(struct udevice *dev)
err_shutdown_phy: phy_shutdown(eqos->phy);
err_stop_resets:eqos->phy = NULL;
eqos_stop_resets_tegra186(dev);
err_stop_clks:eqos->config->ops->eqos_stop_resets(dev);
eqos_stop_clks_tegra186(dev);
err: pr_err("FAILED: %d", ret); return ret;eqos->config->ops->eqos_stop_clks(dev);
@@ -1170,10 +1337,9 @@ void eqos_stop(struct udevice *dev)
if (eqos->phy) { phy_shutdown(eqos->phy);
eqos->phy = NULL; }
eqos_stop_resets_tegra186(dev);
eqos_stop_clks_tegra186(dev);
eqos->config->ops->eqos_stop_resets(dev);
eqos->config->ops->eqos_stop_clks(dev); debug("%s: OK\n", __func__);
}
@@ -1188,7 +1354,7 @@ int eqos_send(struct udevice *dev, void *packet, int length) length);
memcpy(eqos->tx_dma_buf, packet, length);
eqos_flush_buffer(eqos->tx_dma_buf, length);
eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length); tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]); eqos->tx_desc_idx++;
@@ -1203,12 +1369,12 @@ int eqos_send(struct udevice *dev, void *packet, int length) */ mb(); tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length;
eqos_flush_desc(tx_desc);
eqos->config->ops->eqos_flush_desc(tx_desc); writel((ulong)(tx_desc + 1), &eqos->dma_regs->ch0_txdesc_tail_pointer); for (i = 0; i < 1000000; i++) {
eqos_inval_desc(tx_desc);
eqos->config->ops->eqos_inval_desc(tx_desc); if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN)) return 0; udelay(1);
@@ -1238,7 +1404,7 @@ int eqos_recv(struct udevice *dev, int flags, uchar **packetp) length = rx_desc->des3 & 0x7fff; debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length);
eqos_inval_buffer(*packetp, length);
eqos->config->ops->eqos_inval_buffer(*packetp, length); return length;
}
@@ -1269,7 +1435,7 @@ int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) */ mb(); rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
eqos_flush_desc(rx_desc);
eqos->config->ops->eqos_flush_desc(rx_desc); writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
@@ -1304,7 +1470,7 @@ static int eqos_probe_resources_core(struct udevice *dev) ret = -ENOMEM; goto err_free_descs; }
debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf); eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE); if (!eqos->rx_dma_buf) {
@@ -1312,7 +1478,7 @@ static int eqos_probe_resources_core(struct udevice *dev) ret = -ENOMEM; goto err_free_tx_dma_buf; }
debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf); eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE); if (!eqos->rx_pkt) {
@@ -1424,6 +1590,98 @@ err_free_reset_eqos: return ret; }
+/* board-specific Ethernet Interface initializations. */ +__weak int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg,
bool eth_ref_clk_sel_reg)
+{
return 0;
+}
+static int eqos_probe_resources_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
int ret;
int interface;
bool eth_clk_sel_reg = false;
bool eth_ref_clk_sel_reg = false;
debug("%s(dev=%p):\n", __func__, dev);
interface = eqos->config->interface(dev);
if (interface == -1) {
pr_err("Invalid PHY interface\n");
return -EINVAL;
}
/* Gigabit Ethernet 125MHz clock selection. */
eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
/* Ethernet 50Mhz RMII clock selection */
eth_ref_clk_sel_reg =
dev_read_bool(dev, "st,eth_ref_clk_sel");
ret = board_interface_eth_init(interface, eth_clk_sel_reg,
eth_ref_clk_sel_reg);
if (ret)
return -EINVAL;
ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
if (ret) {
pr_err("clk_get_by_name(master_bus) failed: %d", ret);
goto err_probe;
}
ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx);
if (ret) {
pr_err("clk_get_by_name(rx) failed: %d", ret);
goto err_free_clk_master_bus;
}
ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx);
if (ret) {
pr_err("clk_get_by_name(tx) failed: %d", ret);
goto err_free_clk_rx;
}
/* Get ETH_CLK clocks (optional) */
ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck);
if (ret)
pr_warn("No phy clock provided %d", ret);
debug("%s: OK\n", __func__);
return 0;
+err_free_clk_rx:
clk_free(&eqos->clk_rx);
+err_free_clk_master_bus:
clk_free(&eqos->clk_master_bus);
+err_probe:
debug("%s: returns %d\n", __func__, ret);
return ret;
+}
+static int eqos_get_interface_stm32(struct udevice *dev) +{
const char *phy_mode;
int interface = -1;
debug("%s(dev=%p):\n", __func__, dev);
phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
NULL);
if (phy_mode)
interface = phy_get_interface_by_name(phy_mode);
return interface;
+}
+static int eqos_get_interface_tegra186(struct udevice *dev) +{
return 0;
+}
- static int eqos_remove_resources_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1442,6 +1700,22 @@ static int eqos_remove_resources_tegra186(struct udevice *dev) return 0; }
+static int eqos_remove_resources_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
clk_free(&eqos->clk_tx);
clk_free(&eqos->clk_rx);
clk_free(&eqos->clk_master_bus);
if (clk_valid(&eqos->clk_ck))
clk_free(&eqos->clk_ck);
debug("%s: OK\n", __func__);
return 0;
+}
- static int eqos_probe(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1468,15 +1742,16 @@ static int eqos_probe(struct udevice *dev) return ret; }
ret = eqos_probe_resources_tegra186(dev);
ret = eqos->config->ops->eqos_probe_resources(dev); if (ret < 0) {
pr_err("eqos_probe_resources_tegra186() failed: %d", ret);
pr_err("eqos_probe_resources() failed: %d", ret); goto err_remove_resources_core; } eqos->mii = mdio_alloc(); if (!eqos->mii) { pr_err("mdio_alloc() failed");
ret = -ENOMEM; goto err_remove_resources_tegra; } eqos->mii->read = eqos_mdio_read;
@@ -1496,7 +1771,7 @@ static int eqos_probe(struct udevice *dev) err_free_mdio: mdio_free(eqos->mii); err_remove_resources_tegra:
eqos_remove_resources_tegra186(dev);
err_remove_resources_core: eqos_remove_resources_core(dev);eqos->config->ops->eqos_remove_resources(dev);
@@ -1512,7 +1787,8 @@ static int eqos_remove(struct udevice *dev)
mdio_unregister(eqos->mii); mdio_free(eqos->mii);
eqos_remove_resources_tegra186(dev);
eqos->config->ops->eqos_remove_resources(dev);
eqos_probe_resources_core(dev); debug("%s: OK\n", __func__);
@@ -1528,8 +1804,58 @@ static const struct eth_ops eqos_ops = { .write_hwaddr = eqos_write_hwaddr, };
+static struct eqos_ops eqos_tegra186_ops = {
.eqos_inval_desc = eqos_inval_desc_tegra186,
.eqos_flush_desc = eqos_flush_desc_tegra186,
.eqos_inval_buffer = eqos_inval_buffer_tegra186,
.eqos_flush_buffer = eqos_flush_buffer_tegra186,
.eqos_probe_resources = eqos_probe_resources_tegra186,
.eqos_remove_resources = eqos_remove_resources_tegra186,
.eqos_stop_resets = eqos_stop_resets_tegra186,
.eqos_start_resets = eqos_start_resets_tegra186,
.eqos_stop_clks = eqos_stop_clks_tegra186,
.eqos_start_clks = eqos_start_clks_tegra186,
.eqos_calibrate_pads = eqos_calibrate_pads_tegra186,
.eqos_disable_calibration = eqos_disable_calibration_tegra186,
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186,
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186
+};
- static const struct eqos_config eqos_tegra186_config = { .reg_access_always_ok = false,
.mdio_wait = 10,
.swr_wait = 10,
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35,
.interface = eqos_get_interface_tegra186,
.ops = &eqos_tegra186_ops
+};
+static struct eqos_ops eqos_stm32_ops = {
.eqos_inval_desc = eqos_inval_desc_stm32,
.eqos_flush_desc = eqos_flush_desc_stm32,
.eqos_inval_buffer = eqos_inval_buffer_stm32,
.eqos_flush_buffer = eqos_flush_buffer_stm32,
.eqos_probe_resources = eqos_probe_resources_stm32,
.eqos_remove_resources = eqos_remove_resources_stm32,
.eqos_stop_resets = eqos_stop_resets_stm32,
.eqos_start_resets = eqos_start_resets_stm32,
.eqos_stop_clks = eqos_stop_clks_stm32,
.eqos_start_clks = eqos_start_clks_stm32,
.eqos_calibrate_pads = eqos_calibrate_pads_stm32,
.eqos_disable_calibration = eqos_disable_calibration_stm32,
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32,
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32
+};
+static const struct eqos_config eqos_stm32_config = {
.reg_access_always_ok = false,
.mdio_wait = 10000,
.swr_wait = 50,
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
.interface = eqos_get_interface_stm32,
.ops = &eqos_stm32_ops
};
static const struct udevice_id eqos_ids[] = {
@@ -1537,6 +1863,11 @@ static const struct udevice_id eqos_ids[] = { .compatible = "nvidia,tegra186-eqos", .data = (ulong)&eqos_tegra186_config },
{
.compatible = "snps,dwmac-4.20a",
.data = (ulong)&eqos_stm32_config
},
};{ }
-- 2.17.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

On Fri, May 10, 2019 at 8:59 AM Christophe ROULLIER christophe.roullier@st.com wrote:
Hi Joe,
On 09/05/2019 23:07, Joe Hershberger wrote:
On Fri, Apr 26, 2019 at 6:16 AM Christophe Roullier christophe.roullier@st.com wrote:
Synopsys GMAC 4.20 is used. And Phy mode for eval and disco is RMII with PHY Realtek RTL8211 (RGMII) We also support some other PHY config on stm32mp157c PHY_MODE (MII,GMII, RMII, RGMII) and in normal, PHY wo crystal (25Mhz and 50Mhz), No 125Mhz from PHY config
Can you split this into separate logical patches?
If it is possible, I would like to keep this in same patch.
Because the choice to select phy-mode and with or without crystal is only in eqos_probe_resources_stm32 and it is managed by DT properties.
OK.
Thanks in advance.
Christophe
Thanks, -Joe
Signed-off-by: Christophe Roullierchristophe.roullier@st.com
drivers/net/dwc_eth_qos.c | 435 +++++++++++++++++++++++++++++++++----- 1 file changed, 383 insertions(+), 52 deletions(-)
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 9f1c5af46e9..a6546d5e5ce 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -26,7 +26,6 @@
- supports a single RGMII PHY. This configuration also has SW control over
- all clock and reset signals to the HW block.
*/
- #include <common.h> #include <clk.h> #include <dm.h>
@@ -95,6 +94,7 @@ struct eqos_mac_regs { #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK 3 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED 0 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB 2 +#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV 1
#define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0 #define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK 0xff @@ -108,6 +108,7 @@ struct eqos_mac_regs { #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT 16 #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT 8 #define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2 +#define EQOS_MAC_MDIO_ADDRESS_CR_250_300 5 #define EQOS_MAC_MDIO_ADDRESS_SKAP BIT(4) #define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT 2 #define EQOS_MAC_MDIO_ADDRESS_GOC_READ 3 @@ -260,6 +261,29 @@ struct eqos_desc {
struct eqos_config { bool reg_access_always_ok;
int mdio_wait;
int swr_wait;
int config_mac;
int config_mac_mdio;
int (*interface)(struct udevice *dev);
Shouldn't the return type be phy_interface_t?
struct eqos_ops *ops;
+};
+struct eqos_ops {
void (*eqos_inval_desc)(void *desc);
void (*eqos_flush_desc)(void *desc);
void (*eqos_inval_buffer)(void *buf, size_t size);
void (*eqos_flush_buffer)(void *buf, size_t size);
int (*eqos_probe_resources)(struct udevice *dev);
int (*eqos_remove_resources)(struct udevice *dev);
int (*eqos_stop_resets)(struct udevice *dev);
int (*eqos_start_resets)(struct udevice *dev);
void (*eqos_stop_clks)(struct udevice *dev);
int (*eqos_start_clks)(struct udevice *dev);
int (*eqos_calibrate_pads)(struct udevice *dev);
int (*eqos_disable_calibration)(struct udevice *dev);
int (*eqos_set_tx_clk_speed)(struct udevice *dev);
ulong (*eqos_get_tick_clk_rate)(struct udevice *dev);
};
struct eqos_priv {
@@ -276,6 +300,7 @@ struct eqos_priv { struct clk clk_rx; struct clk clk_ptp_ref; struct clk clk_tx;
struct clk clk_ck; struct clk clk_slave_bus; struct mii_dev *mii; struct phy_device *phy;
@@ -327,7 +352,7 @@ static void eqos_free_descs(void *descs) #endif }
-static void eqos_inval_desc(void *desc) +static void eqos_inval_desc_tegra186(void *desc) { #ifndef CONFIG_SYS_NONCACHED_MEMORY unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1); @@ -338,14 +363,36 @@ static void eqos_inval_desc(void *desc) #endif }
-static void eqos_flush_desc(void *desc) +static void eqos_inval_desc_stm32(void *desc) +{ +#ifndef CONFIG_SYS_NONCACHED_MEMORY
unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
ARCH_DMA_MINALIGN);
invalidate_dcache_range(start, end);
+#endif +}
+static void eqos_flush_desc_tegra186(void *desc) { #ifndef CONFIG_SYS_NONCACHED_MEMORY flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE); #endif }
-static void eqos_inval_buffer(void *buf, size_t size) +static void eqos_flush_desc_stm32(void *desc) +{ +#ifndef CONFIG_SYS_NONCACHED_MEMORY
unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
ARCH_DMA_MINALIGN);
flush_dcache_range(start, end);
+#endif +}
+static void eqos_inval_buffer_tegra186(void *buf, size_t size) { unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1); unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN); @@ -353,11 +400,29 @@ static void eqos_inval_buffer(void *buf, size_t size) invalidate_dcache_range(start, end); }
-static void eqos_flush_buffer(void *buf, size_t size) +static void eqos_inval_buffer_stm32(void *buf, size_t size) +{
unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)buf + size,
ARCH_DMA_MINALIGN);
invalidate_dcache_range(start, end);
+}
+static void eqos_flush_buffer_tegra186(void *buf, size_t size) { flush_cache((unsigned long)buf, size); }
+static void eqos_flush_buffer_stm32(void *buf, size_t size) +{
unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
unsigned long end = roundup((unsigned long)buf + size,
ARCH_DMA_MINALIGN);
flush_dcache_range(start, end);
+}
- static int eqos_mdio_wait_idle(struct eqos_priv *eqos) { return wait_for_bit_le32(&eqos->mac_regs->mdio_address,
@@ -386,14 +451,14 @@ static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad, EQOS_MAC_MDIO_ADDRESS_C45E; val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
(EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
(eqos->config->config_mac_mdio << EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | (EQOS_MAC_MDIO_ADDRESS_GOC_READ << EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | EQOS_MAC_MDIO_ADDRESS_GB; writel(val, &eqos->mac_regs->mdio_address);
udelay(10);
udelay(eqos->config->mdio_wait); ret = eqos_mdio_wait_idle(eqos); if (ret) {
@@ -432,14 +497,14 @@ static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad, EQOS_MAC_MDIO_ADDRESS_C45E; val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) | (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
(EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
(eqos->config->config_mac_mdio << EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) | (EQOS_MAC_MDIO_ADDRESS_GOC_WRITE << EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) | EQOS_MAC_MDIO_ADDRESS_GB; writel(val, &eqos->mac_regs->mdio_address);
udelay(10);
udelay(eqos->config->mdio_wait); ret = eqos_mdio_wait_idle(eqos); if (ret) {
@@ -509,6 +574,53 @@ err: return ret; }
+static int eqos_start_clks_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
int ret;
debug("%s(dev=%p):\n", __func__, dev);
ret = clk_enable(&eqos->clk_master_bus);
if (ret < 0) {
pr_err("clk_enable(clk_master_bus) failed: %d", ret);
goto err;
}
ret = clk_enable(&eqos->clk_rx);
if (ret < 0) {
pr_err("clk_enable(clk_rx) failed: %d", ret);
goto err_disable_clk_master_bus;
}
ret = clk_enable(&eqos->clk_tx);
if (ret < 0) {
pr_err("clk_enable(clk_tx) failed: %d", ret);
goto err_disable_clk_rx;
}
if (clk_valid(&eqos->clk_ck)) {
ret = clk_enable(&eqos->clk_ck);
if (ret < 0) {
pr_err("clk_enable(clk_ck) failed: %d", ret);
goto err_disable_clk_tx;
}
}
debug("%s: OK\n", __func__);
return 0;
+err_disable_clk_tx:
clk_disable(&eqos->clk_tx);
+err_disable_clk_rx:
clk_disable(&eqos->clk_rx);
+err_disable_clk_master_bus:
clk_disable(&eqos->clk_master_bus);
+err:
debug("%s: FAILED: %d\n", __func__, ret);
return ret;
+}
- void eqos_stop_clks_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -524,6 +636,21 @@ void eqos_stop_clks_tegra186(struct udevice *dev) debug("%s: OK\n", __func__); }
+void eqos_stop_clks_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
clk_disable(&eqos->clk_tx);
clk_disable(&eqos->clk_rx);
clk_disable(&eqos->clk_master_bus);
if (clk_valid(&eqos->clk_ck))
clk_disable(&eqos->clk_ck);
debug("%s: OK\n", __func__);
+}
- static int eqos_start_resets_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -563,6 +690,11 @@ static int eqos_start_resets_tegra186(struct udevice *dev) return 0; }
+static int eqos_start_resets_stm32(struct udevice *dev) +{
return 0;
+}
- static int eqos_stop_resets_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -573,6 +705,11 @@ static int eqos_stop_resets_tegra186(struct udevice *dev) return 0; }
+static int eqos_stop_resets_stm32(struct udevice *dev) +{
return 0;
+}
- static int eqos_calibrate_pads_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -632,6 +769,23 @@ static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev) return clk_get_rate(&eqos->clk_slave_bus); }
+static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
return clk_get_rate(&eqos->clk_master_bus);
+}
+static int eqos_calibrate_pads_stm32(struct udevice *dev) +{
return 0;
+}
+static int eqos_disable_calibration_stm32(struct udevice *dev) +{
return 0;
+}
- static int eqos_set_full_duplex(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -726,6 +880,11 @@ static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev) return 0; }
+static int eqos_set_tx_clk_speed_stm32(struct udevice *dev) +{
return 0;
+}
- static int eqos_adjust_link(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -766,23 +925,23 @@ static int eqos_adjust_link(struct udevice *dev) }
if (en_calibration) {
ret = eqos_calibrate_pads_tegra186(dev);
ret = eqos->config->ops->eqos_calibrate_pads(dev); if (ret < 0) {
pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
pr_err("eqos_calibrate_pads() failed: %d",
ret); return ret; } } else {
ret = eqos_disable_calibration_tegra186(dev);
ret = eqos->config->ops->eqos_disable_calibration(dev); if (ret < 0) {
pr_err("eqos_disable_calibration_tegra186() failed: %d",
ret);
pr_err("eqos_disable_calibration() failed: %d",
ret); return ret; } }
ret = eqos_set_tx_clk_speed_tegra186(dev);
ret = eqos->config->ops->eqos_set_tx_clk_speed(dev); if (ret < 0) {
pr_err("eqos_set_tx_clk_speed_tegra186() failed: %d", ret);
pr_err("eqos_set_tx_clk_speed() failed: %d", ret); return ret; }
@@ -846,15 +1005,15 @@ static int eqos_start(struct udevice *dev) eqos->tx_desc_idx = 0; eqos->rx_desc_idx = 0;
ret = eqos_start_clks_tegra186(dev);
ret = eqos->config->ops->eqos_start_clks(dev); if (ret < 0) {
pr_err("eqos_start_clks_tegra186() failed: %d", ret);
pr_err("eqos_start_clks() failed: %d", ret); goto err; }
ret = eqos_start_resets_tegra186(dev);
ret = eqos->config->ops->eqos_start_resets(dev); if (ret < 0) {
pr_err("eqos_start_resets_tegra186() failed: %d", ret);
pr_err("eqos_start_resets() failed: %d", ret); goto err_stop_clks; }
@@ -863,32 +1022,41 @@ static int eqos_start(struct udevice *dev) eqos->reg_access_ok = true;
ret = wait_for_bit_le32(&eqos->dma_regs->mode,
EQOS_DMA_MODE_SWR, false, 10, false);
EQOS_DMA_MODE_SWR, false,
eqos->config->swr_wait, false); if (ret) { pr_err("EQOS_DMA_MODE_SWR stuck"); goto err_stop_resets; }
ret = eqos_calibrate_pads_tegra186(dev);
ret = eqos->config->ops->eqos_calibrate_pads(dev); if (ret < 0) {
pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
pr_err("eqos_calibrate_pads() failed: %d", ret); goto err_stop_resets; }
rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
rate = eqos_get_tick_clk_rate_tegra186(dev); val = (rate / 1000000) - 1; writel(val, &eqos->mac_regs->us_tic_counter);
eqos->phy = phy_connect(eqos->mii, 0, dev, 0);
/*
* if PHY was already connected and configured,
* don't need to reconnect/reconfigure again
*/ if (!eqos->phy) {
pr_err("phy_connect() failed");
goto err_stop_resets;
}
ret = phy_config(eqos->phy);
if (ret < 0) {
pr_err("phy_config() failed: %d", ret);
goto err_shutdown_phy;
eqos->phy = phy_connect(eqos->mii, 0, dev,
eqos->config->interface(dev));
if (!eqos->phy) {
pr_err("phy_connect() failed");
goto err_stop_resets;
}
ret = phy_config(eqos->phy);
if (ret < 0) {
pr_err("phy_config() failed: %d", ret);
goto err_shutdown_phy;
} }
ret = phy_startup(eqos->phy); if (ret < 0) { pr_err("phy_startup() failed: %d", ret);
@@ -993,7 +1161,7 @@ static int eqos_start(struct udevice *dev) clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0, EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK << EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT,
EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB <<
eqos->config->config_mac << EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); /* Set TX flow control parameters */
@@ -1074,7 +1242,7 @@ static int eqos_start(struct udevice *dev) (i * EQOS_MAX_PACKET_SIZE)); rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; }
flush_cache((unsigned long)eqos->descs, EQOS_DESCRIPTORS_SIZE);
eqos->config->ops->eqos_flush_desc(eqos->descs); writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress); writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address);
@@ -1113,11 +1281,10 @@ static int eqos_start(struct udevice *dev)
err_shutdown_phy: phy_shutdown(eqos->phy);
err_stop_resets:eqos->phy = NULL;
eqos_stop_resets_tegra186(dev);
err_stop_clks:eqos->config->ops->eqos_stop_resets(dev);
eqos_stop_clks_tegra186(dev);
err: pr_err("FAILED: %d", ret); return ret;eqos->config->ops->eqos_stop_clks(dev);
@@ -1170,10 +1337,9 @@ void eqos_stop(struct udevice *dev)
if (eqos->phy) { phy_shutdown(eqos->phy);
eqos->phy = NULL; }
eqos_stop_resets_tegra186(dev);
eqos_stop_clks_tegra186(dev);
eqos->config->ops->eqos_stop_resets(dev);
eqos->config->ops->eqos_stop_clks(dev); debug("%s: OK\n", __func__);
}
@@ -1188,7 +1354,7 @@ int eqos_send(struct udevice *dev, void *packet, int length) length);
memcpy(eqos->tx_dma_buf, packet, length);
eqos_flush_buffer(eqos->tx_dma_buf, length);
eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length); tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]); eqos->tx_desc_idx++;
@@ -1203,12 +1369,12 @@ int eqos_send(struct udevice *dev, void *packet, int length) */ mb(); tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length;
eqos_flush_desc(tx_desc);
eqos->config->ops->eqos_flush_desc(tx_desc); writel((ulong)(tx_desc + 1), &eqos->dma_regs->ch0_txdesc_tail_pointer); for (i = 0; i < 1000000; i++) {
eqos_inval_desc(tx_desc);
eqos->config->ops->eqos_inval_desc(tx_desc); if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN)) return 0; udelay(1);
@@ -1238,7 +1404,7 @@ int eqos_recv(struct udevice *dev, int flags, uchar **packetp) length = rx_desc->des3 & 0x7fff; debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length);
eqos_inval_buffer(*packetp, length);
eqos->config->ops->eqos_inval_buffer(*packetp, length); return length;
}
@@ -1269,7 +1435,7 @@ int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) */ mb(); rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
eqos_flush_desc(rx_desc);
eqos->config->ops->eqos_flush_desc(rx_desc); writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
@@ -1304,7 +1470,7 @@ static int eqos_probe_resources_core(struct udevice *dev) ret = -ENOMEM; goto err_free_descs; }
debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf); eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE); if (!eqos->rx_dma_buf) {
@@ -1312,7 +1478,7 @@ static int eqos_probe_resources_core(struct udevice *dev) ret = -ENOMEM; goto err_free_tx_dma_buf; }
debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf); eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE); if (!eqos->rx_pkt) {
@@ -1424,6 +1590,98 @@ err_free_reset_eqos: return ret; }
+/* board-specific Ethernet Interface initializations. */ +__weak int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg,
bool eth_ref_clk_sel_reg)
+{
return 0;
+}
+static int eqos_probe_resources_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
int ret;
int interface;
bool eth_clk_sel_reg = false;
bool eth_ref_clk_sel_reg = false;
debug("%s(dev=%p):\n", __func__, dev);
interface = eqos->config->interface(dev);
if (interface == -1) {
I think it would be better to check for PHY_INTERFACE_MODE_NONE here and return it in the DT parsing.
pr_err("Invalid PHY interface\n");
return -EINVAL;
}
/* Gigabit Ethernet 125MHz clock selection. */
eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
/* Ethernet 50Mhz RMII clock selection */
eth_ref_clk_sel_reg =
dev_read_bool(dev, "st,eth_ref_clk_sel");
ret = board_interface_eth_init(interface, eth_clk_sel_reg,
eth_ref_clk_sel_reg);
if (ret)
return -EINVAL;
ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
if (ret) {
pr_err("clk_get_by_name(master_bus) failed: %d", ret);
goto err_probe;
}
ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx);
if (ret) {
pr_err("clk_get_by_name(rx) failed: %d", ret);
goto err_free_clk_master_bus;
}
ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx);
if (ret) {
pr_err("clk_get_by_name(tx) failed: %d", ret);
goto err_free_clk_rx;
}
/* Get ETH_CLK clocks (optional) */
ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck);
if (ret)
pr_warn("No phy clock provided %d", ret);
debug("%s: OK\n", __func__);
return 0;
+err_free_clk_rx:
clk_free(&eqos->clk_rx);
+err_free_clk_master_bus:
clk_free(&eqos->clk_master_bus);
+err_probe:
debug("%s: returns %d\n", __func__, ret);
return ret;
+}
+static int eqos_get_interface_stm32(struct udevice *dev)
Shouldn't the return type be phy_interface_t?
+{
const char *phy_mode;
int interface = -1;
I think it would be better to default this to PHY_INTERFACE_MODE_NONE.
debug("%s(dev=%p):\n", __func__, dev);
phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
NULL);
if (phy_mode)
interface = phy_get_interface_by_name(phy_mode);
return interface;
+}
+static int eqos_get_interface_tegra186(struct udevice *dev)
Shouldn't the return type be phy_interface_t?
+{
return 0;
This should be PHY_INTERFACE_MODE_MII.
+}
- static int eqos_remove_resources_tegra186(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1442,6 +1700,22 @@ static int eqos_remove_resources_tegra186(struct udevice *dev) return 0; }
+static int eqos_remove_resources_stm32(struct udevice *dev) +{
struct eqos_priv *eqos = dev_get_priv(dev);
debug("%s(dev=%p):\n", __func__, dev);
clk_free(&eqos->clk_tx);
clk_free(&eqos->clk_rx);
clk_free(&eqos->clk_master_bus);
if (clk_valid(&eqos->clk_ck))
clk_free(&eqos->clk_ck);
debug("%s: OK\n", __func__);
return 0;
+}
- static int eqos_probe(struct udevice *dev) { struct eqos_priv *eqos = dev_get_priv(dev);
@@ -1468,15 +1742,16 @@ static int eqos_probe(struct udevice *dev) return ret; }
ret = eqos_probe_resources_tegra186(dev);
ret = eqos->config->ops->eqos_probe_resources(dev); if (ret < 0) {
pr_err("eqos_probe_resources_tegra186() failed: %d", ret);
pr_err("eqos_probe_resources() failed: %d", ret); goto err_remove_resources_core; } eqos->mii = mdio_alloc(); if (!eqos->mii) { pr_err("mdio_alloc() failed");
ret = -ENOMEM; goto err_remove_resources_tegra; } eqos->mii->read = eqos_mdio_read;
@@ -1496,7 +1771,7 @@ static int eqos_probe(struct udevice *dev) err_free_mdio: mdio_free(eqos->mii); err_remove_resources_tegra:
eqos_remove_resources_tegra186(dev);
err_remove_resources_core: eqos_remove_resources_core(dev);eqos->config->ops->eqos_remove_resources(dev);
@@ -1512,7 +1787,8 @@ static int eqos_remove(struct udevice *dev)
mdio_unregister(eqos->mii); mdio_free(eqos->mii);
eqos_remove_resources_tegra186(dev);
eqos->config->ops->eqos_remove_resources(dev);
eqos_probe_resources_core(dev); debug("%s: OK\n", __func__);
@@ -1528,8 +1804,58 @@ static const struct eth_ops eqos_ops = { .write_hwaddr = eqos_write_hwaddr, };
+static struct eqos_ops eqos_tegra186_ops = {
.eqos_inval_desc = eqos_inval_desc_tegra186,
.eqos_flush_desc = eqos_flush_desc_tegra186,
.eqos_inval_buffer = eqos_inval_buffer_tegra186,
.eqos_flush_buffer = eqos_flush_buffer_tegra186,
.eqos_probe_resources = eqos_probe_resources_tegra186,
.eqos_remove_resources = eqos_remove_resources_tegra186,
.eqos_stop_resets = eqos_stop_resets_tegra186,
.eqos_start_resets = eqos_start_resets_tegra186,
.eqos_stop_clks = eqos_stop_clks_tegra186,
.eqos_start_clks = eqos_start_clks_tegra186,
.eqos_calibrate_pads = eqos_calibrate_pads_tegra186,
.eqos_disable_calibration = eqos_disable_calibration_tegra186,
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186,
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186
+};
- static const struct eqos_config eqos_tegra186_config = { .reg_access_always_ok = false,
.mdio_wait = 10,
.swr_wait = 10,
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35,
.interface = eqos_get_interface_tegra186,
.ops = &eqos_tegra186_ops
+};
+static struct eqos_ops eqos_stm32_ops = {
.eqos_inval_desc = eqos_inval_desc_stm32,
.eqos_flush_desc = eqos_flush_desc_stm32,
.eqos_inval_buffer = eqos_inval_buffer_stm32,
.eqos_flush_buffer = eqos_flush_buffer_stm32,
.eqos_probe_resources = eqos_probe_resources_stm32,
.eqos_remove_resources = eqos_remove_resources_stm32,
.eqos_stop_resets = eqos_stop_resets_stm32,
.eqos_start_resets = eqos_start_resets_stm32,
.eqos_stop_clks = eqos_stop_clks_stm32,
.eqos_start_clks = eqos_start_clks_stm32,
.eqos_calibrate_pads = eqos_calibrate_pads_stm32,
.eqos_disable_calibration = eqos_disable_calibration_stm32,
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32,
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32
+};
+static const struct eqos_config eqos_stm32_config = {
.reg_access_always_ok = false,
.mdio_wait = 10000,
.swr_wait = 50,
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
.interface = eqos_get_interface_stm32,
.ops = &eqos_stm32_ops
};
static const struct udevice_id eqos_ids[] = {
@@ -1537,6 +1863,11 @@ static const struct udevice_id eqos_ids[] = { .compatible = "nvidia,tegra186-eqos", .data = (ulong)&eqos_tegra186_config },
{
.compatible = "snps,dwmac-4.20a",
.data = (ulong)&eqos_stm32_config
},
};{ }
-- 2.17.1
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot

This patch add Ethernet support on stm32mp157 eval board
Signed-off-by: Christophe Roullier christophe.roullier@st.com ---
arch/arm/dts/stm32mp157-pinctrl.dtsi | 31 ++++++++++++++++++++++++ arch/arm/dts/stm32mp157c-ev1.dts | 21 +++++++++++++++++ arch/arm/dts/stm32mp157c.dtsi | 35 ++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+)
diff --git a/arch/arm/dts/stm32mp157-pinctrl.dtsi b/arch/arm/dts/stm32mp157-pinctrl.dtsi index 85da5926551..66723b01749 100644 --- a/arch/arm/dts/stm32mp157-pinctrl.dtsi +++ b/arch/arm/dts/stm32mp157-pinctrl.dtsi @@ -157,6 +157,37 @@ }; };
+ ethernet0_rgmii_pins_a: rgmii-0 { + pins1 { + pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */ + <STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */ + <STM32_PINMUX('G', 13, AF11)>, /* ETH_RGMII_TXD0 */ + <STM32_PINMUX('G', 14, AF11)>, /* ETH_RGMII_TXD1 */ + <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */ + <STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */ + <STM32_PINMUX('B', 11, AF11)>, /* ETH_RGMII_TX_CTL */ + <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + pins2 { + pinmux = <STM32_PINMUX('A', 2, AF11)>; /* ETH_MDIO */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins3 { + pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */ + <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */ + <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */ + <STM32_PINMUX('B', 1, AF11)>, /* ETH_RGMII_RXD3 */ + <STM32_PINMUX('A', 1, AF11)>, /* ETH_RGMII_RX_CLK */ + <STM32_PINMUX('A', 7, AF11)>; /* ETH_RGMII_RX_CTL */ + bias-disable; + }; + }; + i2c1_pins_a: i2c1-0 { pins { pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */ diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts index 902a42bee29..bdbf7fbd105 100644 --- a/arch/arm/dts/stm32mp157c-ev1.dts +++ b/arch/arm/dts/stm32mp157c-ev1.dts @@ -11,6 +11,9 @@ model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157";
+ aliases { + ethernet0 = ðernet0; + }; };
&cec { @@ -19,6 +22,24 @@ status = "okay"; };
+ðernet0 { + status = "okay"; + pinctrl-0 = <ðernet0_rgmii_pins_a>; + pinctrl-names = "default"; + phy-mode = "rgmii-id"; + max-speed = <1000>; + phy-handle = <&phy0>; + + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; +}; + &i2c2 { pinctrl-names = "default"; pinctrl-0 = <&i2c2_pins_a>; diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi index 37cadfa30c9..1271abf42e6 100644 --- a/arch/arm/dts/stm32mp157c.dtsi +++ b/arch/arm/dts/stm32mp157c.dtsi @@ -915,6 +915,41 @@ status = "disabled"; };
+ stmmac_axi_config_0: stmmac-axi-config { + snps,wr_osr_lmt = <0x7>; + snps,rd_osr_lmt = <0x7>; + snps,blen = <0 0 0 0 16 8 4>; + }; + + ethernet0: ethernet@5800a000 { + compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a"; + reg = <0x5800a000 0x2000>; + reg-names = "stmmaceth"; + interrupts-extended = + <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>, + <&exti 70 1>; + interrupt-names = "macirq", + "eth_wake_irq", + "stm32_pwr_wakeup"; + clock-names = "stmmaceth", + "mac-clk-tx", + "mac-clk-rx", + "ethstp"; + clocks = <&rcc ETHMAC>, + <&rcc ETHTX>, + <&rcc ETHRX>, + <&rcc ETHSTP>; + st,syscon = <&syscfg 0x4>; + snps,mixed-burst; + snps,pbl = <2>; + snps,en-tx-lpi-clockgating; + snps,axi-config = <&stmmac_axi_config_0>; + snps,tso; + power-domains = <&pd_core>; + status = "disabled"; + }; + usbh_ohci: usbh-ohci@5800c000 { compatible = "generic-ohci"; reg = <0x5800c000 0x1000>;

Add default SERVERIP address Enable noncached memory region required by ethernet driver Add PXE support
Signed-off-by: Christophe Roullier christophe.roullier@st.com ---
include/configs/stm32mp1.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h index 701298cab88..846952900f6 100644 --- a/include/configs/stm32mp1.h +++ b/include/configs/stm32mp1.h @@ -73,12 +73,21 @@ #define CONFIG_SYS_MMC_MAX_DEVICE 3 #define CONFIG_SUPPORT_EMMC_BOOT
+/* Ethernet need */ +#ifdef CONFIG_DWC_ETH_QOS +#define CONFIG_SYS_NONCACHED_MEMORY (1 * SZ_1M) /* 1M */ +#define CONFIG_SERVERIP 192.168.1.1 +#define CONFIG_BOOTP_SERVERIP +#define CONFIG_SYS_AUTOLOAD "no" +#endif + #if !defined(CONFIG_SPL) || !defined(CONFIG_SPL_BUILD)
#define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 1) \ func(MMC, mmc, 0) \ - func(MMC, mmc, 2) + func(MMC, mmc, 2) \ + func(PXE, pxe, na)
#include <config_distro_bootcmd.h>

This allows to enable Ethernet and use driver for Synopsys Ethernet QoS device
Signed-off-by: Christophe Roullier christophe.roullier@st.com ---
configs/stm32mp15_basic_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index d20b2ab3508..38a2a0aeefa 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -41,6 +41,8 @@ CONFIG_LED=y CONFIG_LED_GPIO=y CONFIG_DM_MMC=y CONFIG_STM32_SDMMC2=y +CONFIG_DM_ETH=y +CONFIG_DWC_ETH_QOS=y CONFIG_PHY=y CONFIG_PHY_STM32_USBPHYC=y # CONFIG_PINCTRL_FULL is not set
participants (3)
-
Christophe ROULLIER
-
Christophe Roullier
-
Joe Hershberger