* [U-Boot] [PATCH 0/6] - Add Ethernet support for stm32mpu
@ 2019-03-05 10:09 Christophe Roullier
2019-03-05 10:09 ` [U-Boot] [PATCH 1/6] stm32mp1: clk: use the correct identifier for ethck Christophe Roullier
` (5 more replies)
0 siblings, 6 replies; 13+ messages in thread
From: Christophe Roullier @ 2019-03-05 10:09 UTC (permalink / raw)
To: u-boot
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
Patrick Delaunay (1):
stm32mp1: clk: use the correct identifier for ethck
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/clk/clk_stm32mp1.c | 2 +-
drivers/net/dwc_eth_qos.c | 435 ++++++++++++++++++++++++++++++-----
include/configs/stm32mp1.h | 11 +-
8 files changed, 560 insertions(+), 54 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 1/6] stm32mp1: clk: use the correct identifier for ethck
2019-03-05 10:09 [U-Boot] [PATCH 0/6] - Add Ethernet support for stm32mpu Christophe Roullier
@ 2019-03-05 10:09 ` Christophe Roullier
2019-04-19 15:05 ` Patrick DELAUNAY
2019-03-05 10:09 ` [U-Boot] [PATCH 2/6] board: stm32mp1: Add board_interface_eth_init Christophe Roullier
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Christophe Roullier @ 2019-03-05 10:09 UTC (permalink / raw)
To: u-boot
From: Patrick Delaunay <patrick.delaunay@st.com>
ETHCK_K is the identifier the kernel clock for ETH in kernel
binding, selected by ETHKSELR / gated by ETHCKEN = BIT(7).
U-Boot driver need to use the same identifier, so change ETHCK
to ETHCK_K.
Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Signed-off-by: Christophe Roullier <christophe.roullier@st.com>
---
drivers/clk/clk_stm32mp1.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c
index aebc6f0..d70e039 100644
--- a/drivers/clk/clk_stm32mp1.c
+++ b/drivers/clk/clk_stm32mp1.c
@@ -553,7 +553,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
STM32MP1_CLK_SET_CLR(RCC_MP_AHB5ENSETR, 0, GPIOZ, _UNKNOWN_SEL),
- STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 7, ETHCK, _ETH_SEL),
+ STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 7, ETHCK_K, _ETH_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 8, ETHTX, _UNKNOWN_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 9, ETHRX, _UNKNOWN_SEL),
STM32MP1_CLK_SET_CLR_F(RCC_MP_AHB6ENSETR, 10, ETHMAC, _ACLK),
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 1/6] stm32mp1: clk: use the correct identifier for ethck
2019-03-05 10:09 ` [U-Boot] [PATCH 1/6] stm32mp1: clk: use the correct identifier for ethck Christophe Roullier
@ 2019-04-19 15:05 ` Patrick DELAUNAY
0 siblings, 0 replies; 13+ messages in thread
From: Patrick DELAUNAY @ 2019-04-19 15:05 UTC (permalink / raw)
To: u-boot
Hi Christophe,
>
> From: Patrick Delaunay <patrick.delaunay@st.com>
>
> ETHCK_K is the identifier the kernel clock for ETH in kernel binding, selected by
> ETHKSELR / gated by ETHCKEN = BIT(7).
> U-Boot driver need to use the same identifier, so change ETHCK to ETHCK_K.
>
> Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
> Signed-off-by: Christophe Roullier <christophe.roullier@st.com>
> ---
>
> drivers/clk/clk_stm32mp1.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index
> aebc6f0..d70e039 100644
> --- a/drivers/clk/clk_stm32mp1.c
> +++ b/drivers/clk/clk_stm32mp1.c
> @@ -553,7 +553,7 @@ static const struct stm32mp1_clk_gate
> stm32mp1_clk_gate[] = {
>
> STM32MP1_CLK_SET_CLR(RCC_MP_AHB5ENSETR, 0, GPIOZ,
> _UNKNOWN_SEL),
>
> - STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 7, ETHCK,
> _ETH_SEL),
> + STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 7, ETHCK_K,
> _ETH_SEL),
> STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 8, ETHTX,
> _UNKNOWN_SEL),
> STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 9, ETHRX,
> _UNKNOWN_SEL),
> STM32MP1_CLK_SET_CLR_F(RCC_MP_AHB6ENSETR, 10, ETHMAC,
> _ACLK),
> --
> 2.7.4
For stm32mp1 boards EV1 and DK2
Test done with master (SHA1 = 75ce8c938d39bd22460be66e6bf318bd2410c17b)
Tested-by: Patrick Delaunay <patrick.delaunay@st.com>
Regards
Patrick
^ permalink raw reply [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 2/6] board: stm32mp1: Add board_interface_eth_init
2019-03-05 10:09 [U-Boot] [PATCH 0/6] - Add Ethernet support for stm32mpu Christophe Roullier
2019-03-05 10:09 ` [U-Boot] [PATCH 1/6] stm32mp1: clk: use the correct identifier for ethck Christophe Roullier
@ 2019-03-05 10:09 ` Christophe Roullier
2019-04-19 15:06 ` Patrick DELAUNAY
2019-03-05 10:09 ` [U-Boot] [PATCH 3/6] net: dwc_eth_qos: add Ethernet stm32mp1 support Christophe Roullier
` (3 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Christophe Roullier @ 2019-03-05 10:09 UTC (permalink / raw)
To: u-boot
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 54feca0..7c37018 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;
+}
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 2/6] board: stm32mp1: Add board_interface_eth_init
2019-03-05 10:09 ` [U-Boot] [PATCH 2/6] board: stm32mp1: Add board_interface_eth_init Christophe Roullier
@ 2019-04-19 15:06 ` Patrick DELAUNAY
0 siblings, 0 replies; 13+ messages in thread
From: Patrick DELAUNAY @ 2019-04-19 15:06 UTC (permalink / raw)
To: u-boot
Hi Christophe,
>
> 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 54feca0..7c37018 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;
> +}
> --
> 2.7.4
For stm32mp1 boards EV1 and DK2
Test done with master (SHA1 = 75ce8c938d39bd22460be66e6bf318bd2410c17b)
Tested-by: Patrick Delaunay <patrick.delaunay@st.com>
Acked-by: Patrick Delaunay <patrick.delaunay@st.com>
Regards
Patrick
^ permalink raw reply [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 3/6] net: dwc_eth_qos: add Ethernet stm32mp1 support
2019-03-05 10:09 [U-Boot] [PATCH 0/6] - Add Ethernet support for stm32mpu Christophe Roullier
2019-03-05 10:09 ` [U-Boot] [PATCH 1/6] stm32mp1: clk: use the correct identifier for ethck Christophe Roullier
2019-03-05 10:09 ` [U-Boot] [PATCH 2/6] board: stm32mp1: Add board_interface_eth_init Christophe Roullier
@ 2019-03-05 10:09 ` Christophe Roullier
2019-03-05 10:09 ` [U-Boot] [PATCH 4/6] ARM: dts: stm32: Add Ethernet support on stm32mp1 Christophe Roullier
` (2 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Christophe Roullier @ 2019-03-05 10:09 UTC (permalink / raw)
To: u-boot
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 9f1c5af..a6546d5 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.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 4/6] ARM: dts: stm32: Add Ethernet support on stm32mp1
2019-03-05 10:09 [U-Boot] [PATCH 0/6] - Add Ethernet support for stm32mpu Christophe Roullier
` (2 preceding siblings ...)
2019-03-05 10:09 ` [U-Boot] [PATCH 3/6] net: dwc_eth_qos: add Ethernet stm32mp1 support Christophe Roullier
@ 2019-03-05 10:09 ` Christophe Roullier
2019-04-19 15:08 ` Patrick DELAUNAY
2019-03-05 10:09 ` [U-Boot] [PATCH 5/6] stm32mp1: Add Ethernet support for stm32mp1 board Christophe Roullier
2019-03-05 10:09 ` [U-Boot] [PATCH 6/6] configs: stm32mp15: Enable Ethernet feature Christophe Roullier
5 siblings, 1 reply; 13+ messages in thread
From: Christophe Roullier @ 2019-03-05 10:09 UTC (permalink / raw)
To: 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 85da592..66723b0 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 902a42b..bdbf7fb 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 at 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 37cadfa..1271abf 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 at 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 at 5800c000 {
compatible = "generic-ohci";
reg = <0x5800c000 0x1000>;
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 4/6] ARM: dts: stm32: Add Ethernet support on stm32mp1
2019-03-05 10:09 ` [U-Boot] [PATCH 4/6] ARM: dts: stm32: Add Ethernet support on stm32mp1 Christophe Roullier
@ 2019-04-19 15:08 ` Patrick DELAUNAY
0 siblings, 0 replies; 13+ messages in thread
From: Patrick DELAUNAY @ 2019-04-19 15:08 UTC (permalink / raw)
To: u-boot
Hi Christophe,
>
> 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 85da592..66723b0 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 902a42b..bdbf7fb 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 at 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
> 37cadfa..1271abf 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 at 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 at 5800c000 {
> compatible = "generic-ohci";
> reg = <0x5800c000 0x1000>;
> --
> 2.7.4
For stm32mp1 boards EV1 and DK2
Test done with master (SHA1 = 75ce8c938d39bd22460be66e6bf318bd2410c17b)
Tested-by: Patrick Delaunay <patrick.delaunay@st.com>
Acked-by: Patrick Delaunay <patrick.delaunay@st.com>
Regards
Patrick
^ permalink raw reply [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 5/6] stm32mp1: Add Ethernet support for stm32mp1 board
2019-03-05 10:09 [U-Boot] [PATCH 0/6] - Add Ethernet support for stm32mpu Christophe Roullier
` (3 preceding siblings ...)
2019-03-05 10:09 ` [U-Boot] [PATCH 4/6] ARM: dts: stm32: Add Ethernet support on stm32mp1 Christophe Roullier
@ 2019-03-05 10:09 ` Christophe Roullier
2019-04-19 15:16 ` Patrick DELAUNAY
2019-03-05 10:09 ` [U-Boot] [PATCH 6/6] configs: stm32mp15: Enable Ethernet feature Christophe Roullier
5 siblings, 1 reply; 13+ messages in thread
From: Christophe Roullier @ 2019-03-05 10:09 UTC (permalink / raw)
To: u-boot
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 701298c..8469529 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>
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 5/6] stm32mp1: Add Ethernet support for stm32mp1 board
2019-03-05 10:09 ` [U-Boot] [PATCH 5/6] stm32mp1: Add Ethernet support for stm32mp1 board Christophe Roullier
@ 2019-04-19 15:16 ` Patrick DELAUNAY
0 siblings, 0 replies; 13+ messages in thread
From: Patrick DELAUNAY @ 2019-04-19 15:16 UTC (permalink / raw)
To: u-boot
Hi Christophe,
> 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
> 701298c..8469529 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>
>
> --
> 2.7.4
For stm32mp1 boards EV1 and DK2
Test done with master (SHA1 = 75ce8c938d39bd22460be66e6bf318bd2410c17b)
Tested-by: Patrick Delaunay <patrick.delaunay@st.com>
Acked-by: Patrick Delaunay <patrick.delaunay@st.com>
One minor remark: you can add "boot_net_usb_start=true" in CONFIG_EXTRA_ENV_SETTINGS to avoid unnecessary usb start when ethernet is started.
I will push a patch when the serie will be accepted.
Regards
Patrick
^ permalink raw reply [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 6/6] configs: stm32mp15: Enable Ethernet feature
2019-03-05 10:09 [U-Boot] [PATCH 0/6] - Add Ethernet support for stm32mpu Christophe Roullier
` (4 preceding siblings ...)
2019-03-05 10:09 ` [U-Boot] [PATCH 5/6] stm32mp1: Add Ethernet support for stm32mp1 board Christophe Roullier
@ 2019-03-05 10:09 ` Christophe Roullier
2019-04-19 15:17 ` Patrick DELAUNAY
5 siblings, 1 reply; 13+ messages in thread
From: Christophe Roullier @ 2019-03-05 10:09 UTC (permalink / raw)
To: u-boot
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 d20b2ab..38a2a0a 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
--
2.7.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 6/6] configs: stm32mp15: Enable Ethernet feature
2019-03-05 10:09 ` [U-Boot] [PATCH 6/6] configs: stm32mp15: Enable Ethernet feature Christophe Roullier
@ 2019-04-19 15:17 ` Patrick DELAUNAY
0 siblings, 0 replies; 13+ messages in thread
From: Patrick DELAUNAY @ 2019-04-19 15:17 UTC (permalink / raw)
To: u-boot
Hi Christophe,
>
> 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 d20b2ab..38a2a0a 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
> --
> 2.7.4
For stm32mp1 boards EV1 and DK2
Test done with master (SHA1 = 75ce8c938d39bd22460be66e6bf318bd2410c17b)
Tested-by: Patrick Delaunay <patrick.delaunay@st.com>
Acked-by: Patrick Delaunay <patrick.delaunay@st.com>
Regards
Patrick
^ permalink raw reply [flat|nested] 13+ messages in thread
* [U-Boot] [PATCH 3/6] net: dwc_eth_qos: add Ethernet stm32mp1 support
@ 2019-04-19 15:12 Patrick DELAUNAY
0 siblings, 0 replies; 13+ messages in thread
From: Patrick DELAUNAY @ 2019-04-19 15:12 UTC (permalink / raw)
To: u-boot
Hi Christophe,
>
> 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
> 9f1c5af..a6546d5 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.7.4
For stm32mp1 boards EV1 and DK2
Test done with master (SHA1 = 75ce8c938d39bd22460be66e6bf318bd2410c17b)
Tested-by: Patrick Delaunay <patrick.delaunay@st.com>
Reviewed-by: Patrick Delaunay <patrick.delaunay@st.com>
Regards
Patrick
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2019-04-19 15:17 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-05 10:09 [U-Boot] [PATCH 0/6] - Add Ethernet support for stm32mpu Christophe Roullier
2019-03-05 10:09 ` [U-Boot] [PATCH 1/6] stm32mp1: clk: use the correct identifier for ethck Christophe Roullier
2019-04-19 15:05 ` Patrick DELAUNAY
2019-03-05 10:09 ` [U-Boot] [PATCH 2/6] board: stm32mp1: Add board_interface_eth_init Christophe Roullier
2019-04-19 15:06 ` Patrick DELAUNAY
2019-03-05 10:09 ` [U-Boot] [PATCH 3/6] net: dwc_eth_qos: add Ethernet stm32mp1 support Christophe Roullier
2019-03-05 10:09 ` [U-Boot] [PATCH 4/6] ARM: dts: stm32: Add Ethernet support on stm32mp1 Christophe Roullier
2019-04-19 15:08 ` Patrick DELAUNAY
2019-03-05 10:09 ` [U-Boot] [PATCH 5/6] stm32mp1: Add Ethernet support for stm32mp1 board Christophe Roullier
2019-04-19 15:16 ` Patrick DELAUNAY
2019-03-05 10:09 ` [U-Boot] [PATCH 6/6] configs: stm32mp15: Enable Ethernet feature Christophe Roullier
2019-04-19 15:17 ` Patrick DELAUNAY
2019-04-19 15:12 [U-Boot] [PATCH 3/6] net: dwc_eth_qos: add Ethernet stm32mp1 support Patrick DELAUNAY
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.