All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588
@ 2023-08-07  0:08 Jonas Karlman
  2023-08-07  0:08 ` [PATCH 1/7] net: dwc_eth_qos: Drop unused rx_pkt from eqos_priv Jonas Karlman
                   ` (7 more replies)
  0 siblings, 8 replies; 22+ messages in thread
From: Jonas Karlman @ 2023-08-07  0:08 UTC (permalink / raw)
  To: Kever Yang, Simon Glass, Philipp Tomsich
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot,
	Jonas Karlman

This series adds a glue driver, dwc_eth_qos_rockchip, to support GMAC
on RK356x and RK3588.

rk_gmac_ops used in this series has been ported from mainline linux.

Patch 1-3 does some minor cleanup in dwc_eth_qos driver.
Patch 4 add glue driver with RK3568 support.
Patch 5 add support for RK3588 to glue driver.
Patch 6-7 update defconfigs to enable use of the new driver.

Dependencies:
- "pinctrl: rockchip: Fix drive and input schmitt on RK3568" [1]
- "clk: rockchip: rk3568: Add dummy support for GMAC speed clocks" [2]
- "net: phy: motorcomm: Add support for YT8511 PHY" [3]
- "rockchip: Port IO-domain driver for RK3568 from linux" [4]

dhcp and ping commands has been tested on the followin devices:
- RK3566: Quartz64 Model A and SOQuartz on Blade
- RK3568: ROCK 3 Model A
- RK3588: ROCK 5 Model A

This series can also be found at [5].

[1] https://patchwork.ozlabs.org/patch/1816600/
[2] https://patchwork.ozlabs.org/patch/1816856/
[3] https://patchwork.ozlabs.org/patch/1817295/
[4] https://patchwork.ozlabs.org/cover/1817469/
[5] https://github.com/Kwiboo/u-boot-rockchip/commits/rk35xx-gmac-v1

Jonas Karlman (7):
  net: dwc_eth_qos: Drop unused rx_pkt from eqos_priv
  net: dwc_eth_qos: Return error code when start fails
  net: dwc_eth_qos: Stop spam of RX packet not available message
  net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568
  net: dwc_eth_qos_rockchip: Add support for RK3588
  configs: rockchip: Enable ethernet driver on RK356x boards
  configs: rockchip: Enable ethernet driver on RK3588 boards

 configs/evb-rk3568_defconfig              |   5 +-
 configs/evb-rk3588_defconfig              |   5 +-
 configs/nanopi-r5s-rk3568_defconfig       |   3 +
 configs/neu6a-io-rk3588_defconfig         |   2 -
 configs/neu6b-io-rk3588_defconfig         |   2 -
 configs/odroid-m1-rk3568_defconfig        |   3 +
 configs/quartz64-a-rk3566_defconfig       |   3 +
 configs/quartz64-b-rk3566_defconfig       |   3 +
 configs/radxa-cm3-io-rk3566_defconfig     |   6 +-
 configs/rock-3a-rk3568_defconfig          |   5 +-
 configs/rock5a-rk3588s_defconfig          |   6 +-
 configs/soquartz-blade-rk3566_defconfig   |   3 +
 configs/soquartz-cm4-rk3566_defconfig     |   3 +
 configs/soquartz-model-a-rk3566_defconfig |   3 +
 drivers/net/Kconfig                       |   8 +
 drivers/net/Makefile                      |   1 +
 drivers/net/dwc_eth_qos.c                 |  33 +-
 drivers/net/dwc_eth_qos.h                 |   3 +-
 drivers/net/dwc_eth_qos_rockchip.c        | 522 ++++++++++++++++++++++
 19 files changed, 585 insertions(+), 34 deletions(-)
 create mode 100644 drivers/net/dwc_eth_qos_rockchip.c

-- 
2.41.0


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/7] net: dwc_eth_qos: Drop unused rx_pkt from eqos_priv
  2023-08-07  0:08 [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Jonas Karlman
@ 2023-08-07  0:08 ` Jonas Karlman
  2023-09-27  3:00   ` Kever Yang
  2023-08-07  0:08 ` [PATCH 2/7] net: dwc_eth_qos: Return error code when start fails Jonas Karlman
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Jonas Karlman @ 2023-08-07  0:08 UTC (permalink / raw)
  To: Kever Yang, Simon Glass, Philipp Tomsich, Joe Hershberger, Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot,
	Jonas Karlman

rx_pkt is allocated and not used for anything, remove it.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
 drivers/net/dwc_eth_qos.c | 11 -----------
 drivers/net/dwc_eth_qos.h |  1 -
 2 files changed, 12 deletions(-)

diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 1e92bd9ca9c0..555eaee3bbc3 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1314,22 +1314,12 @@ static int eqos_probe_resources_core(struct udevice *dev)
 	}
 	debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
 
-	eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE);
-	if (!eqos->rx_pkt) {
-		debug("%s: malloc(rx_pkt) failed\n", __func__);
-		ret = -ENOMEM;
-		goto err_free_rx_dma_buf;
-	}
-	debug("%s: rx_pkt=%p\n", __func__, eqos->rx_pkt);
-
 	eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf,
 			EQOS_MAX_PACKET_SIZE * EQOS_DESCRIPTORS_RX);
 
 	debug("%s: OK\n", __func__);
 	return 0;
 
-err_free_rx_dma_buf:
-	free(eqos->rx_dma_buf);
 err_free_tx_dma_buf:
 	free(eqos->tx_dma_buf);
 err_free_descs:
@@ -1348,7 +1338,6 @@ static int eqos_remove_resources_core(struct udevice *dev)
 
 	debug("%s(dev=%p):\n", __func__, dev);
 
-	free(eqos->rx_pkt);
 	free(eqos->rx_dma_buf);
 	free(eqos->tx_dma_buf);
 	eqos_free_descs(eqos->rx_descs);
diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
index a6b719af809f..06a082da72ef 100644
--- a/drivers/net/dwc_eth_qos.h
+++ b/drivers/net/dwc_eth_qos.h
@@ -273,7 +273,6 @@ struct eqos_priv {
 	unsigned int desc_per_cacheline;
 	void *tx_dma_buf;
 	void *rx_dma_buf;
-	void *rx_pkt;
 	bool started;
 	bool reg_access_ok;
 	bool clk_ck_enabled;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 2/7] net: dwc_eth_qos: Return error code when start fails
  2023-08-07  0:08 [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Jonas Karlman
  2023-08-07  0:08 ` [PATCH 1/7] net: dwc_eth_qos: Drop unused rx_pkt from eqos_priv Jonas Karlman
@ 2023-08-07  0:08 ` Jonas Karlman
  2023-09-27  3:00   ` Kever Yang
  2023-08-07  0:08 ` [PATCH 3/7] net: dwc_eth_qos: Stop spam of RX packet not available message Jonas Karlman
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Jonas Karlman @ 2023-08-07  0:08 UTC (permalink / raw)
  To: Kever Yang, Simon Glass, Philipp Tomsich, Joe Hershberger, Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot,
	Jonas Karlman

Return error code when phy_connect fails or no link can be established.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
 drivers/net/dwc_eth_qos.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 555eaee3bbc3..7565e716823a 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -811,6 +811,7 @@ static int eqos_start(struct udevice *dev)
 
 		if (!eqos->phy) {
 			pr_err("phy_connect() failed");
+			ret = -ENODEV;
 			goto err_stop_resets;
 		}
 
@@ -838,6 +839,7 @@ static int eqos_start(struct udevice *dev)
 
 	if (!eqos->phy->link) {
 		pr_err("No link");
+		ret = -EAGAIN;
 		goto err_shutdown_phy;
 	}
 
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 3/7] net: dwc_eth_qos: Stop spam of RX packet not available message
  2023-08-07  0:08 [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Jonas Karlman
  2023-08-07  0:08 ` [PATCH 1/7] net: dwc_eth_qos: Drop unused rx_pkt from eqos_priv Jonas Karlman
  2023-08-07  0:08 ` [PATCH 2/7] net: dwc_eth_qos: Return error code when start fails Jonas Karlman
@ 2023-08-07  0:08 ` Jonas Karlman
  2023-09-27  3:00   ` Kever Yang
  2023-08-07  0:08 ` [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568 Jonas Karlman
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Jonas Karlman @ 2023-08-07  0:08 UTC (permalink / raw)
  To: Kever Yang, Simon Glass, Philipp Tomsich, Joe Hershberger, Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot,
	Jonas Karlman

Remove spam of RX packet not available debug messages when waiting to
receive a packet.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
 drivers/net/dwc_eth_qos.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 7565e716823a..24fb3fac1f12 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1193,14 +1193,12 @@ static int eqos_recv(struct udevice *dev, int flags, uchar **packetp)
 	struct eqos_desc *rx_desc;
 	int length;
 
-	debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags);
-
 	rx_desc = eqos_get_desc(eqos, eqos->rx_desc_idx, true);
 	eqos->config->ops->eqos_inval_desc(rx_desc);
-	if (rx_desc->des3 & EQOS_DESC3_OWN) {
-		debug("%s: RX packet not available\n", __func__);
+	if (rx_desc->des3 & EQOS_DESC3_OWN)
 		return -EAGAIN;
-	}
+
+	debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags);
 
 	*packetp = eqos->rx_dma_buf +
 		(eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE);
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568
  2023-08-07  0:08 [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Jonas Karlman
                   ` (2 preceding siblings ...)
  2023-08-07  0:08 ` [PATCH 3/7] net: dwc_eth_qos: Stop spam of RX packet not available message Jonas Karlman
@ 2023-08-07  0:08 ` Jonas Karlman
  2023-08-07 14:41   ` Eugen Hristev
                     ` (2 more replies)
  2023-08-07  0:08 ` [PATCH 5/7] net: dwc_eth_qos_rockchip: Add support for RK3588 Jonas Karlman
                   ` (3 subsequent siblings)
  7 siblings, 3 replies; 22+ messages in thread
From: Jonas Karlman @ 2023-08-07  0:08 UTC (permalink / raw)
  To: Kever Yang, Simon Glass, Philipp Tomsich, Joe Hershberger, Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot,
	Jonas Karlman, David Wu, Ezequiel Garcia

Add a new glue driver for Rockchip SoCs, i.e RK3568, with a GMAC based
on Synopsys DWC Ethernet QoS IP.

rk_gmac_ops was ported from linux commit:
3bb3d6b1c195 ("net: stmmac: Add RK3566/RK3568 SoC support")

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
Cc: David Wu <david.wu@rock-chips.com>
Cc: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/net/Kconfig                |   8 +
 drivers/net/Makefile               |   1 +
 drivers/net/dwc_eth_qos.c          |   8 +-
 drivers/net/dwc_eth_qos.h          |   2 +
 drivers/net/dwc_eth_qos_rockchip.c | 348 +++++++++++++++++++++++++++++
 5 files changed, 365 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/dwc_eth_qos_rockchip.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 0ed39a61e4de..29304fd77759 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -225,6 +225,14 @@ config DWC_ETH_QOS_IMX
 	  The Synopsys Designware Ethernet QOS IP block with the specific
 	  configuration used in IMX soc.
 
+config DWC_ETH_QOS_ROCKCHIP
+	bool "Synopsys DWC Ethernet QOS device support for Rockchip SoCs"
+	depends on DWC_ETH_QOS
+	select DM_ETH_PHY
+	help
+	  The Synopsys Designware Ethernet QOS IP block with specific
+	  configuration used in Rockchip SoCs.
+
 config DWC_ETH_QOS_STM32
 	bool "Synopsys DWC Ethernet QOS device support for STM32"
 	depends on DWC_ETH_QOS
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index d4af253b6f28..1d444f5b4a69 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
 obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
 obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
 obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o
+obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o
 obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
 obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o
 obj-$(CONFIG_E1000) += e1000.o
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 24fb3fac1f12..9fb98a2c3c74 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1707,7 +1707,12 @@ static const struct udevice_id eqos_ids[] = {
 		.data = (ulong)&eqos_imx_config
 	},
 #endif
-
+#if IS_ENABLED(CONFIG_DWC_ETH_QOS_ROCKCHIP)
+	{
+		.compatible = "rockchip,rk3568-gmac",
+		.data = (ulong)&eqos_rockchip_config
+	},
+#endif
 #if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
 	{
 		.compatible = "qcom,qcs404-ethqos",
@@ -1720,7 +1725,6 @@ static const struct udevice_id eqos_ids[] = {
 		.data = (ulong)&eqos_jh7110_config
 	},
 #endif
-
 	{ }
 };
 
diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
index 06a082da72ef..e3222e1e17e5 100644
--- a/drivers/net/dwc_eth_qos.h
+++ b/drivers/net/dwc_eth_qos.h
@@ -82,6 +82,7 @@ struct eqos_mac_regs {
 #define EQOS_MAC_MDIO_ADDRESS_PA_SHIFT			21
 #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT			16
 #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT			8
+#define EQOS_MAC_MDIO_ADDRESS_CR_100_150		1
 #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)
@@ -287,5 +288,6 @@ void eqos_flush_buffer_generic(void *buf, size_t size);
 int eqos_null_ops(struct udevice *dev);
 
 extern struct eqos_config eqos_imx_config;
+extern struct eqos_config eqos_rockchip_config;
 extern struct eqos_config eqos_qcom_config;
 extern struct eqos_config eqos_jh7110_config;
diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c
new file mode 100644
index 000000000000..c8abe351fc3e
--- /dev/null
+++ b/drivers/net/dwc_eth_qos_rockchip.c
@@ -0,0 +1,348 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <net.h>
+#include <phy.h>
+#include <regmap.h>
+#include <reset.h>
+#include <syscon.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+
+#include "dwc_eth_qos.h"
+
+struct rk_gmac_ops {
+	const char *compatible;
+	int (*set_to_rgmii)(struct udevice *dev,
+			    int tx_delay, int rx_delay);
+	int (*set_to_rmii)(struct udevice *dev);
+	int (*set_gmac_speed)(struct udevice *dev);
+	u32 regs[3];
+};
+
+struct rockchip_platform_data {
+	struct reset_ctl_bulk resets;
+	const struct rk_gmac_ops *ops;
+	int id;
+	struct regmap *grf;
+};
+
+#define HIWORD_UPDATE(val, mask, shift) \
+		((val) << (shift) | (mask) << ((shift) + 16))
+
+#define GRF_BIT(nr)	(BIT(nr) | BIT((nr) + 16))
+#define GRF_CLR_BIT(nr)	(BIT((nr) + 16))
+
+#define RK3568_GRF_GMAC0_CON0		0x0380
+#define RK3568_GRF_GMAC0_CON1		0x0384
+#define RK3568_GRF_GMAC1_CON0		0x0388
+#define RK3568_GRF_GMAC1_CON1		0x038c
+
+/* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */
+#define RK3568_GMAC_PHY_INTF_SEL_RGMII	\
+		(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
+#define RK3568_GMAC_PHY_INTF_SEL_RMII	\
+		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
+#define RK3568_GMAC_FLOW_CTRL			GRF_BIT(3)
+#define RK3568_GMAC_FLOW_CTRL_CLR		GRF_CLR_BIT(3)
+#define RK3568_GMAC_RXCLK_DLY_ENABLE		GRF_BIT(1)
+#define RK3568_GMAC_RXCLK_DLY_DISABLE		GRF_CLR_BIT(1)
+#define RK3568_GMAC_TXCLK_DLY_ENABLE		GRF_BIT(0)
+#define RK3568_GMAC_TXCLK_DLY_DISABLE		GRF_CLR_BIT(0)
+
+/* RK3568_GRF_GMAC0_CON0 && RK3568_GRF_GMAC1_CON0 */
+#define RK3568_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
+#define RK3568_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
+
+static int rk3568_set_to_rgmii(struct udevice *dev,
+			       int tx_delay, int rx_delay)
+{
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+	u32 con0, con1;
+
+	con0 = (data->id == 1) ? RK3568_GRF_GMAC1_CON0 :
+				 RK3568_GRF_GMAC0_CON0;
+	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
+				 RK3568_GRF_GMAC0_CON1;
+
+	regmap_write(data->grf, con0,
+		     RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) |
+		     RK3568_GMAC_CLK_TX_DL_CFG(tx_delay));
+
+	regmap_write(data->grf, con1,
+		     RK3568_GMAC_PHY_INTF_SEL_RGMII |
+		     RK3568_GMAC_RXCLK_DLY_ENABLE |
+		     RK3568_GMAC_TXCLK_DLY_ENABLE);
+
+	return 0;
+}
+
+static int rk3568_set_to_rmii(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+	u32 con1;
+
+	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
+				 RK3568_GRF_GMAC0_CON1;
+	regmap_write(data->grf, con1, RK3568_GMAC_PHY_INTF_SEL_RMII);
+
+	return 0;
+}
+
+static int rk3568_set_gmac_speed(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+	ulong rate;
+	int ret;
+
+	switch (eqos->phy->speed) {
+	case SPEED_10:
+		rate = 2500000;
+		break;
+	case SPEED_100:
+		rate = 25000000;
+		break;
+	case SPEED_1000:
+		rate = 125000000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = clk_set_rate(&eqos->clk_tx, rate);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct rk_gmac_ops rk_gmac_ops[] = {
+	{
+		.compatible = "rockchip,rk3568-gmac",
+		.set_to_rgmii = rk3568_set_to_rgmii,
+		.set_to_rmii = rk3568_set_to_rmii,
+		.set_gmac_speed = rk3568_set_gmac_speed,
+		.regs = {
+			0xfe2a0000, /* gmac0 */
+			0xfe010000, /* gmac1 */
+			0x0, /* sentinel */
+		},
+	},
+	{ }
+};
+
+static const struct rk_gmac_ops *get_rk_gmac_ops(struct udevice *dev)
+{
+	const struct rk_gmac_ops *ops = rk_gmac_ops;
+
+	while (ops->compatible) {
+		if (device_is_compatible(dev, ops->compatible))
+			return ops;
+		ops++;
+	}
+
+	return NULL;
+}
+
+static int eqos_probe_resources_rk(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data;
+	int reset_flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
+	int ret;
+
+	data = calloc(1, sizeof(struct rockchip_platform_data));
+	if (!data)
+		return -ENOMEM;
+
+	data->ops = get_rk_gmac_ops(dev);
+	if (!data->ops) {
+		ret = -EINVAL;
+		goto err_free;
+	}
+
+	for (int i = 0; data->ops->regs[i]; i++) {
+		if (data->ops->regs[i] == (u32)eqos->regs) {
+			data->id = i;
+			break;
+		}
+	}
+
+	pdata->priv_pdata = data;
+	pdata->phy_interface = eqos->config->interface(dev);
+	pdata->max_speed = eqos->max_speed;
+
+	if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
+		pr_err("Invalid PHY interface\n");
+		ret = -EINVAL;
+		goto err_free;
+	}
+
+	data->grf = syscon_regmap_lookup_by_phandle(dev, "rockchip,grf");
+	if (IS_ERR(data->grf)) {
+		dev_err(dev, "Missing rockchip,grf property\n");
+		ret = -EINVAL;
+		goto err_free;
+	}
+
+	ret = reset_get_bulk(dev, &data->resets);
+	if (ret < 0)
+		goto err_free;
+
+	reset_assert_bulk(&data->resets);
+
+	ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
+	if (ret) {
+		dev_dbg(dev, "clk_get_by_name(stmmaceth) failed: %d", ret);
+		goto err_release_resets;
+	}
+
+	ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
+	if (ret) {
+		dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
+		goto err_free_clk_master_bus;
+	}
+
+	if (dev_read_bool(dev, "snps,reset-active-low"))
+		reset_flags |= GPIOD_ACTIVE_LOW;
+
+	dev_read_u32_array(dev, "snps,reset-delays-us", eqos->reset_delays, 3);
+
+	gpio_request_by_name(dev, "snps,reset-gpio", 0,
+			     &eqos->phy_reset_gpio, reset_flags);
+
+	return 0;
+
+err_free_clk_master_bus:
+	clk_free(&eqos->clk_master_bus);
+err_release_resets:
+	reset_release_bulk(&data->resets);
+err_free:
+	free(data);
+
+	return ret;
+}
+
+static int eqos_remove_resources_rk(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+
+	if (dm_gpio_is_valid(&eqos->phy_reset_gpio))
+		dm_gpio_free(dev, &eqos->phy_reset_gpio);
+
+	clk_free(&eqos->clk_tx);
+	clk_free(&eqos->clk_master_bus);
+	reset_release_bulk(&data->resets);
+	free(data);
+
+	return 0;
+}
+
+static int eqos_stop_resets_rk(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+
+	return reset_assert_bulk(&data->resets);
+}
+
+static int eqos_start_resets_rk(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+
+	return reset_deassert_bulk(&data->resets);
+}
+
+static int eqos_stop_clks_rk(struct udevice *dev)
+{
+	return 0;
+}
+
+static int eqos_start_clks_rk(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+	int tx_delay, rx_delay, ret;
+
+	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
+		udelay(eqos->reset_delays[1]);
+
+		ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
+		if (ret < 0)
+			return ret;
+
+		udelay(eqos->reset_delays[2]);
+	}
+
+	tx_delay = dev_read_u32_default(dev, "tx_delay", 0x30);
+	rx_delay = dev_read_u32_default(dev, "rx_delay", 0x10);
+
+	switch (pdata->phy_interface) {
+	case PHY_INTERFACE_MODE_RGMII:
+		return data->ops->set_to_rgmii(dev, tx_delay, rx_delay);
+	case PHY_INTERFACE_MODE_RGMII_ID:
+		return data->ops->set_to_rgmii(dev, 0, 0);
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+		return data->ops->set_to_rgmii(dev, tx_delay, 0);
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		return data->ops->set_to_rgmii(dev, 0, rx_delay);
+	case PHY_INTERFACE_MODE_RMII:
+		return data->ops->set_to_rmii(dev);
+	}
+
+	return -EINVAL;
+}
+
+static int eqos_set_tx_clk_speed_rk(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+
+	return data->ops->set_gmac_speed(dev);
+}
+
+static ulong eqos_get_tick_clk_rate_rk(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+
+	return clk_get_rate(&eqos->clk_master_bus);
+}
+
+static struct eqos_ops eqos_rockchip_ops = {
+	.eqos_inval_desc = eqos_inval_desc_generic,
+	.eqos_flush_desc = eqos_flush_desc_generic,
+	.eqos_inval_buffer = eqos_inval_buffer_generic,
+	.eqos_flush_buffer = eqos_flush_buffer_generic,
+	.eqos_probe_resources = eqos_probe_resources_rk,
+	.eqos_remove_resources = eqos_remove_resources_rk,
+	.eqos_stop_resets = eqos_stop_resets_rk,
+	.eqos_start_resets = eqos_start_resets_rk,
+	.eqos_stop_clks = eqos_stop_clks_rk,
+	.eqos_start_clks = eqos_start_clks_rk,
+	.eqos_calibrate_pads = eqos_null_ops,
+	.eqos_disable_calibration = eqos_null_ops,
+	.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_rk,
+	.eqos_get_enetaddr = eqos_null_ops,
+	.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_rk,
+};
+
+struct eqos_config eqos_rockchip_config = {
+	.reg_access_always_ok = false,
+	.mdio_wait = 10,
+	.swr_wait = 50,
+	.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
+	.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_100_150,
+	.axi_bus_width = EQOS_AXI_WIDTH_64,
+	.interface = dev_read_phy_mode,
+	.ops = &eqos_rockchip_ops,
+};
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 5/7] net: dwc_eth_qos_rockchip: Add support for RK3588
  2023-08-07  0:08 [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Jonas Karlman
                   ` (3 preceding siblings ...)
  2023-08-07  0:08 ` [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568 Jonas Karlman
@ 2023-08-07  0:08 ` Jonas Karlman
  2023-09-27  3:01   ` Kever Yang
  2023-10-06 14:43   ` Tom Fitzhenry
  2023-08-07  0:08 ` [PATCH 6/7] configs: rockchip: Enable ethernet driver on RK356x boards Jonas Karlman
                   ` (2 subsequent siblings)
  7 siblings, 2 replies; 22+ messages in thread
From: Jonas Karlman @ 2023-08-07  0:08 UTC (permalink / raw)
  To: Kever Yang, Simon Glass, Philipp Tomsich, Joe Hershberger, Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot,
	Jonas Karlman, David Wu, Sebastian Reichel, Benjamin Gaignard

Add rk_gmac_ops and other special handling that is needed for GMAC to
work on RK3588.

rk_gmac_ops was ported from linux commits:
2f2b60a0ec28 ("net: ethernet: stmmac: dwmac-rk: Add gmac support for rk3588")
88619e77b33d ("net: stmmac: rk3588: Allow multiple gmac controller")

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
Cc: David Wu <david.wu@rock-chips.com>
Cc: Sebastian Reichel <sebastian.reichel@collabora.com>
Cc: Benjamin Gaignard <benjamin.gaignard@collabora.com>
---
 drivers/net/dwc_eth_qos.c          |   4 +
 drivers/net/dwc_eth_qos_rockchip.c | 182 ++++++++++++++++++++++++++++-
 2 files changed, 182 insertions(+), 4 deletions(-)

diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 9fb98a2c3c74..dc04416865dd 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1712,6 +1712,10 @@ static const struct udevice_id eqos_ids[] = {
 		.compatible = "rockchip,rk3568-gmac",
 		.data = (ulong)&eqos_rockchip_config
 	},
+	{
+		.compatible = "rockchip,rk3588-gmac",
+		.data = (ulong)&eqos_rockchip_config
+	},
 #endif
 #if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
 	{
diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c
index c8abe351fc3e..34020496bde6 100644
--- a/drivers/net/dwc_eth_qos_rockchip.c
+++ b/drivers/net/dwc_eth_qos_rockchip.c
@@ -20,6 +20,7 @@ struct rk_gmac_ops {
 			    int tx_delay, int rx_delay);
 	int (*set_to_rmii)(struct udevice *dev);
 	int (*set_gmac_speed)(struct udevice *dev);
+	void (*set_clock_selection)(struct udevice *dev, bool enable);
 	u32 regs[3];
 };
 
@@ -27,7 +28,9 @@ struct rockchip_platform_data {
 	struct reset_ctl_bulk resets;
 	const struct rk_gmac_ops *ops;
 	int id;
+	bool clock_input;
 	struct regmap *grf;
+	struct regmap *php_grf;
 };
 
 #define HIWORD_UPDATE(val, mask, shift) \
@@ -121,6 +124,137 @@ static int rk3568_set_gmac_speed(struct udevice *dev)
 	return 0;
 }
 
+/* sys_grf */
+#define RK3588_GRF_GMAC_CON7			0x031c
+#define RK3588_GRF_GMAC_CON8			0x0320
+#define RK3588_GRF_GMAC_CON9			0x0324
+
+#define RK3588_GMAC_RXCLK_DLY_ENABLE(id)	GRF_BIT(2 * (id) + 3)
+#define RK3588_GMAC_RXCLK_DLY_DISABLE(id)	GRF_CLR_BIT(2 * (id) + 3)
+#define RK3588_GMAC_TXCLK_DLY_ENABLE(id)	GRF_BIT(2 * (id) + 2)
+#define RK3588_GMAC_TXCLK_DLY_DISABLE(id)	GRF_CLR_BIT(2 * (id) + 2)
+
+#define RK3588_GMAC_CLK_RX_DL_CFG(val)		HIWORD_UPDATE(val, 0xFF, 8)
+#define RK3588_GMAC_CLK_TX_DL_CFG(val)		HIWORD_UPDATE(val, 0xFF, 0)
+
+/* php_grf */
+#define RK3588_GRF_GMAC_CON0			0x0008
+#define RK3588_GRF_CLK_CON1			0x0070
+
+#define RK3588_GMAC_PHY_INTF_SEL_RGMII(id)	\
+	(GRF_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_CLR_BIT(5 + (id) * 6))
+#define RK3588_GMAC_PHY_INTF_SEL_RMII(id)	\
+	(GRF_CLR_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_BIT(5 + (id) * 6))
+
+#define RK3588_GMAC_CLK_RMII_MODE(id)		GRF_BIT(5 * (id))
+#define RK3588_GMAC_CLK_RGMII_MODE(id)		GRF_CLR_BIT(5 * (id))
+
+#define RK3588_GMAC_CLK_SELET_CRU(id)		GRF_BIT(5 * (id) + 4)
+#define RK3588_GMAC_CLK_SELET_IO(id)		GRF_CLR_BIT(5 * (id) + 4)
+
+#define RK3588_GMAC_CLK_RMII_DIV2(id)		GRF_BIT(5 * (id) + 2)
+#define RK3588_GMAC_CLK_RMII_DIV20(id)		GRF_CLR_BIT(5 * (id) + 2)
+
+#define RK3588_GMAC_CLK_RGMII_DIV1(id)		\
+			(GRF_CLR_BIT(5 * (id) + 2) | GRF_CLR_BIT(5 * (id) + 3))
+#define RK3588_GMAC_CLK_RGMII_DIV5(id)		\
+			(GRF_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3))
+#define RK3588_GMAC_CLK_RGMII_DIV50(id)		\
+			(GRF_CLR_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3))
+
+#define RK3588_GMAC_CLK_RMII_GATE(id)		GRF_BIT(5 * (id) + 1)
+#define RK3588_GMAC_CLK_RMII_NOGATE(id)		GRF_CLR_BIT(5 * (id) + 1)
+
+static int rk3588_set_to_rgmii(struct udevice *dev,
+			       int tx_delay, int rx_delay)
+{
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+	u32 offset_con, id = data->id;
+
+	offset_con = data->id == 1 ? RK3588_GRF_GMAC_CON9 :
+				     RK3588_GRF_GMAC_CON8;
+
+	regmap_write(data->php_grf, RK3588_GRF_GMAC_CON0,
+		     RK3588_GMAC_PHY_INTF_SEL_RGMII(id));
+
+	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1,
+		     RK3588_GMAC_CLK_RGMII_MODE(id));
+
+	regmap_write(data->grf, RK3588_GRF_GMAC_CON7,
+		     RK3588_GMAC_RXCLK_DLY_ENABLE(id) |
+		     RK3588_GMAC_TXCLK_DLY_ENABLE(id));
+
+	regmap_write(data->grf, offset_con,
+		     RK3588_GMAC_CLK_RX_DL_CFG(rx_delay) |
+		     RK3588_GMAC_CLK_TX_DL_CFG(tx_delay));
+
+	return 0;
+}
+
+static int rk3588_set_to_rmii(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+
+	regmap_write(data->php_grf, RK3588_GRF_GMAC_CON0,
+		     RK3588_GMAC_PHY_INTF_SEL_RMII(data->id));
+
+	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1,
+		     RK3588_GMAC_CLK_RMII_MODE(data->id));
+
+	return 0;
+}
+
+static int rk3588_set_gmac_speed(struct udevice *dev)
+{
+	struct eqos_priv *eqos = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+	u32 val = 0, id = data->id;
+
+	switch (eqos->phy->speed) {
+	case SPEED_10:
+		if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII)
+			val = RK3588_GMAC_CLK_RMII_DIV20(id);
+		else
+			val = RK3588_GMAC_CLK_RGMII_DIV50(id);
+		break;
+	case SPEED_100:
+		if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII)
+			val = RK3588_GMAC_CLK_RMII_DIV2(id);
+		else
+			val = RK3588_GMAC_CLK_RGMII_DIV5(id);
+		break;
+	case SPEED_1000:
+		if (pdata->phy_interface != PHY_INTERFACE_MODE_RMII)
+			val = RK3588_GMAC_CLK_RGMII_DIV1(id);
+		else
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1, val);
+
+	return 0;
+}
+
+static void rk3588_set_clock_selection(struct udevice *dev, bool enable)
+{
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+
+	u32 val = data->clock_input ? RK3588_GMAC_CLK_SELET_IO(data->id) :
+				      RK3588_GMAC_CLK_SELET_CRU(data->id);
+
+	val |= enable ? RK3588_GMAC_CLK_RMII_NOGATE(data->id) :
+			RK3588_GMAC_CLK_RMII_GATE(data->id);
+
+	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1, val);
+}
+
 static const struct rk_gmac_ops rk_gmac_ops[] = {
 	{
 		.compatible = "rockchip,rk3568-gmac",
@@ -133,6 +267,18 @@ static const struct rk_gmac_ops rk_gmac_ops[] = {
 			0x0, /* sentinel */
 		},
 	},
+	{
+		.compatible = "rockchip,rk3588-gmac",
+		.set_to_rgmii = rk3588_set_to_rgmii,
+		.set_to_rmii = rk3588_set_to_rmii,
+		.set_gmac_speed = rk3588_set_gmac_speed,
+		.set_clock_selection = rk3588_set_clock_selection,
+		.regs = {
+			0xfe1b0000, /* gmac0 */
+			0xfe1c0000, /* gmac1 */
+			0x0, /* sentinel */
+		},
+	},
 	{ }
 };
 
@@ -154,6 +300,7 @@ static int eqos_probe_resources_rk(struct udevice *dev)
 	struct eqos_priv *eqos = dev_get_priv(dev);
 	struct eth_pdata *pdata = dev_get_plat(dev);
 	struct rockchip_platform_data *data;
+	const char *clock_in_out;
 	int reset_flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
 	int ret;
 
@@ -191,6 +338,16 @@ static int eqos_probe_resources_rk(struct udevice *dev)
 		goto err_free;
 	}
 
+	if (device_is_compatible(dev, "rockchip,rk3588-gmac")) {
+		data->php_grf =
+			syscon_regmap_lookup_by_phandle(dev, "rockchip,php-grf");
+		if (IS_ERR(data->php_grf)) {
+			dev_err(dev, "Missing rockchip,php-grf property\n");
+			ret = -EINVAL;
+			goto err_free;
+		}
+	}
+
 	ret = reset_get_bulk(dev, &data->resets);
 	if (ret < 0)
 		goto err_free;
@@ -203,12 +360,20 @@ static int eqos_probe_resources_rk(struct udevice *dev)
 		goto err_release_resets;
 	}
 
-	ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
-	if (ret) {
-		dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
-		goto err_free_clk_master_bus;
+	if (device_is_compatible(dev, "rockchip,rk3568-gmac")) {
+		ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
+		if (ret) {
+			dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
+			goto err_free_clk_master_bus;
+		}
 	}
 
+	clock_in_out = dev_read_string(dev, "clock_in_out");
+	if (clock_in_out && !strcmp(clock_in_out, "input"))
+		data->clock_input = true;
+	else
+		data->clock_input = false;
+
 	if (dev_read_bool(dev, "snps,reset-active-low"))
 		reset_flags |= GPIOD_ACTIVE_LOW;
 
@@ -264,6 +429,12 @@ static int eqos_start_resets_rk(struct udevice *dev)
 
 static int eqos_stop_clks_rk(struct udevice *dev)
 {
+	struct eth_pdata *pdata = dev_get_plat(dev);
+	struct rockchip_platform_data *data = pdata->priv_pdata;
+
+	if (data->ops->set_clock_selection)
+		data->ops->set_clock_selection(dev, false);
+
 	return 0;
 }
 
@@ -284,6 +455,9 @@ static int eqos_start_clks_rk(struct udevice *dev)
 		udelay(eqos->reset_delays[2]);
 	}
 
+	if (data->ops->set_clock_selection)
+		data->ops->set_clock_selection(dev, true);
+
 	tx_delay = dev_read_u32_default(dev, "tx_delay", 0x30);
 	rx_delay = dev_read_u32_default(dev, "rx_delay", 0x10);
 
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 6/7] configs: rockchip: Enable ethernet driver on RK356x boards
  2023-08-07  0:08 [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Jonas Karlman
                   ` (4 preceding siblings ...)
  2023-08-07  0:08 ` [PATCH 5/7] net: dwc_eth_qos_rockchip: Add support for RK3588 Jonas Karlman
@ 2023-08-07  0:08 ` Jonas Karlman
  2023-09-27  3:01   ` Kever Yang
  2023-08-07  0:08 ` [PATCH 7/7] configs: rockchip: Enable ethernet driver on RK3588 boards Jonas Karlman
  2023-08-12  3:04 ` [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Kever Yang
  7 siblings, 1 reply; 22+ messages in thread
From: Jonas Karlman @ 2023-08-07  0:08 UTC (permalink / raw)
  To: Kever Yang, Simon Glass, Philipp Tomsich, Joseph Chen,
	Tianling Shen, Jonas Karlman, Nicolas Frattaroli, Jagan Teki,
	Akash Gajjar
  Cc: Eugen Hristev, Frank Wunderlich, u-boot

Enable DWC_ETH_QOS_ROCKCHIP and related PHY driver on RK356x boards that
have an enabled gmac node.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
 configs/evb-rk3568_defconfig              | 5 +++--
 configs/nanopi-r5s-rk3568_defconfig       | 3 +++
 configs/odroid-m1-rk3568_defconfig        | 3 +++
 configs/quartz64-a-rk3566_defconfig       | 3 +++
 configs/quartz64-b-rk3566_defconfig       | 3 +++
 configs/radxa-cm3-io-rk3566_defconfig     | 6 ++++--
 configs/rock-3a-rk3568_defconfig          | 5 +++--
 configs/soquartz-blade-rk3566_defconfig   | 3 +++
 configs/soquartz-cm4-rk3566_defconfig     | 3 +++
 configs/soquartz-model-a-rk3566_defconfig | 3 +++
 10 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/configs/evb-rk3568_defconfig b/configs/evb-rk3568_defconfig
index 5f3fab7304c2..43431ecdfed6 100644
--- a/configs/evb-rk3568_defconfig
+++ b/configs/evb-rk3568_defconfig
@@ -58,8 +58,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
-CONFIG_ETH_DESIGNWARE=y
-CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_RK8XX=y
 CONFIG_REGULATOR_RK8XX=y
diff --git a/configs/nanopi-r5s-rk3568_defconfig b/configs/nanopi-r5s-rk3568_defconfig
index c278ce083d9a..2736d382a352 100644
--- a/configs/nanopi-r5s-rk3568_defconfig
+++ b/configs/nanopi-r5s-rk3568_defconfig
@@ -65,6 +65,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_RTL8169=y
 CONFIG_NVME_PCI=y
 CONFIG_PCIE_DW_ROCKCHIP=y
diff --git a/configs/odroid-m1-rk3568_defconfig b/configs/odroid-m1-rk3568_defconfig
index 3dda5c1f9170..96b4e9ecdaff 100644
--- a/configs/odroid-m1-rk3568_defconfig
+++ b/configs/odroid-m1-rk3568_defconfig
@@ -82,6 +82,9 @@ CONFIG_SF_DEFAULT_BUS=4
 CONFIG_SPI_FLASH_SFDP_SUPPORT=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_NVME_PCI=y
 CONFIG_PCIE_DW_ROCKCHIP=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
diff --git a/configs/quartz64-a-rk3566_defconfig b/configs/quartz64-a-rk3566_defconfig
index 6853cd6c44b4..bf4d4cd2b8ed 100644
--- a/configs/quartz64-a-rk3566_defconfig
+++ b/configs/quartz64-a-rk3566_defconfig
@@ -81,6 +81,9 @@ CONFIG_SPI_FLASH_SFDP_SUPPORT=y
 CONFIG_SPI_FLASH_GIGADEVICE=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_PHY_MOTORCOMM=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_NVME_PCI=y
 CONFIG_PCIE_DW_ROCKCHIP=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
diff --git a/configs/quartz64-b-rk3566_defconfig b/configs/quartz64-b-rk3566_defconfig
index aa29fff14643..358687ab5d7f 100644
--- a/configs/quartz64-b-rk3566_defconfig
+++ b/configs/quartz64-b-rk3566_defconfig
@@ -79,6 +79,9 @@ CONFIG_SPI_FLASH_SFDP_SUPPORT=y
 CONFIG_SPI_FLASH_GIGADEVICE=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_NVME_PCI=y
 CONFIG_PCIE_DW_ROCKCHIP=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
diff --git a/configs/radxa-cm3-io-rk3566_defconfig b/configs/radxa-cm3-io-rk3566_defconfig
index f89777184ceb..4b606dcb8e94 100644
--- a/configs/radxa-cm3-io-rk3566_defconfig
+++ b/configs/radxa-cm3-io-rk3566_defconfig
@@ -47,6 +47,7 @@ CONFIG_CMD_REGULATOR=y
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_OF_LIVE=y
 CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_SPL_REGMAP=y
 CONFIG_SPL_SYSCON=y
 CONFIG_SPL_CLK=y
@@ -59,8 +60,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
-CONFIG_ETH_DESIGNWARE=y
-CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
 CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
 CONFIG_SPL_PINCTRL=y
diff --git a/configs/rock-3a-rk3568_defconfig b/configs/rock-3a-rk3568_defconfig
index 409aa95acf06..28d157dbd7a7 100644
--- a/configs/rock-3a-rk3568_defconfig
+++ b/configs/rock-3a-rk3568_defconfig
@@ -77,8 +77,9 @@ CONFIG_SF_DEFAULT_BUS=4
 CONFIG_SPI_FLASH_SFDP_SUPPORT=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_XTX=y
-CONFIG_ETH_DESIGNWARE=y
-CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_NVME_PCI=y
 CONFIG_PCIE_DW_ROCKCHIP=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
diff --git a/configs/soquartz-blade-rk3566_defconfig b/configs/soquartz-blade-rk3566_defconfig
index 181c284e73e9..1d993a5b71b0 100644
--- a/configs/soquartz-blade-rk3566_defconfig
+++ b/configs/soquartz-blade-rk3566_defconfig
@@ -67,6 +67,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_PHY_MOTORCOMM=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_NVME_PCI=y
 CONFIG_PCIE_DW_ROCKCHIP=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
diff --git a/configs/soquartz-cm4-rk3566_defconfig b/configs/soquartz-cm4-rk3566_defconfig
index 7e290351477e..f01aa7269a1c 100644
--- a/configs/soquartz-cm4-rk3566_defconfig
+++ b/configs/soquartz-cm4-rk3566_defconfig
@@ -67,6 +67,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_PHY_MOTORCOMM=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_NVME_PCI=y
 CONFIG_PCIE_DW_ROCKCHIP=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
diff --git a/configs/soquartz-model-a-rk3566_defconfig b/configs/soquartz-model-a-rk3566_defconfig
index a0884a797d58..2f3145745d58 100644
--- a/configs/soquartz-model-a-rk3566_defconfig
+++ b/configs/soquartz-model-a-rk3566_defconfig
@@ -68,6 +68,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_PHY_MOTORCOMM=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_NVME_PCI=y
 CONFIG_PCIE_DW_ROCKCHIP=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 7/7] configs: rockchip: Enable ethernet driver on RK3588 boards
  2023-08-07  0:08 [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Jonas Karlman
                   ` (5 preceding siblings ...)
  2023-08-07  0:08 ` [PATCH 6/7] configs: rockchip: Enable ethernet driver on RK356x boards Jonas Karlman
@ 2023-08-07  0:08 ` Jonas Karlman
  2023-09-27  3:01   ` Kever Yang
  2023-08-12  3:04 ` [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Kever Yang
  7 siblings, 1 reply; 22+ messages in thread
From: Jonas Karlman @ 2023-08-07  0:08 UTC (permalink / raw)
  To: Kever Yang, Simon Glass, Philipp Tomsich, Jagan Teki, Eugen Hristev
  Cc: Frank Wunderlich, Nicolas Frattaroli, u-boot, Jonas Karlman

Enable DWC_ETH_QOS_ROCKCHIP and related PHY driver on RK3588 boards that
have an enabled gmac node and drop ETH_DESIGNWARE and GMAC_ROCKCHIP for
remaining RK3588 boards.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
 configs/evb-rk3588_defconfig      | 5 +++--
 configs/neu6a-io-rk3588_defconfig | 2 --
 configs/neu6b-io-rk3588_defconfig | 2 --
 configs/rock5a-rk3588s_defconfig  | 6 +++---
 4 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/configs/evb-rk3588_defconfig b/configs/evb-rk3588_defconfig
index f49c2ca686a8..0b7b4f2f627a 100644
--- a/configs/evb-rk3588_defconfig
+++ b/configs/evb-rk3588_defconfig
@@ -58,8 +58,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
-CONFIG_ETH_DESIGNWARE=y
-CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_REGULATOR_PWM=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_SPL_RAM=y
diff --git a/configs/neu6a-io-rk3588_defconfig b/configs/neu6a-io-rk3588_defconfig
index 09729a0ea429..d5301c630b2a 100644
--- a/configs/neu6a-io-rk3588_defconfig
+++ b/configs/neu6a-io-rk3588_defconfig
@@ -53,8 +53,6 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
-CONFIG_ETH_DESIGNWARE=y
-CONFIG_GMAC_ROCKCHIP=y
 CONFIG_REGULATOR_PWM=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_SPL_RAM=y
diff --git a/configs/neu6b-io-rk3588_defconfig b/configs/neu6b-io-rk3588_defconfig
index c7bc3b1965f0..b13c9b5db1b0 100644
--- a/configs/neu6b-io-rk3588_defconfig
+++ b/configs/neu6b-io-rk3588_defconfig
@@ -53,8 +53,6 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
-CONFIG_ETH_DESIGNWARE=y
-CONFIG_GMAC_ROCKCHIP=y
 CONFIG_REGULATOR_PWM=y
 CONFIG_PWM_ROCKCHIP=y
 CONFIG_SPL_RAM=y
diff --git a/configs/rock5a-rk3588s_defconfig b/configs/rock5a-rk3588s_defconfig
index 6cbd9817c528..bccdb1e3ecd6 100644
--- a/configs/rock5a-rk3588s_defconfig
+++ b/configs/rock5a-rk3588s_defconfig
@@ -11,7 +11,6 @@ CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000
 CONFIG_DEFAULT_DEVICE_TREE="rk3588s-rock-5a"
 CONFIG_ROCKCHIP_RK3588=y
 CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y
-CONFIG_SPL_MMC=y
 CONFIG_SPL_SERIAL=y
 CONFIG_SPL_STACK_R_ADDR=0x1000000
 CONFIG_TARGET_ROCK5A_RK3588=y
@@ -59,8 +58,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
-CONFIG_ETH_DESIGNWARE=y
-CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PHY_REALTEK=y
+CONFIG_DWC_ETH_QOS=y
+CONFIG_DWC_ETH_QOS_ROCKCHIP=y
 CONFIG_SPL_PINCTRL=y
 CONFIG_REGULATOR_PWM=y
 CONFIG_PWM_ROCKCHIP=y
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568
  2023-08-07  0:08 ` [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568 Jonas Karlman
@ 2023-08-07 14:41   ` Eugen Hristev
  2023-08-07 23:38     ` Jonas Karlman
  2023-08-15 13:12   ` David Wu
  2023-09-27  3:01   ` Kever Yang
  2 siblings, 1 reply; 22+ messages in thread
From: Eugen Hristev @ 2023-08-07 14:41 UTC (permalink / raw)
  To: Jonas Karlman, Kever Yang, Simon Glass, Philipp Tomsich,
	Joe Hershberger, Ramon Fried
  Cc: Frank Wunderlich, Nicolas Frattaroli, u-boot, David Wu, Ezequiel Garcia

Hi Jonas,

Thank you for your work,

On 8/7/23 03:08, Jonas Karlman wrote:
> Add a new glue driver for Rockchip SoCs, i.e RK3568, with a GMAC based
> on Synopsys DWC Ethernet QoS IP.
> 
> rk_gmac_ops was ported from linux commit:
> 3bb3d6b1c195 ("net: stmmac: Add RK3566/RK3568 SoC support")
> 
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
> ---
> Cc: David Wu <david.wu@rock-chips.com>
> Cc: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>   drivers/net/Kconfig                |   8 +
>   drivers/net/Makefile               |   1 +
>   drivers/net/dwc_eth_qos.c          |   8 +-
>   drivers/net/dwc_eth_qos.h          |   2 +
>   drivers/net/dwc_eth_qos_rockchip.c | 348 +++++++++++++++++++++++++++++
>   5 files changed, 365 insertions(+), 2 deletions(-)
>   create mode 100644 drivers/net/dwc_eth_qos_rockchip.c
> 
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 0ed39a61e4de..29304fd77759 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -225,6 +225,14 @@ config DWC_ETH_QOS_IMX
>   	  The Synopsys Designware Ethernet QOS IP block with the specific
>   	  configuration used in IMX soc.
>   
> +config DWC_ETH_QOS_ROCKCHIP
> +	bool "Synopsys DWC Ethernet QOS device support for Rockchip SoCs"
> +	depends on DWC_ETH_QOS
> +	select DM_ETH_PHY
> +	help
> +	  The Synopsys Designware Ethernet QOS IP block with specific
> +	  configuration used in Rockchip SoCs.
> +
>   config DWC_ETH_QOS_STM32
>   	bool "Synopsys DWC Ethernet QOS device support for STM32"
>   	depends on DWC_ETH_QOS
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index d4af253b6f28..1d444f5b4a69 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
>   obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
>   obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
>   obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o
> +obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o
>   obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
>   obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o
>   obj-$(CONFIG_E1000) += e1000.o
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index 24fb3fac1f12..9fb98a2c3c74 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -1707,7 +1707,12 @@ static const struct udevice_id eqos_ids[] = {
>   		.data = (ulong)&eqos_imx_config
>   	},
>   #endif
> -
> +#if IS_ENABLED(CONFIG_DWC_ETH_QOS_ROCKCHIP)
> +	{
> +		.compatible = "rockchip,rk3568-gmac",
> +		.data = (ulong)&eqos_rockchip_config
> +	},
> +#endif
>   #if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
>   	{
>   		.compatible = "qcom,qcs404-ethqos",
> @@ -1720,7 +1725,6 @@ static const struct udevice_id eqos_ids[] = {
>   		.data = (ulong)&eqos_jh7110_config
>   	},
>   #endif
> -
Unintended change ?
>   	{ }
>   };
>   
> diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
> index 06a082da72ef..e3222e1e17e5 100644
> --- a/drivers/net/dwc_eth_qos.h
> +++ b/drivers/net/dwc_eth_qos.h
> @@ -82,6 +82,7 @@ struct eqos_mac_regs {
>   #define EQOS_MAC_MDIO_ADDRESS_PA_SHIFT			21
>   #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT			16
>   #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT			8
> +#define EQOS_MAC_MDIO_ADDRESS_CR_100_150		1
>   #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)
> @@ -287,5 +288,6 @@ void eqos_flush_buffer_generic(void *buf, size_t size);
>   int eqos_null_ops(struct udevice *dev);
>   
>   extern struct eqos_config eqos_imx_config;
> +extern struct eqos_config eqos_rockchip_config;
>   extern struct eqos_config eqos_qcom_config;
>   extern struct eqos_config eqos_jh7110_config;
> diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c
> new file mode 100644
> index 000000000000..c8abe351fc3e
> --- /dev/null
> +++ b/drivers/net/dwc_eth_qos_rockchip.c
> @@ -0,0 +1,348 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dm/device_compat.h>
> +#include <net.h>
> +#include <phy.h>
> +#include <regmap.h>
> +#include <reset.h>
> +#include <syscon.h>
> +#include <asm/gpio.h>
> +#include <linux/delay.h>
> +
> +#include "dwc_eth_qos.h"
> +
> +struct rk_gmac_ops {
> +	const char *compatible;
> +	int (*set_to_rgmii)(struct udevice *dev,
> +			    int tx_delay, int rx_delay);
> +	int (*set_to_rmii)(struct udevice *dev);
> +	int (*set_gmac_speed)(struct udevice *dev);
> +	u32 regs[3];

Can't these be somehow const and point to a dedicated array for a 
specific SoC ?

Also I believe the naming 'regs' is a bit unfortunate, as it does not 
hold the usual regmap, rather an array of addresses hardcoded used to 
figure out which of the GMAC instances we are referring to.

> +};
> +
> +struct rockchip_platform_data {
> +	struct reset_ctl_bulk resets;
> +	const struct rk_gmac_ops *ops;
> +	int id;
> +	struct regmap *grf;
> +};
> +
> +#define HIWORD_UPDATE(val, mask, shift) \
> +		((val) << (shift) | (mask) << ((shift) + 16))
> +
> +#define GRF_BIT(nr)	(BIT(nr) | BIT((nr) + 16))
> +#define GRF_CLR_BIT(nr)	(BIT((nr) + 16))

can't you use rk_clrsetreg and friends? it should already do this

> +
> +#define RK3568_GRF_GMAC0_CON0		0x0380
> +#define RK3568_GRF_GMAC0_CON1		0x0384
> +#define RK3568_GRF_GMAC1_CON0		0x0388
> +#define RK3568_GRF_GMAC1_CON1		0x038c

Can you add these as a struct in

arch/arm/include/asm/arch-rockchip/grf_rk3568.h

(e.g. I got this from downstream Uboot for 3588 :
https://gitlab.collabora.com/hardware-enablement/rockchip-3588/u-boot/-/blob/rk3568-88-gmac/arch/arm/include/asm/arch-rockchip/grf_rk3588.h
)



> +
> +/* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */
> +#define RK3568_GMAC_PHY_INTF_SEL_RGMII	\
> +		(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
> +#define RK3568_GMAC_PHY_INTF_SEL_RMII	\
> +		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
> +#define RK3568_GMAC_FLOW_CTRL			GRF_BIT(3)
> +#define RK3568_GMAC_FLOW_CTRL_CLR		GRF_CLR_BIT(3)
> +#define RK3568_GMAC_RXCLK_DLY_ENABLE		GRF_BIT(1)
> +#define RK3568_GMAC_RXCLK_DLY_DISABLE		GRF_CLR_BIT(1)
> +#define RK3568_GMAC_TXCLK_DLY_ENABLE		GRF_BIT(0)
> +#define RK3568_GMAC_TXCLK_DLY_DISABLE		GRF_CLR_BIT(0)
> +
> +/* RK3568_GRF_GMAC0_CON0 && RK3568_GRF_GMAC1_CON0 */
> +#define RK3568_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
> +#define RK3568_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
> +
> +static int rk3568_set_to_rgmii(struct udevice *dev,
> +			       int tx_delay, int rx_delay)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +	u32 con0, con1;
> +
> +	con0 = (data->id == 1) ? RK3568_GRF_GMAC1_CON0 :
> +				 RK3568_GRF_GMAC0_CON0;
> +	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
> +				 RK3568_GRF_GMAC0_CON1;
> +
> +	regmap_write(data->grf, con0,
> +		     RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) |
> +		     RK3568_GMAC_CLK_TX_DL_CFG(tx_delay));
> +
> +	regmap_write(data->grf, con1,
> +		     RK3568_GMAC_PHY_INTF_SEL_RGMII |
> +		     RK3568_GMAC_RXCLK_DLY_ENABLE |
> +		     RK3568_GMAC_TXCLK_DLY_ENABLE);

Shouldn't you set RK3568_GMAC_TXCLK_DLY_DISABLE here in case the delays 
are 0 ?

> +
> +	return 0;
> +}
> +
> +static int rk3568_set_to_rmii(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +	u32 con1;
> +
> +	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
> +				 RK3568_GRF_GMAC0_CON1;
> +	regmap_write(data->grf, con1, RK3568_GMAC_PHY_INTF_SEL_RMII);
> +
> +	return 0;
> +}
> +
> +static int rk3568_set_gmac_speed(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	ulong rate;
> +	int ret;
> +
> +	switch (eqos->phy->speed) {
> +	case SPEED_10:
> +		rate = 2500000;
> +		break;
> +	case SPEED_100:
> +		rate = 25000000;
> +		break;
> +	case SPEED_1000:
> +		rate = 125000000;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	ret = clk_set_rate(&eqos->clk_tx, rate);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static const struct rk_gmac_ops rk_gmac_ops[] = {
> +	{
> +		.compatible = "rockchip,rk3568-gmac",
> +		.set_to_rgmii = rk3568_set_to_rgmii,
> +		.set_to_rmii = rk3568_set_to_rmii,
> +		.set_gmac_speed = rk3568_set_gmac_speed,
> +		.regs = {
> +			0xfe2a0000, /* gmac0 */
> +			0xfe010000, /* gmac1 */
> +			0x0, /* sentinel */
> +		},
Can these be referenced to a const struct ?
> +	},
> +	{ }
> +};
> +
> +static const struct rk_gmac_ops *get_rk_gmac_ops(struct udevice *dev)
> +{
> +	const struct rk_gmac_ops *ops = rk_gmac_ops;
> +
> +	while (ops->compatible) {
> +		if (device_is_compatible(dev, ops->compatible))
> +			return ops;
> +		ops++;
> +	}
> +
> +	return NULL;
> +}
> +
> +static int eqos_probe_resources_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data;
> +	int reset_flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
> +	int ret;
> +
> +	data = calloc(1, sizeof(struct rockchip_platform_data));
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->ops = get_rk_gmac_ops(dev);
> +	if (!data->ops) {
> +		ret = -EINVAL;
> +		goto err_free;
> +	}
> +
> +	for (int i = 0; data->ops->regs[i]; i++) {
> +		if (data->ops->regs[i] == (u32)eqos->regs) {
> +			data->id = i;
> +			break;
> +		}
> +	}
> +
> +	pdata->priv_pdata = data;
> +	pdata->phy_interface = eqos->config->interface(dev);
> +	pdata->max_speed = eqos->max_speed;
> +
> +	if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
> +		pr_err("Invalid PHY interface\n");
> +		ret = -EINVAL;
> +		goto err_free;
> +	}
> +
> +	data->grf = syscon_regmap_lookup_by_phandle(dev, "rockchip,grf");
> +	if (IS_ERR(data->grf)) {
> +		dev_err(dev, "Missing rockchip,grf property\n");
> +		ret = -EINVAL;
> +		goto err_free;
> +	}

 From my read of the binding, rockchip,grf is not mandatory. Is it 
possible to just ignore the grf if the property is missing ?

> +
> +	ret = reset_get_bulk(dev, &data->resets);
> +	if (ret < 0)
> +		goto err_free;
> +
> +	reset_assert_bulk(&data->resets);
> +

The same goes for the clocks below, the binding specifies min clocks is 
5, and maximum clocks is 8, but not which are the 5 minimum required clocks.
So , can we not stop if some of the clocks are missing ?

> +	ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
> +	if (ret) {
> +		dev_dbg(dev, "clk_get_by_name(stmmaceth) failed: %d", ret);
> +		goto err_release_resets;
> +	}
> +
> +	ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
> +	if (ret) {
> +		dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
> +		goto err_free_clk_master_bus;
> +	}
> +
> +	if (dev_read_bool(dev, "snps,reset-active-low"))
> +		reset_flags |= GPIOD_ACTIVE_LOW;
> +
> +	dev_read_u32_array(dev, "snps,reset-delays-us", eqos->reset_delays, 3);
> +
> +	gpio_request_by_name(dev, "snps,reset-gpio", 0,
> +			     &eqos->phy_reset_gpio, reset_flags);

reset-gpio appears to be deprecated according to the binding,
also, you do not check the error code and assume the property exists ?


Greetings,
Eugen
> +
> +	return 0;
> +
> +err_free_clk_master_bus:
> +	clk_free(&eqos->clk_master_bus);
> +err_release_resets:
> +	reset_release_bulk(&data->resets);
> +err_free:
> +	free(data);
> +
> +	return ret;
> +}
> +
> +static int eqos_remove_resources_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio))
> +		dm_gpio_free(dev, &eqos->phy_reset_gpio);
> +
> +	clk_free(&eqos->clk_tx);
> +	clk_free(&eqos->clk_master_bus);
> +	reset_release_bulk(&data->resets);
> +	free(data);
> +
> +	return 0;
> +}
> +
> +static int eqos_stop_resets_rk(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	return reset_assert_bulk(&data->resets);
> +}
> +
> +static int eqos_start_resets_rk(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	return reset_deassert_bulk(&data->resets);
> +}
> +
> +static int eqos_stop_clks_rk(struct udevice *dev)
> +{
> +	return 0;
> +}
> +
> +static int eqos_start_clks_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +	int tx_delay, rx_delay, ret;
> +
> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
> +		udelay(eqos->reset_delays[1]);
> +
> +		ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
> +		if (ret < 0)
> +			return ret;
> +
> +		udelay(eqos->reset_delays[2]);
> +	}
> +
> +	tx_delay = dev_read_u32_default(dev, "tx_delay", 0x30);
> +	rx_delay = dev_read_u32_default(dev, "rx_delay", 0x10);
> +
> +	switch (pdata->phy_interface) {
> +	case PHY_INTERFACE_MODE_RGMII:
> +		return data->ops->set_to_rgmii(dev, tx_delay, rx_delay);
> +	case PHY_INTERFACE_MODE_RGMII_ID:
> +		return data->ops->set_to_rgmii(dev, 0, 0);
> +	case PHY_INTERFACE_MODE_RGMII_RXID:
> +		return data->ops->set_to_rgmii(dev, tx_delay, 0);
> +	case PHY_INTERFACE_MODE_RGMII_TXID:
> +		return data->ops->set_to_rgmii(dev, 0, rx_delay);
> +	case PHY_INTERFACE_MODE_RMII:
> +		return data->ops->set_to_rmii(dev);
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int eqos_set_tx_clk_speed_rk(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	return data->ops->set_gmac_speed(dev);
> +}
> +
> +static ulong eqos_get_tick_clk_rate_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +
> +	return clk_get_rate(&eqos->clk_master_bus);
> +}
> +
> +static struct eqos_ops eqos_rockchip_ops = {
> +	.eqos_inval_desc = eqos_inval_desc_generic,
> +	.eqos_flush_desc = eqos_flush_desc_generic,
> +	.eqos_inval_buffer = eqos_inval_buffer_generic,
> +	.eqos_flush_buffer = eqos_flush_buffer_generic,
> +	.eqos_probe_resources = eqos_probe_resources_rk,
> +	.eqos_remove_resources = eqos_remove_resources_rk,
> +	.eqos_stop_resets = eqos_stop_resets_rk,
> +	.eqos_start_resets = eqos_start_resets_rk,
> +	.eqos_stop_clks = eqos_stop_clks_rk,
> +	.eqos_start_clks = eqos_start_clks_rk,
> +	.eqos_calibrate_pads = eqos_null_ops,
> +	.eqos_disable_calibration = eqos_null_ops,
> +	.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_rk,
> +	.eqos_get_enetaddr = eqos_null_ops,
> +	.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_rk,
> +};
> +
> +struct eqos_config eqos_rockchip_config = {
> +	.reg_access_always_ok = false,
> +	.mdio_wait = 10,
> +	.swr_wait = 50,
> +	.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
> +	.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_100_150,
> +	.axi_bus_width = EQOS_AXI_WIDTH_64,
> +	.interface = dev_read_phy_mode,
> +	.ops = &eqos_rockchip_ops,
> +};


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568
  2023-08-07 14:41   ` Eugen Hristev
@ 2023-08-07 23:38     ` Jonas Karlman
  0 siblings, 0 replies; 22+ messages in thread
From: Jonas Karlman @ 2023-08-07 23:38 UTC (permalink / raw)
  To: Eugen Hristev, Kever Yang, Simon Glass, Philipp Tomsich,
	Joe Hershberger, Ramon Fried
  Cc: Frank Wunderlich, Nicolas Frattaroli, u-boot, David Wu, Ezequiel Garcia

Hi Eugen,

On 2023-08-07 16:41, Eugen Hristev wrote:
> Hi Jonas,
> 
> Thank you for your work,

Thanks!

> 
> On 8/7/23 03:08, Jonas Karlman wrote:
>> Add a new glue driver for Rockchip SoCs, i.e RK3568, with a GMAC based
>> on Synopsys DWC Ethernet QoS IP.
>>
>> rk_gmac_ops was ported from linux commit:
>> 3bb3d6b1c195 ("net: stmmac: Add RK3566/RK3568 SoC support")
>>
>> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
>> ---
>> Cc: David Wu <david.wu@rock-chips.com>
>> Cc: Ezequiel Garcia <ezequiel@collabora.com>
>> ---
>>   drivers/net/Kconfig                |   8 +
>>   drivers/net/Makefile               |   1 +
>>   drivers/net/dwc_eth_qos.c          |   8 +-
>>   drivers/net/dwc_eth_qos.h          |   2 +
>>   drivers/net/dwc_eth_qos_rockchip.c | 348 +++++++++++++++++++++++++++++
>>   5 files changed, 365 insertions(+), 2 deletions(-)
>>   create mode 100644 drivers/net/dwc_eth_qos_rockchip.c
>>
>> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
>> index 0ed39a61e4de..29304fd77759 100644
>> --- a/drivers/net/Kconfig
>> +++ b/drivers/net/Kconfig
>> @@ -225,6 +225,14 @@ config DWC_ETH_QOS_IMX
>>   	  The Synopsys Designware Ethernet QOS IP block with the specific
>>   	  configuration used in IMX soc.
>>   
>> +config DWC_ETH_QOS_ROCKCHIP
>> +	bool "Synopsys DWC Ethernet QOS device support for Rockchip SoCs"
>> +	depends on DWC_ETH_QOS
>> +	select DM_ETH_PHY
>> +	help
>> +	  The Synopsys Designware Ethernet QOS IP block with specific
>> +	  configuration used in Rockchip SoCs.
>> +
>>   config DWC_ETH_QOS_STM32
>>   	bool "Synopsys DWC Ethernet QOS device support for STM32"
>>   	depends on DWC_ETH_QOS
>> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
>> index d4af253b6f28..1d444f5b4a69 100644
>> --- a/drivers/net/Makefile
>> +++ b/drivers/net/Makefile
>> @@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
>>   obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
>>   obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
>>   obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o
>> +obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o
>>   obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
>>   obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o
>>   obj-$(CONFIG_E1000) += e1000.o
>> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
>> index 24fb3fac1f12..9fb98a2c3c74 100644
>> --- a/drivers/net/dwc_eth_qos.c
>> +++ b/drivers/net/dwc_eth_qos.c
>> @@ -1707,7 +1707,12 @@ static const struct udevice_id eqos_ids[] = {
>>   		.data = (ulong)&eqos_imx_config
>>   	},
>>   #endif
>> -
>> +#if IS_ENABLED(CONFIG_DWC_ETH_QOS_ROCKCHIP)
>> +	{
>> +		.compatible = "rockchip,rk3568-gmac",
>> +		.data = (ulong)&eqos_rockchip_config
>> +	},
>> +#endif
>>   #if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
>>   	{
>>   		.compatible = "qcom,qcs404-ethqos",
>> @@ -1720,7 +1725,6 @@ static const struct udevice_id eqos_ids[] = {
>>   		.data = (ulong)&eqos_jh7110_config
>>   	},
>>   #endif
>> -
> Unintended change ?

A change to have it consistent without blank lines as remaining if/endif
blocks.

>>   	{ }
>>   };
>>   
>> diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
>> index 06a082da72ef..e3222e1e17e5 100644
>> --- a/drivers/net/dwc_eth_qos.h
>> +++ b/drivers/net/dwc_eth_qos.h
>> @@ -82,6 +82,7 @@ struct eqos_mac_regs {
>>   #define EQOS_MAC_MDIO_ADDRESS_PA_SHIFT			21
>>   #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT			16
>>   #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT			8
>> +#define EQOS_MAC_MDIO_ADDRESS_CR_100_150		1
>>   #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)
>> @@ -287,5 +288,6 @@ void eqos_flush_buffer_generic(void *buf, size_t size);
>>   int eqos_null_ops(struct udevice *dev);
>>   
>>   extern struct eqos_config eqos_imx_config;
>> +extern struct eqos_config eqos_rockchip_config;
>>   extern struct eqos_config eqos_qcom_config;
>>   extern struct eqos_config eqos_jh7110_config;
>> diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c
>> new file mode 100644
>> index 000000000000..c8abe351fc3e
>> --- /dev/null
>> +++ b/drivers/net/dwc_eth_qos_rockchip.c
>> @@ -0,0 +1,348 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <dm/device_compat.h>
>> +#include <net.h>
>> +#include <phy.h>
>> +#include <regmap.h>
>> +#include <reset.h>
>> +#include <syscon.h>
>> +#include <asm/gpio.h>
>> +#include <linux/delay.h>
>> +
>> +#include "dwc_eth_qos.h"
>> +
>> +struct rk_gmac_ops {
>> +	const char *compatible;
>> +	int (*set_to_rgmii)(struct udevice *dev,
>> +			    int tx_delay, int rx_delay);
>> +	int (*set_to_rmii)(struct udevice *dev);
>> +	int (*set_gmac_speed)(struct udevice *dev);
>> +	u32 regs[3];
> 
> Can't these be somehow const and point to a dedicated array for a 
> specific SoC ?
> 
> Also I believe the naming 'regs' is a bit unfortunate, as it does not 
> hold the usual regmap, rather an array of addresses hardcoded used to 
> figure out which of the GMAC instances we are referring to.

I agree that it is an unfortunate naming, but would prefer to keep this
in sync with mainline linux as much as possible to ease porting any fix
merged in linux.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c#n29

> 
>> +};
>> +
>> +struct rockchip_platform_data {
>> +	struct reset_ctl_bulk resets;
>> +	const struct rk_gmac_ops *ops;
>> +	int id;
>> +	struct regmap *grf;
>> +};
>> +
>> +#define HIWORD_UPDATE(val, mask, shift) \
>> +		((val) << (shift) | (mask) << ((shift) + 16))
>> +
>> +#define GRF_BIT(nr)	(BIT(nr) | BIT((nr) + 16))
>> +#define GRF_CLR_BIT(nr)	(BIT((nr) + 16))
> 
> can't you use rk_clrsetreg and friends? it should already do this

Same here, would like to keep this in sync with linux driver. I only did
absolute minimal change, wrap nr and add space, to please checkpatch.pl

> 
>> +
>> +#define RK3568_GRF_GMAC0_CON0		0x0380
>> +#define RK3568_GRF_GMAC0_CON1		0x0384
>> +#define RK3568_GRF_GMAC1_CON0		0x0388
>> +#define RK3568_GRF_GMAC1_CON1		0x038c
> 
> Can you add these as a struct in

Same here, would like to keep this in sync with linux driver.

> 
> arch/arm/include/asm/arch-rockchip/grf_rk3568.h
> 
> (e.g. I got this from downstream Uboot for 3588 :
> https://gitlab.collabora.com/hardware-enablement/rockchip-3588/u-boot/-/blob/rk3568-88-gmac/arch/arm/include/asm/arch-rockchip/grf_rk3588.h
> )
> 
> 
> 
>> +
>> +/* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */
>> +#define RK3568_GMAC_PHY_INTF_SEL_RGMII	\
>> +		(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
>> +#define RK3568_GMAC_PHY_INTF_SEL_RMII	\
>> +		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
>> +#define RK3568_GMAC_FLOW_CTRL			GRF_BIT(3)
>> +#define RK3568_GMAC_FLOW_CTRL_CLR		GRF_CLR_BIT(3)
>> +#define RK3568_GMAC_RXCLK_DLY_ENABLE		GRF_BIT(1)
>> +#define RK3568_GMAC_RXCLK_DLY_DISABLE		GRF_CLR_BIT(1)
>> +#define RK3568_GMAC_TXCLK_DLY_ENABLE		GRF_BIT(0)
>> +#define RK3568_GMAC_TXCLK_DLY_DISABLE		GRF_CLR_BIT(0)
>> +
>> +/* RK3568_GRF_GMAC0_CON0 && RK3568_GRF_GMAC1_CON0 */
>> +#define RK3568_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
>> +#define RK3568_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
>> +
>> +static int rk3568_set_to_rgmii(struct udevice *dev,
>> +			       int tx_delay, int rx_delay)
>> +{
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +	u32 con0, con1;
>> +
>> +	con0 = (data->id == 1) ? RK3568_GRF_GMAC1_CON0 :
>> +				 RK3568_GRF_GMAC0_CON0;
>> +	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
>> +				 RK3568_GRF_GMAC0_CON1;
>> +
>> +	regmap_write(data->grf, con0,
>> +		     RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) |
>> +		     RK3568_GMAC_CLK_TX_DL_CFG(tx_delay));
>> +
>> +	regmap_write(data->grf, con1,
>> +		     RK3568_GMAC_PHY_INTF_SEL_RGMII |
>> +		     RK3568_GMAC_RXCLK_DLY_ENABLE |
>> +		     RK3568_GMAC_TXCLK_DLY_ENABLE);
> 
> Shouldn't you set RK3568_GMAC_TXCLK_DLY_DISABLE here in case the delays 
> are 0 ?

I did this in my original work, but opted to just import all rk_gmac_ops
as close to 1:1 from mainline linux as possible in the end. Or we may
end up with network working differently in linux and U-Boot. But if this
is a bug, it should be fixed in both.

> 
>> +
>> +	return 0;
>> +}
>> +
>> +static int rk3568_set_to_rmii(struct udevice *dev)
>> +{
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +	u32 con1;
>> +
>> +	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
>> +				 RK3568_GRF_GMAC0_CON1;
>> +	regmap_write(data->grf, con1, RK3568_GMAC_PHY_INTF_SEL_RMII);
>> +
>> +	return 0;
>> +}
>> +
>> +static int rk3568_set_gmac_speed(struct udevice *dev)
>> +{
>> +	struct eqos_priv *eqos = dev_get_priv(dev);
>> +	ulong rate;
>> +	int ret;
>> +
>> +	switch (eqos->phy->speed) {
>> +	case SPEED_10:
>> +		rate = 2500000;
>> +		break;
>> +	case SPEED_100:
>> +		rate = 25000000;
>> +		break;
>> +	case SPEED_1000:
>> +		rate = 125000000;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = clk_set_rate(&eqos->clk_tx, rate);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct rk_gmac_ops rk_gmac_ops[] = {
>> +	{
>> +		.compatible = "rockchip,rk3568-gmac",
>> +		.set_to_rgmii = rk3568_set_to_rgmii,
>> +		.set_to_rmii = rk3568_set_to_rmii,
>> +		.set_gmac_speed = rk3568_set_gmac_speed,
>> +		.regs = {
>> +			0xfe2a0000, /* gmac0 */
>> +			0xfe010000, /* gmac1 */
>> +			0x0, /* sentinel */
>> +		},
> Can these be referenced to a const struct ?
>> +	},
>> +	{ }
>> +};
>> +
>> +static const struct rk_gmac_ops *get_rk_gmac_ops(struct udevice *dev)
>> +{
>> +	const struct rk_gmac_ops *ops = rk_gmac_ops;
>> +
>> +	while (ops->compatible) {
>> +		if (device_is_compatible(dev, ops->compatible))
>> +			return ops;
>> +		ops++;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +static int eqos_probe_resources_rk(struct udevice *dev)
>> +{
>> +	struct eqos_priv *eqos = dev_get_priv(dev);
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data;
>> +	int reset_flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
>> +	int ret;
>> +
>> +	data = calloc(1, sizeof(struct rockchip_platform_data));
>> +	if (!data)
>> +		return -ENOMEM;
>> +
>> +	data->ops = get_rk_gmac_ops(dev);
>> +	if (!data->ops) {
>> +		ret = -EINVAL;
>> +		goto err_free;
>> +	}
>> +
>> +	for (int i = 0; data->ops->regs[i]; i++) {
>> +		if (data->ops->regs[i] == (u32)eqos->regs) {
>> +			data->id = i;
>> +			break;
>> +		}
>> +	}
>> +
>> +	pdata->priv_pdata = data;
>> +	pdata->phy_interface = eqos->config->interface(dev);
>> +	pdata->max_speed = eqos->max_speed;
>> +
>> +	if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
>> +		pr_err("Invalid PHY interface\n");
>> +		ret = -EINVAL;
>> +		goto err_free;
>> +	}
>> +
>> +	data->grf = syscon_regmap_lookup_by_phandle(dev, "rockchip,grf");
>> +	if (IS_ERR(data->grf)) {
>> +		dev_err(dev, "Missing rockchip,grf property\n");
>> +		ret = -EINVAL;
>> +		goto err_free;
>> +	}
> 
>  From my read of the binding, rockchip,grf is not mandatory. Is it 
> possible to just ignore the grf if the property is missing ?

This code and the linux driver require this property or it cannot locate
grf, would like to avoid falling back on the hack we have in U-Boot to
locate grf. And without having regmap of grf we cannot configure the
gmac in rgmii/rmii mode.

The linux driver does a check if grf is valid in the individual
set_to_grmii/rmii functions, I thoutht it was better to fail earlier
at probe time.

> 
>> +
>> +	ret = reset_get_bulk(dev, &data->resets);
>> +	if (ret < 0)
>> +		goto err_free;
>> +
>> +	reset_assert_bulk(&data->resets);
>> +
> 
> The same goes for the clocks below, the binding specifies min clocks is 
> 5, and maximum clocks is 8, but not which are the 5 minimum required clocks.
> So , can we not stop if some of the clocks are missing ?

I do not really see any reason for that, the clock drivers for rk35xx in
U-Boot do not implement set_enable/disable, so auto gating or default
state is required for gmac to work in U-Boot.

We only need the following clock refs to get the rate or to set the gmac
speed in rk3568 case. Also we just follow linux driver here:

  return dev_err_probe(dev, ret, "Cannot get stmmaceth clock\n");

So the stmmaceth clock is mandatory, and clk_mac_speed for rk3568 or we
cannot change link speed.

> 
>> +	ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
>> +	if (ret) {
>> +		dev_dbg(dev, "clk_get_by_name(stmmaceth) failed: %d", ret);
>> +		goto err_release_resets;
>> +	}
>> +
>> +	ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
>> +	if (ret) {
>> +		dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
>> +		goto err_free_clk_master_bus;
>> +	}
>> +
>> +	if (dev_read_bool(dev, "snps,reset-active-low"))
>> +		reset_flags |= GPIOD_ACTIVE_LOW;
>> +
>> +	dev_read_u32_array(dev, "snps,reset-delays-us", eqos->reset_delays, 3);
>> +
>> +	gpio_request_by_name(dev, "snps,reset-gpio", 0,
>> +			     &eqos->phy_reset_gpio, reset_flags);
> 
> reset-gpio appears to be deprecated according to the binding,
> also, you do not check the error code and assume the property exists ?

Yes this was intentional, should probably add a comment about it.

This tries very minimum to support reset using the deprecated binding.
If the properties exists, gpio pin will be asserted here and then in
start_clks we wait, deassert pin, wait again. If they do not exists we
silently continue.

With reset-gpios in phy node, the Ethernet Generic PHY driver will
propertly assert pin, wait, deassert pin, wait again.

However, some boards still use the deprecated binding because reset-gpios
in phy node does not work properly. Linux does not issue an proper assert
deassert cycle in a way that one would expect, and instead treats it like
a reset signal.

There there is also a chicken-and-egg problem in linux:
- phy needs to be reset or phy_id read back as 0xffffffff on mdio bus
- phy device is not created because a valid phy_id is not read back
- phy device needs to be created before it can be reset

Please see more details of what I discovered in this linux thread:
https://lore.kernel.org/linux-rockchip/47d55aca-bee6-810f-379f-9431649fefa6@kwiboo.se/

Regards,
Jonas

> 
> 
> Greetings,
> Eugen
>> +
>> +	return 0;
>> +
>> +err_free_clk_master_bus:
>> +	clk_free(&eqos->clk_master_bus);
>> +err_release_resets:
>> +	reset_release_bulk(&data->resets);
>> +err_free:
>> +	free(data);
>> +
>> +	return ret;
>> +}
>> +
>> +static int eqos_remove_resources_rk(struct udevice *dev)
>> +{
>> +	struct eqos_priv *eqos = dev_get_priv(dev);
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +
>> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio))
>> +		dm_gpio_free(dev, &eqos->phy_reset_gpio);
>> +
>> +	clk_free(&eqos->clk_tx);
>> +	clk_free(&eqos->clk_master_bus);
>> +	reset_release_bulk(&data->resets);
>> +	free(data);
>> +
>> +	return 0;
>> +}
>> +
>> +static int eqos_stop_resets_rk(struct udevice *dev)
>> +{
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +
>> +	return reset_assert_bulk(&data->resets);
>> +}
>> +
>> +static int eqos_start_resets_rk(struct udevice *dev)
>> +{
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +
>> +	return reset_deassert_bulk(&data->resets);
>> +}
>> +
>> +static int eqos_stop_clks_rk(struct udevice *dev)
>> +{
>> +	return 0;
>> +}
>> +
>> +static int eqos_start_clks_rk(struct udevice *dev)
>> +{
>> +	struct eqos_priv *eqos = dev_get_priv(dev);
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +	int tx_delay, rx_delay, ret;
>> +
>> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
>> +		udelay(eqos->reset_delays[1]);
>> +
>> +		ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		udelay(eqos->reset_delays[2]);
>> +	}
>> +
>> +	tx_delay = dev_read_u32_default(dev, "tx_delay", 0x30);
>> +	rx_delay = dev_read_u32_default(dev, "rx_delay", 0x10);
>> +
>> +	switch (pdata->phy_interface) {
>> +	case PHY_INTERFACE_MODE_RGMII:
>> +		return data->ops->set_to_rgmii(dev, tx_delay, rx_delay);
>> +	case PHY_INTERFACE_MODE_RGMII_ID:
>> +		return data->ops->set_to_rgmii(dev, 0, 0);
>> +	case PHY_INTERFACE_MODE_RGMII_RXID:
>> +		return data->ops->set_to_rgmii(dev, tx_delay, 0);
>> +	case PHY_INTERFACE_MODE_RGMII_TXID:
>> +		return data->ops->set_to_rgmii(dev, 0, rx_delay);
>> +	case PHY_INTERFACE_MODE_RMII:
>> +		return data->ops->set_to_rmii(dev);
>> +	}
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static int eqos_set_tx_clk_speed_rk(struct udevice *dev)
>> +{
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +
>> +	return data->ops->set_gmac_speed(dev);
>> +}
>> +
>> +static ulong eqos_get_tick_clk_rate_rk(struct udevice *dev)
>> +{
>> +	struct eqos_priv *eqos = dev_get_priv(dev);
>> +
>> +	return clk_get_rate(&eqos->clk_master_bus);
>> +}
>> +
>> +static struct eqos_ops eqos_rockchip_ops = {
>> +	.eqos_inval_desc = eqos_inval_desc_generic,
>> +	.eqos_flush_desc = eqos_flush_desc_generic,
>> +	.eqos_inval_buffer = eqos_inval_buffer_generic,
>> +	.eqos_flush_buffer = eqos_flush_buffer_generic,
>> +	.eqos_probe_resources = eqos_probe_resources_rk,
>> +	.eqos_remove_resources = eqos_remove_resources_rk,
>> +	.eqos_stop_resets = eqos_stop_resets_rk,
>> +	.eqos_start_resets = eqos_start_resets_rk,
>> +	.eqos_stop_clks = eqos_stop_clks_rk,
>> +	.eqos_start_clks = eqos_start_clks_rk,
>> +	.eqos_calibrate_pads = eqos_null_ops,
>> +	.eqos_disable_calibration = eqos_null_ops,
>> +	.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_rk,
>> +	.eqos_get_enetaddr = eqos_null_ops,
>> +	.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_rk,
>> +};
>> +
>> +struct eqos_config eqos_rockchip_config = {
>> +	.reg_access_always_ok = false,
>> +	.mdio_wait = 10,
>> +	.swr_wait = 50,
>> +	.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
>> +	.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_100_150,
>> +	.axi_bus_width = EQOS_AXI_WIDTH_64,
>> +	.interface = dev_read_phy_mode,
>> +	.ops = &eqos_rockchip_ops,
>> +};
> 


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588
  2023-08-07  0:08 [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Jonas Karlman
                   ` (6 preceding siblings ...)
  2023-08-07  0:08 ` [PATCH 7/7] configs: rockchip: Enable ethernet driver on RK3588 boards Jonas Karlman
@ 2023-08-12  3:04 ` Kever Yang
  7 siblings, 0 replies; 22+ messages in thread
From: Kever Yang @ 2023-08-12  3:04 UTC (permalink / raw)
  To: Jonas Karlman, Simon Glass, Philipp Tomsich, 吴达超
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot

Add David,


Hi David,

     Please help to review this patch set for dwc_eth_qos for rk3568/rk3588.


Thanks,

- Kever

On 2023/8/7 08:08, Jonas Karlman wrote:
> This series adds a glue driver, dwc_eth_qos_rockchip, to support GMAC
> on RK356x and RK3588.
>
> rk_gmac_ops used in this series has been ported from mainline linux.
>
> Patch 1-3 does some minor cleanup in dwc_eth_qos driver.
> Patch 4 add glue driver with RK3568 support.
> Patch 5 add support for RK3588 to glue driver.
> Patch 6-7 update defconfigs to enable use of the new driver.
>
> Dependencies:
> - "pinctrl: rockchip: Fix drive and input schmitt on RK3568" [1]
> - "clk: rockchip: rk3568: Add dummy support for GMAC speed clocks" [2]
> - "net: phy: motorcomm: Add support for YT8511 PHY" [3]
> - "rockchip: Port IO-domain driver for RK3568 from linux" [4]
>
> dhcp and ping commands has been tested on the followin devices:
> - RK3566: Quartz64 Model A and SOQuartz on Blade
> - RK3568: ROCK 3 Model A
> - RK3588: ROCK 5 Model A
>
> This series can also be found at [5].
>
> [1] https://patchwork.ozlabs.org/patch/1816600/
> [2] https://patchwork.ozlabs.org/patch/1816856/
> [3] https://patchwork.ozlabs.org/patch/1817295/
> [4] https://patchwork.ozlabs.org/cover/1817469/
> [5] https://github.com/Kwiboo/u-boot-rockchip/commits/rk35xx-gmac-v1
>
> Jonas Karlman (7):
>    net: dwc_eth_qos: Drop unused rx_pkt from eqos_priv
>    net: dwc_eth_qos: Return error code when start fails
>    net: dwc_eth_qos: Stop spam of RX packet not available message
>    net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568
>    net: dwc_eth_qos_rockchip: Add support for RK3588
>    configs: rockchip: Enable ethernet driver on RK356x boards
>    configs: rockchip: Enable ethernet driver on RK3588 boards
>
>   configs/evb-rk3568_defconfig              |   5 +-
>   configs/evb-rk3588_defconfig              |   5 +-
>   configs/nanopi-r5s-rk3568_defconfig       |   3 +
>   configs/neu6a-io-rk3588_defconfig         |   2 -
>   configs/neu6b-io-rk3588_defconfig         |   2 -
>   configs/odroid-m1-rk3568_defconfig        |   3 +
>   configs/quartz64-a-rk3566_defconfig       |   3 +
>   configs/quartz64-b-rk3566_defconfig       |   3 +
>   configs/radxa-cm3-io-rk3566_defconfig     |   6 +-
>   configs/rock-3a-rk3568_defconfig          |   5 +-
>   configs/rock5a-rk3588s_defconfig          |   6 +-
>   configs/soquartz-blade-rk3566_defconfig   |   3 +
>   configs/soquartz-cm4-rk3566_defconfig     |   3 +
>   configs/soquartz-model-a-rk3566_defconfig |   3 +
>   drivers/net/Kconfig                       |   8 +
>   drivers/net/Makefile                      |   1 +
>   drivers/net/dwc_eth_qos.c                 |  33 +-
>   drivers/net/dwc_eth_qos.h                 |   3 +-
>   drivers/net/dwc_eth_qos_rockchip.c        | 522 ++++++++++++++++++++++
>   19 files changed, 585 insertions(+), 34 deletions(-)
>   create mode 100644 drivers/net/dwc_eth_qos_rockchip.c
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568
  2023-08-07  0:08 ` [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568 Jonas Karlman
  2023-08-07 14:41   ` Eugen Hristev
@ 2023-08-15 13:12   ` David Wu
  2023-10-01 19:04     ` Jonas Karlman
  2023-09-27  3:01   ` Kever Yang
  2 siblings, 1 reply; 22+ messages in thread
From: David Wu @ 2023-08-15 13:12 UTC (permalink / raw)
  To: Jonas Karlman, Kever Yang, Simon Glass, Philipp Tomsich,
	Joe Hershberger, Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot,
	Ezequiel Garcia

Hi Jonas,

Thank you for your help.

在 2023/8/7 08:08, Jonas Karlman 写道:
> Add a new glue driver for Rockchip SoCs, i.e RK3568, with a GMAC based
> on Synopsys DWC Ethernet QoS IP.
>
> rk_gmac_ops was ported from linux commit:
> 3bb3d6b1c195 ("net: stmmac: Add RK3566/RK3568 SoC support")
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
> ---
> Cc: David Wu <david.wu@rock-chips.com>
> Cc: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>   drivers/net/Kconfig                |   8 +
>   drivers/net/Makefile               |   1 +
>   drivers/net/dwc_eth_qos.c          |   8 +-
>   drivers/net/dwc_eth_qos.h          |   2 +
>   drivers/net/dwc_eth_qos_rockchip.c | 348 +++++++++++++++++++++++++++++
>   5 files changed, 365 insertions(+), 2 deletions(-)
>   create mode 100644 drivers/net/dwc_eth_qos_rockchip.c
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 0ed39a61e4de..29304fd77759 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -225,6 +225,14 @@ config DWC_ETH_QOS_IMX
>   	  The Synopsys Designware Ethernet QOS IP block with the specific
>   	  configuration used in IMX soc.
>   
> +config DWC_ETH_QOS_ROCKCHIP
> +	bool "Synopsys DWC Ethernet QOS device support for Rockchip SoCs"
> +	depends on DWC_ETH_QOS
> +	select DM_ETH_PHY
> +	help
> +	  The Synopsys Designware Ethernet QOS IP block with specific
> +	  configuration used in Rockchip SoCs.
> +
>   config DWC_ETH_QOS_STM32
>   	bool "Synopsys DWC Ethernet QOS device support for STM32"
>   	depends on DWC_ETH_QOS
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index d4af253b6f28..1d444f5b4a69 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
>   obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
>   obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
>   obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o
> +obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o
>   obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
>   obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o
>   obj-$(CONFIG_E1000) += e1000.o
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index 24fb3fac1f12..9fb98a2c3c74 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -1707,7 +1707,12 @@ static const struct udevice_id eqos_ids[] = {
>   		.data = (ulong)&eqos_imx_config
>   	},
>   #endif
> -
> +#if IS_ENABLED(CONFIG_DWC_ETH_QOS_ROCKCHIP)
> +	{
> +		.compatible = "rockchip,rk3568-gmac",
> +		.data = (ulong)&eqos_rockchip_config
> +	},
> +#endif

If this compatible could move to dwc_eth_qos_rockchip.c, it is better,
we have other SoCs  that also use this driver in the feature,  and it 
must increase
this array all the time for new SoCs later, it will be better only change
dwc_eth_qos_rockchip.c, we don't need to change the current file.

>   #if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
>   	{
>   		.compatible = "qcom,qcs404-ethqos",
> @@ -1720,7 +1725,6 @@ static const struct udevice_id eqos_ids[] = {
>   		.data = (ulong)&eqos_jh7110_config
>   	},
>   #endif
> -
>   	{ }
>   };
>   
> diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
> index 06a082da72ef..e3222e1e17e5 100644
> --- a/drivers/net/dwc_eth_qos.h
> +++ b/drivers/net/dwc_eth_qos.h
> @@ -82,6 +82,7 @@ struct eqos_mac_regs {
>   #define EQOS_MAC_MDIO_ADDRESS_PA_SHIFT			21
>   #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT			16
>   #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT			8
> +#define EQOS_MAC_MDIO_ADDRESS_CR_100_150		1
>   #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)
> @@ -287,5 +288,6 @@ void eqos_flush_buffer_generic(void *buf, size_t size);
>   int eqos_null_ops(struct udevice *dev);
>   
>   extern struct eqos_config eqos_imx_config;
> +extern struct eqos_config eqos_rockchip_config;
>   extern struct eqos_config eqos_qcom_config;
>   extern struct eqos_config eqos_jh7110_config;
> diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c
> new file mode 100644
> index 000000000000..c8abe351fc3e
> --- /dev/null
> +++ b/drivers/net/dwc_eth_qos_rockchip.c
> @@ -0,0 +1,348 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dm/device_compat.h>
> +#include <net.h>
> +#include <phy.h>
> +#include <regmap.h>
> +#include <reset.h>
> +#include <syscon.h>
> +#include <asm/gpio.h>
> +#include <linux/delay.h>
> +
> +#include "dwc_eth_qos.h"
> +
> +struct rk_gmac_ops {
> +	const char *compatible;
> +	int (*set_to_rgmii)(struct udevice *dev,
> +			    int tx_delay, int rx_delay);
> +	int (*set_to_rmii)(struct udevice *dev);
> +	int (*set_gmac_speed)(struct udevice *dev);
> +	u32 regs[3];
> +};
> +
> +struct rockchip_platform_data {
> +	struct reset_ctl_bulk resets;
> +	const struct rk_gmac_ops *ops;
> +	int id;
> +	struct regmap *grf;
> +};
> +
> +#define HIWORD_UPDATE(val, mask, shift) \
> +		((val) << (shift) | (mask) << ((shift) + 16))
> +
> +#define GRF_BIT(nr)	(BIT(nr) | BIT((nr) + 16))
> +#define GRF_CLR_BIT(nr)	(BIT((nr) + 16))
> +
> +#define RK3568_GRF_GMAC0_CON0		0x0380
> +#define RK3568_GRF_GMAC0_CON1		0x0384
> +#define RK3568_GRF_GMAC1_CON0		0x0388
> +#define RK3568_GRF_GMAC1_CON1		0x038c
> +
> +/* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */
> +#define RK3568_GMAC_PHY_INTF_SEL_RGMII	\
> +		(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
> +#define RK3568_GMAC_PHY_INTF_SEL_RMII	\
> +		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
> +#define RK3568_GMAC_FLOW_CTRL			GRF_BIT(3)
> +#define RK3568_GMAC_FLOW_CTRL_CLR		GRF_CLR_BIT(3)
> +#define RK3568_GMAC_RXCLK_DLY_ENABLE		GRF_BIT(1)
> +#define RK3568_GMAC_RXCLK_DLY_DISABLE		GRF_CLR_BIT(1)
> +#define RK3568_GMAC_TXCLK_DLY_ENABLE		GRF_BIT(0)
> +#define RK3568_GMAC_TXCLK_DLY_DISABLE		GRF_CLR_BIT(0)
> +
> +/* RK3568_GRF_GMAC0_CON0 && RK3568_GRF_GMAC1_CON0 */
> +#define RK3568_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
> +#define RK3568_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
> +
> +static int rk3568_set_to_rgmii(struct udevice *dev,
> +			       int tx_delay, int rx_delay)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +	u32 con0, con1;
> +
> +	con0 = (data->id == 1) ? RK3568_GRF_GMAC1_CON0 :
> +				 RK3568_GRF_GMAC0_CON0;
> +	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
> +				 RK3568_GRF_GMAC0_CON1;
> +
> +	regmap_write(data->grf, con0,
> +		     RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) |
> +		     RK3568_GMAC_CLK_TX_DL_CFG(tx_delay));
> +
> +	regmap_write(data->grf, con1,
> +		     RK3568_GMAC_PHY_INTF_SEL_RGMII |
> +		     RK3568_GMAC_RXCLK_DLY_ENABLE |
> +		     RK3568_GMAC_TXCLK_DLY_ENABLE);
> +
> +	return 0;
> +}
> +
> +static int rk3568_set_to_rmii(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +	u32 con1;
> +
> +	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
> +				 RK3568_GRF_GMAC0_CON1;
> +	regmap_write(data->grf, con1, RK3568_GMAC_PHY_INTF_SEL_RMII);
> +
> +	return 0;
> +}
> +
> +static int rk3568_set_gmac_speed(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	ulong rate;
> +	int ret;
> +
> +	switch (eqos->phy->speed) {
> +	case SPEED_10:
> +		rate = 2500000;
> +		break;
> +	case SPEED_100:
> +		rate = 25000000;
> +		break;
> +	case SPEED_1000:
> +		rate = 125000000;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	ret = clk_set_rate(&eqos->clk_tx, rate);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static const struct rk_gmac_ops rk_gmac_ops[] = {
> +	{
> +		.compatible = "rockchip,rk3568-gmac",
> +		.set_to_rgmii = rk3568_set_to_rgmii,
> +		.set_to_rmii = rk3568_set_to_rmii,
> +		.set_gmac_speed = rk3568_set_gmac_speed,
> +		.regs = {
> +			0xfe2a0000, /* gmac0 */
> +			0xfe010000, /* gmac1 */
> +			0x0, /* sentinel */
> +		},
> +	},
> +	{ }
> +};
> +
> +static const struct rk_gmac_ops *get_rk_gmac_ops(struct udevice *dev)
> +{
> +	const struct rk_gmac_ops *ops = rk_gmac_ops;
> +
> +	while (ops->compatible) {
> +		if (device_is_compatible(dev, ops->compatible))
> +			return ops;
> +		ops++;
> +	}
> +
> +	return NULL;
> +}
> +
> +static int eqos_probe_resources_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data;
> +	int reset_flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
> +	int ret;
> +
> +	data = calloc(1, sizeof(struct rockchip_platform_data));
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->ops = get_rk_gmac_ops(dev);
> +	if (!data->ops) {
> +		ret = -EINVAL;
> +		goto err_free;
> +	}
> +
> +	for (int i = 0; data->ops->regs[i]; i++) {
> +		if (data->ops->regs[i] == (u32)eqos->regs) {
> +			data->id = i;
> +			break;
> +		}
> +	}
> +
> +	pdata->priv_pdata = data;
> +	pdata->phy_interface = eqos->config->interface(dev);
> +	pdata->max_speed = eqos->max_speed;
> +
> +	if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
> +		pr_err("Invalid PHY interface\n");
> +		ret = -EINVAL;
> +		goto err_free;
> +	}
> +
> +	data->grf = syscon_regmap_lookup_by_phandle(dev, "rockchip,grf");
> +	if (IS_ERR(data->grf)) {
> +		dev_err(dev, "Missing rockchip,grf property\n");
> +		ret = -EINVAL;
> +		goto err_free;
> +	}
> +
> +	ret = reset_get_bulk(dev, &data->resets);
> +	if (ret < 0)
> +		goto err_free;
> +
> +	reset_assert_bulk(&data->resets);
> +
> +	ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
> +	if (ret) {
> +		dev_dbg(dev, "clk_get_by_name(stmmaceth) failed: %d", ret);
> +		goto err_release_resets;
> +	}
> +
> +	ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
> +	if (ret) {
> +		dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
> +		goto err_free_clk_master_bus;
> +	}
> +
> +	if (dev_read_bool(dev, "snps,reset-active-low"))
> +		reset_flags |= GPIOD_ACTIVE_LOW;
> +
> +	dev_read_u32_array(dev, "snps,reset-delays-us", eqos->reset_delays, 3);
> +
> +	gpio_request_by_name(dev, "snps,reset-gpio", 0,
> +			     &eqos->phy_reset_gpio, reset_flags);
> +
> +	return 0;
> +
> +err_free_clk_master_bus:
> +	clk_free(&eqos->clk_master_bus);
> +err_release_resets:
> +	reset_release_bulk(&data->resets);
> +err_free:
> +	free(data);
> +
> +	return ret;
> +}
> +
> +static int eqos_remove_resources_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio))
> +		dm_gpio_free(dev, &eqos->phy_reset_gpio);
> +
> +	clk_free(&eqos->clk_tx);
> +	clk_free(&eqos->clk_master_bus);
> +	reset_release_bulk(&data->resets);
> +	free(data);
> +
> +	return 0;
> +}
> +
> +static int eqos_stop_resets_rk(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	return reset_assert_bulk(&data->resets);
> +}
> +
> +static int eqos_start_resets_rk(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	return reset_deassert_bulk(&data->resets);
> +}
> +
> +static int eqos_stop_clks_rk(struct udevice *dev)
> +{
> +	return 0;
> +}
> +
> +static int eqos_start_clks_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +	int tx_delay, rx_delay, ret;
> +
> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
> +		udelay(eqos->reset_delays[1]);
> +
> +		ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
> +		if (ret < 0)
> +			return ret;
> +
> +		udelay(eqos->reset_delays[2]);
> +	}
> +
> +	tx_delay = dev_read_u32_default(dev, "tx_delay", 0x30);
> +	rx_delay = dev_read_u32_default(dev, "rx_delay", 0x10);
> +
> +	switch (pdata->phy_interface) {
> +	case PHY_INTERFACE_MODE_RGMII:
> +		return data->ops->set_to_rgmii(dev, tx_delay, rx_delay);
> +	case PHY_INTERFACE_MODE_RGMII_ID:
> +		return data->ops->set_to_rgmii(dev, 0, 0);
> +	case PHY_INTERFACE_MODE_RGMII_RXID:
> +		return data->ops->set_to_rgmii(dev, tx_delay, 0);
> +	case PHY_INTERFACE_MODE_RGMII_TXID:
> +		return data->ops->set_to_rgmii(dev, 0, rx_delay);
> +	case PHY_INTERFACE_MODE_RMII:
> +		return data->ops->set_to_rmii(dev);
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int eqos_set_tx_clk_speed_rk(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	return data->ops->set_gmac_speed(dev);
> +}
> +
> +static ulong eqos_get_tick_clk_rate_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +
> +	return clk_get_rate(&eqos->clk_master_bus);
> +}
> +
> +static struct eqos_ops eqos_rockchip_ops = {
> +	.eqos_inval_desc = eqos_inval_desc_generic,
> +	.eqos_flush_desc = eqos_flush_desc_generic,
> +	.eqos_inval_buffer = eqos_inval_buffer_generic,
> +	.eqos_flush_buffer = eqos_flush_buffer_generic,
> +	.eqos_probe_resources = eqos_probe_resources_rk,
> +	.eqos_remove_resources = eqos_remove_resources_rk,
> +	.eqos_stop_resets = eqos_stop_resets_rk,
> +	.eqos_start_resets = eqos_start_resets_rk,
> +	.eqos_stop_clks = eqos_stop_clks_rk,
> +	.eqos_start_clks = eqos_start_clks_rk,
> +	.eqos_calibrate_pads = eqos_null_ops,
> +	.eqos_disable_calibration = eqos_null_ops,
> +	.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_rk,
> +	.eqos_get_enetaddr = eqos_null_ops,
> +	.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_rk,
> +};
> +
> +struct eqos_config eqos_rockchip_config = {
> +	.reg_access_always_ok = false,
> +	.mdio_wait = 10,
> +	.swr_wait = 50,
> +	.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
> +	.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_100_150,
> +	.axi_bus_width = EQOS_AXI_WIDTH_64,
> +	.interface = dev_read_phy_mode,
> +	.ops = &eqos_rockchip_ops,
> +};

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/7] net: dwc_eth_qos: Drop unused rx_pkt from eqos_priv
  2023-08-07  0:08 ` [PATCH 1/7] net: dwc_eth_qos: Drop unused rx_pkt from eqos_priv Jonas Karlman
@ 2023-09-27  3:00   ` Kever Yang
  0 siblings, 0 replies; 22+ messages in thread
From: Kever Yang @ 2023-09-27  3:00 UTC (permalink / raw)
  To: Jonas Karlman, Simon Glass, Philipp Tomsich, Joe Hershberger,
	Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot


On 2023/8/7 08:08, Jonas Karlman wrote:
> rx_pkt is allocated and not used for anything, remove it.
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever
> ---
>   drivers/net/dwc_eth_qos.c | 11 -----------
>   drivers/net/dwc_eth_qos.h |  1 -
>   2 files changed, 12 deletions(-)
>
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index 1e92bd9ca9c0..555eaee3bbc3 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -1314,22 +1314,12 @@ static int eqos_probe_resources_core(struct udevice *dev)
>   	}
>   	debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
>   
> -	eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE);
> -	if (!eqos->rx_pkt) {
> -		debug("%s: malloc(rx_pkt) failed\n", __func__);
> -		ret = -ENOMEM;
> -		goto err_free_rx_dma_buf;
> -	}
> -	debug("%s: rx_pkt=%p\n", __func__, eqos->rx_pkt);
> -
>   	eqos->config->ops->eqos_inval_buffer(eqos->rx_dma_buf,
>   			EQOS_MAX_PACKET_SIZE * EQOS_DESCRIPTORS_RX);
>   
>   	debug("%s: OK\n", __func__);
>   	return 0;
>   
> -err_free_rx_dma_buf:
> -	free(eqos->rx_dma_buf);
>   err_free_tx_dma_buf:
>   	free(eqos->tx_dma_buf);
>   err_free_descs:
> @@ -1348,7 +1338,6 @@ static int eqos_remove_resources_core(struct udevice *dev)
>   
>   	debug("%s(dev=%p):\n", __func__, dev);
>   
> -	free(eqos->rx_pkt);
>   	free(eqos->rx_dma_buf);
>   	free(eqos->tx_dma_buf);
>   	eqos_free_descs(eqos->rx_descs);
> diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
> index a6b719af809f..06a082da72ef 100644
> --- a/drivers/net/dwc_eth_qos.h
> +++ b/drivers/net/dwc_eth_qos.h
> @@ -273,7 +273,6 @@ struct eqos_priv {
>   	unsigned int desc_per_cacheline;
>   	void *tx_dma_buf;
>   	void *rx_dma_buf;
> -	void *rx_pkt;
>   	bool started;
>   	bool reg_access_ok;
>   	bool clk_ck_enabled;

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/7] net: dwc_eth_qos: Return error code when start fails
  2023-08-07  0:08 ` [PATCH 2/7] net: dwc_eth_qos: Return error code when start fails Jonas Karlman
@ 2023-09-27  3:00   ` Kever Yang
  0 siblings, 0 replies; 22+ messages in thread
From: Kever Yang @ 2023-09-27  3:00 UTC (permalink / raw)
  To: Jonas Karlman, Simon Glass, Philipp Tomsich, Joe Hershberger,
	Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot


On 2023/8/7 08:08, Jonas Karlman wrote:
> Return error code when phy_connect fails or no link can be established.
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever
> ---
>   drivers/net/dwc_eth_qos.c | 2 ++
>   1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index 555eaee3bbc3..7565e716823a 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -811,6 +811,7 @@ static int eqos_start(struct udevice *dev)
>   
>   		if (!eqos->phy) {
>   			pr_err("phy_connect() failed");
> +			ret = -ENODEV;
>   			goto err_stop_resets;
>   		}
>   
> @@ -838,6 +839,7 @@ static int eqos_start(struct udevice *dev)
>   
>   	if (!eqos->phy->link) {
>   		pr_err("No link");
> +		ret = -EAGAIN;
>   		goto err_shutdown_phy;
>   	}
>   

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 3/7] net: dwc_eth_qos: Stop spam of RX packet not available message
  2023-08-07  0:08 ` [PATCH 3/7] net: dwc_eth_qos: Stop spam of RX packet not available message Jonas Karlman
@ 2023-09-27  3:00   ` Kever Yang
  0 siblings, 0 replies; 22+ messages in thread
From: Kever Yang @ 2023-09-27  3:00 UTC (permalink / raw)
  To: Jonas Karlman, Simon Glass, Philipp Tomsich, Joe Hershberger,
	Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot


On 2023/8/7 08:08, Jonas Karlman wrote:
> Remove spam of RX packet not available debug messages when waiting to
> receive a packet.
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever
> ---
>   drivers/net/dwc_eth_qos.c | 8 +++-----
>   1 file changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index 7565e716823a..24fb3fac1f12 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -1193,14 +1193,12 @@ static int eqos_recv(struct udevice *dev, int flags, uchar **packetp)
>   	struct eqos_desc *rx_desc;
>   	int length;
>   
> -	debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags);
> -
>   	rx_desc = eqos_get_desc(eqos, eqos->rx_desc_idx, true);
>   	eqos->config->ops->eqos_inval_desc(rx_desc);
> -	if (rx_desc->des3 & EQOS_DESC3_OWN) {
> -		debug("%s: RX packet not available\n", __func__);
> +	if (rx_desc->des3 & EQOS_DESC3_OWN)
>   		return -EAGAIN;
> -	}
> +
> +	debug("%s(dev=%p, flags=%x):\n", __func__, dev, flags);
>   
>   	*packetp = eqos->rx_dma_buf +
>   		(eqos->rx_desc_idx * EQOS_MAX_PACKET_SIZE);

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568
  2023-08-07  0:08 ` [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568 Jonas Karlman
  2023-08-07 14:41   ` Eugen Hristev
  2023-08-15 13:12   ` David Wu
@ 2023-09-27  3:01   ` Kever Yang
  2 siblings, 0 replies; 22+ messages in thread
From: Kever Yang @ 2023-09-27  3:01 UTC (permalink / raw)
  To: Jonas Karlman, Simon Glass, Philipp Tomsich, Joe Hershberger,
	Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot,
	David Wu, Ezequiel Garcia


On 2023/8/7 08:08, Jonas Karlman wrote:
> Add a new glue driver for Rockchip SoCs, i.e RK3568, with a GMAC based
> on Synopsys DWC Ethernet QoS IP.
>
> rk_gmac_ops was ported from linux commit:
> 3bb3d6b1c195 ("net: stmmac: Add RK3566/RK3568 SoC support")
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever
> ---
> Cc: David Wu <david.wu@rock-chips.com>
> Cc: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>   drivers/net/Kconfig                |   8 +
>   drivers/net/Makefile               |   1 +
>   drivers/net/dwc_eth_qos.c          |   8 +-
>   drivers/net/dwc_eth_qos.h          |   2 +
>   drivers/net/dwc_eth_qos_rockchip.c | 348 +++++++++++++++++++++++++++++
>   5 files changed, 365 insertions(+), 2 deletions(-)
>   create mode 100644 drivers/net/dwc_eth_qos_rockchip.c
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 0ed39a61e4de..29304fd77759 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -225,6 +225,14 @@ config DWC_ETH_QOS_IMX
>   	  The Synopsys Designware Ethernet QOS IP block with the specific
>   	  configuration used in IMX soc.
>   
> +config DWC_ETH_QOS_ROCKCHIP
> +	bool "Synopsys DWC Ethernet QOS device support for Rockchip SoCs"
> +	depends on DWC_ETH_QOS
> +	select DM_ETH_PHY
> +	help
> +	  The Synopsys Designware Ethernet QOS IP block with specific
> +	  configuration used in Rockchip SoCs.
> +
>   config DWC_ETH_QOS_STM32
>   	bool "Synopsys DWC Ethernet QOS device support for STM32"
>   	depends on DWC_ETH_QOS
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index d4af253b6f28..1d444f5b4a69 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
>   obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
>   obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
>   obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o
> +obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o
>   obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
>   obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o
>   obj-$(CONFIG_E1000) += e1000.o
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index 24fb3fac1f12..9fb98a2c3c74 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -1707,7 +1707,12 @@ static const struct udevice_id eqos_ids[] = {
>   		.data = (ulong)&eqos_imx_config
>   	},
>   #endif
> -
> +#if IS_ENABLED(CONFIG_DWC_ETH_QOS_ROCKCHIP)
> +	{
> +		.compatible = "rockchip,rk3568-gmac",
> +		.data = (ulong)&eqos_rockchip_config
> +	},
> +#endif
>   #if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
>   	{
>   		.compatible = "qcom,qcs404-ethqos",
> @@ -1720,7 +1725,6 @@ static const struct udevice_id eqos_ids[] = {
>   		.data = (ulong)&eqos_jh7110_config
>   	},
>   #endif
> -
>   	{ }
>   };
>   
> diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
> index 06a082da72ef..e3222e1e17e5 100644
> --- a/drivers/net/dwc_eth_qos.h
> +++ b/drivers/net/dwc_eth_qos.h
> @@ -82,6 +82,7 @@ struct eqos_mac_regs {
>   #define EQOS_MAC_MDIO_ADDRESS_PA_SHIFT			21
>   #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT			16
>   #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT			8
> +#define EQOS_MAC_MDIO_ADDRESS_CR_100_150		1
>   #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)
> @@ -287,5 +288,6 @@ void eqos_flush_buffer_generic(void *buf, size_t size);
>   int eqos_null_ops(struct udevice *dev);
>   
>   extern struct eqos_config eqos_imx_config;
> +extern struct eqos_config eqos_rockchip_config;
>   extern struct eqos_config eqos_qcom_config;
>   extern struct eqos_config eqos_jh7110_config;
> diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c
> new file mode 100644
> index 000000000000..c8abe351fc3e
> --- /dev/null
> +++ b/drivers/net/dwc_eth_qos_rockchip.c
> @@ -0,0 +1,348 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dm/device_compat.h>
> +#include <net.h>
> +#include <phy.h>
> +#include <regmap.h>
> +#include <reset.h>
> +#include <syscon.h>
> +#include <asm/gpio.h>
> +#include <linux/delay.h>
> +
> +#include "dwc_eth_qos.h"
> +
> +struct rk_gmac_ops {
> +	const char *compatible;
> +	int (*set_to_rgmii)(struct udevice *dev,
> +			    int tx_delay, int rx_delay);
> +	int (*set_to_rmii)(struct udevice *dev);
> +	int (*set_gmac_speed)(struct udevice *dev);
> +	u32 regs[3];
> +};
> +
> +struct rockchip_platform_data {
> +	struct reset_ctl_bulk resets;
> +	const struct rk_gmac_ops *ops;
> +	int id;
> +	struct regmap *grf;
> +};
> +
> +#define HIWORD_UPDATE(val, mask, shift) \
> +		((val) << (shift) | (mask) << ((shift) + 16))
> +
> +#define GRF_BIT(nr)	(BIT(nr) | BIT((nr) + 16))
> +#define GRF_CLR_BIT(nr)	(BIT((nr) + 16))
> +
> +#define RK3568_GRF_GMAC0_CON0		0x0380
> +#define RK3568_GRF_GMAC0_CON1		0x0384
> +#define RK3568_GRF_GMAC1_CON0		0x0388
> +#define RK3568_GRF_GMAC1_CON1		0x038c
> +
> +/* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */
> +#define RK3568_GMAC_PHY_INTF_SEL_RGMII	\
> +		(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
> +#define RK3568_GMAC_PHY_INTF_SEL_RMII	\
> +		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
> +#define RK3568_GMAC_FLOW_CTRL			GRF_BIT(3)
> +#define RK3568_GMAC_FLOW_CTRL_CLR		GRF_CLR_BIT(3)
> +#define RK3568_GMAC_RXCLK_DLY_ENABLE		GRF_BIT(1)
> +#define RK3568_GMAC_RXCLK_DLY_DISABLE		GRF_CLR_BIT(1)
> +#define RK3568_GMAC_TXCLK_DLY_ENABLE		GRF_BIT(0)
> +#define RK3568_GMAC_TXCLK_DLY_DISABLE		GRF_CLR_BIT(0)
> +
> +/* RK3568_GRF_GMAC0_CON0 && RK3568_GRF_GMAC1_CON0 */
> +#define RK3568_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
> +#define RK3568_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
> +
> +static int rk3568_set_to_rgmii(struct udevice *dev,
> +			       int tx_delay, int rx_delay)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +	u32 con0, con1;
> +
> +	con0 = (data->id == 1) ? RK3568_GRF_GMAC1_CON0 :
> +				 RK3568_GRF_GMAC0_CON0;
> +	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
> +				 RK3568_GRF_GMAC0_CON1;
> +
> +	regmap_write(data->grf, con0,
> +		     RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) |
> +		     RK3568_GMAC_CLK_TX_DL_CFG(tx_delay));
> +
> +	regmap_write(data->grf, con1,
> +		     RK3568_GMAC_PHY_INTF_SEL_RGMII |
> +		     RK3568_GMAC_RXCLK_DLY_ENABLE |
> +		     RK3568_GMAC_TXCLK_DLY_ENABLE);
> +
> +	return 0;
> +}
> +
> +static int rk3568_set_to_rmii(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +	u32 con1;
> +
> +	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
> +				 RK3568_GRF_GMAC0_CON1;
> +	regmap_write(data->grf, con1, RK3568_GMAC_PHY_INTF_SEL_RMII);
> +
> +	return 0;
> +}
> +
> +static int rk3568_set_gmac_speed(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	ulong rate;
> +	int ret;
> +
> +	switch (eqos->phy->speed) {
> +	case SPEED_10:
> +		rate = 2500000;
> +		break;
> +	case SPEED_100:
> +		rate = 25000000;
> +		break;
> +	case SPEED_1000:
> +		rate = 125000000;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	ret = clk_set_rate(&eqos->clk_tx, rate);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static const struct rk_gmac_ops rk_gmac_ops[] = {
> +	{
> +		.compatible = "rockchip,rk3568-gmac",
> +		.set_to_rgmii = rk3568_set_to_rgmii,
> +		.set_to_rmii = rk3568_set_to_rmii,
> +		.set_gmac_speed = rk3568_set_gmac_speed,
> +		.regs = {
> +			0xfe2a0000, /* gmac0 */
> +			0xfe010000, /* gmac1 */
> +			0x0, /* sentinel */
> +		},
> +	},
> +	{ }
> +};
> +
> +static const struct rk_gmac_ops *get_rk_gmac_ops(struct udevice *dev)
> +{
> +	const struct rk_gmac_ops *ops = rk_gmac_ops;
> +
> +	while (ops->compatible) {
> +		if (device_is_compatible(dev, ops->compatible))
> +			return ops;
> +		ops++;
> +	}
> +
> +	return NULL;
> +}
> +
> +static int eqos_probe_resources_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data;
> +	int reset_flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
> +	int ret;
> +
> +	data = calloc(1, sizeof(struct rockchip_platform_data));
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->ops = get_rk_gmac_ops(dev);
> +	if (!data->ops) {
> +		ret = -EINVAL;
> +		goto err_free;
> +	}
> +
> +	for (int i = 0; data->ops->regs[i]; i++) {
> +		if (data->ops->regs[i] == (u32)eqos->regs) {
> +			data->id = i;
> +			break;
> +		}
> +	}
> +
> +	pdata->priv_pdata = data;
> +	pdata->phy_interface = eqos->config->interface(dev);
> +	pdata->max_speed = eqos->max_speed;
> +
> +	if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
> +		pr_err("Invalid PHY interface\n");
> +		ret = -EINVAL;
> +		goto err_free;
> +	}
> +
> +	data->grf = syscon_regmap_lookup_by_phandle(dev, "rockchip,grf");
> +	if (IS_ERR(data->grf)) {
> +		dev_err(dev, "Missing rockchip,grf property\n");
> +		ret = -EINVAL;
> +		goto err_free;
> +	}
> +
> +	ret = reset_get_bulk(dev, &data->resets);
> +	if (ret < 0)
> +		goto err_free;
> +
> +	reset_assert_bulk(&data->resets);
> +
> +	ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
> +	if (ret) {
> +		dev_dbg(dev, "clk_get_by_name(stmmaceth) failed: %d", ret);
> +		goto err_release_resets;
> +	}
> +
> +	ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
> +	if (ret) {
> +		dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
> +		goto err_free_clk_master_bus;
> +	}
> +
> +	if (dev_read_bool(dev, "snps,reset-active-low"))
> +		reset_flags |= GPIOD_ACTIVE_LOW;
> +
> +	dev_read_u32_array(dev, "snps,reset-delays-us", eqos->reset_delays, 3);
> +
> +	gpio_request_by_name(dev, "snps,reset-gpio", 0,
> +			     &eqos->phy_reset_gpio, reset_flags);
> +
> +	return 0;
> +
> +err_free_clk_master_bus:
> +	clk_free(&eqos->clk_master_bus);
> +err_release_resets:
> +	reset_release_bulk(&data->resets);
> +err_free:
> +	free(data);
> +
> +	return ret;
> +}
> +
> +static int eqos_remove_resources_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio))
> +		dm_gpio_free(dev, &eqos->phy_reset_gpio);
> +
> +	clk_free(&eqos->clk_tx);
> +	clk_free(&eqos->clk_master_bus);
> +	reset_release_bulk(&data->resets);
> +	free(data);
> +
> +	return 0;
> +}
> +
> +static int eqos_stop_resets_rk(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	return reset_assert_bulk(&data->resets);
> +}
> +
> +static int eqos_start_resets_rk(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	return reset_deassert_bulk(&data->resets);
> +}
> +
> +static int eqos_stop_clks_rk(struct udevice *dev)
> +{
> +	return 0;
> +}
> +
> +static int eqos_start_clks_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +	int tx_delay, rx_delay, ret;
> +
> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
> +		udelay(eqos->reset_delays[1]);
> +
> +		ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
> +		if (ret < 0)
> +			return ret;
> +
> +		udelay(eqos->reset_delays[2]);
> +	}
> +
> +	tx_delay = dev_read_u32_default(dev, "tx_delay", 0x30);
> +	rx_delay = dev_read_u32_default(dev, "rx_delay", 0x10);
> +
> +	switch (pdata->phy_interface) {
> +	case PHY_INTERFACE_MODE_RGMII:
> +		return data->ops->set_to_rgmii(dev, tx_delay, rx_delay);
> +	case PHY_INTERFACE_MODE_RGMII_ID:
> +		return data->ops->set_to_rgmii(dev, 0, 0);
> +	case PHY_INTERFACE_MODE_RGMII_RXID:
> +		return data->ops->set_to_rgmii(dev, tx_delay, 0);
> +	case PHY_INTERFACE_MODE_RGMII_TXID:
> +		return data->ops->set_to_rgmii(dev, 0, rx_delay);
> +	case PHY_INTERFACE_MODE_RMII:
> +		return data->ops->set_to_rmii(dev);
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int eqos_set_tx_clk_speed_rk(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	return data->ops->set_gmac_speed(dev);
> +}
> +
> +static ulong eqos_get_tick_clk_rate_rk(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +
> +	return clk_get_rate(&eqos->clk_master_bus);
> +}
> +
> +static struct eqos_ops eqos_rockchip_ops = {
> +	.eqos_inval_desc = eqos_inval_desc_generic,
> +	.eqos_flush_desc = eqos_flush_desc_generic,
> +	.eqos_inval_buffer = eqos_inval_buffer_generic,
> +	.eqos_flush_buffer = eqos_flush_buffer_generic,
> +	.eqos_probe_resources = eqos_probe_resources_rk,
> +	.eqos_remove_resources = eqos_remove_resources_rk,
> +	.eqos_stop_resets = eqos_stop_resets_rk,
> +	.eqos_start_resets = eqos_start_resets_rk,
> +	.eqos_stop_clks = eqos_stop_clks_rk,
> +	.eqos_start_clks = eqos_start_clks_rk,
> +	.eqos_calibrate_pads = eqos_null_ops,
> +	.eqos_disable_calibration = eqos_null_ops,
> +	.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_rk,
> +	.eqos_get_enetaddr = eqos_null_ops,
> +	.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_rk,
> +};
> +
> +struct eqos_config eqos_rockchip_config = {
> +	.reg_access_always_ok = false,
> +	.mdio_wait = 10,
> +	.swr_wait = 50,
> +	.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
> +	.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_100_150,
> +	.axi_bus_width = EQOS_AXI_WIDTH_64,
> +	.interface = dev_read_phy_mode,
> +	.ops = &eqos_rockchip_ops,
> +};

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 5/7] net: dwc_eth_qos_rockchip: Add support for RK3588
  2023-08-07  0:08 ` [PATCH 5/7] net: dwc_eth_qos_rockchip: Add support for RK3588 Jonas Karlman
@ 2023-09-27  3:01   ` Kever Yang
  2023-10-01 19:26     ` Sebastian Reichel
  2023-10-06 14:43   ` Tom Fitzhenry
  1 sibling, 1 reply; 22+ messages in thread
From: Kever Yang @ 2023-09-27  3:01 UTC (permalink / raw)
  To: Jonas Karlman, Simon Glass, Philipp Tomsich, Joe Hershberger,
	Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot,
	David Wu, Sebastian Reichel, Benjamin Gaignard


On 2023/8/7 08:08, Jonas Karlman wrote:
> Add rk_gmac_ops and other special handling that is needed for GMAC to
> work on RK3588.
>
> rk_gmac_ops was ported from linux commits:
> 2f2b60a0ec28 ("net: ethernet: stmmac: dwmac-rk: Add gmac support for rk3588")
> 88619e77b33d ("net: stmmac: rk3588: Allow multiple gmac controller")
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever
> ---
> Cc: David Wu <david.wu@rock-chips.com>
> Cc: Sebastian Reichel <sebastian.reichel@collabora.com>
> Cc: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
>   drivers/net/dwc_eth_qos.c          |   4 +
>   drivers/net/dwc_eth_qos_rockchip.c | 182 ++++++++++++++++++++++++++++-
>   2 files changed, 182 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index 9fb98a2c3c74..dc04416865dd 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -1712,6 +1712,10 @@ static const struct udevice_id eqos_ids[] = {
>   		.compatible = "rockchip,rk3568-gmac",
>   		.data = (ulong)&eqos_rockchip_config
>   	},
> +	{
> +		.compatible = "rockchip,rk3588-gmac",
> +		.data = (ulong)&eqos_rockchip_config
> +	},
>   #endif
>   #if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
>   	{
> diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c
> index c8abe351fc3e..34020496bde6 100644
> --- a/drivers/net/dwc_eth_qos_rockchip.c
> +++ b/drivers/net/dwc_eth_qos_rockchip.c
> @@ -20,6 +20,7 @@ struct rk_gmac_ops {
>   			    int tx_delay, int rx_delay);
>   	int (*set_to_rmii)(struct udevice *dev);
>   	int (*set_gmac_speed)(struct udevice *dev);
> +	void (*set_clock_selection)(struct udevice *dev, bool enable);
>   	u32 regs[3];
>   };
>   
> @@ -27,7 +28,9 @@ struct rockchip_platform_data {
>   	struct reset_ctl_bulk resets;
>   	const struct rk_gmac_ops *ops;
>   	int id;
> +	bool clock_input;
>   	struct regmap *grf;
> +	struct regmap *php_grf;
>   };
>   
>   #define HIWORD_UPDATE(val, mask, shift) \
> @@ -121,6 +124,137 @@ static int rk3568_set_gmac_speed(struct udevice *dev)
>   	return 0;
>   }
>   
> +/* sys_grf */
> +#define RK3588_GRF_GMAC_CON7			0x031c
> +#define RK3588_GRF_GMAC_CON8			0x0320
> +#define RK3588_GRF_GMAC_CON9			0x0324
> +
> +#define RK3588_GMAC_RXCLK_DLY_ENABLE(id)	GRF_BIT(2 * (id) + 3)
> +#define RK3588_GMAC_RXCLK_DLY_DISABLE(id)	GRF_CLR_BIT(2 * (id) + 3)
> +#define RK3588_GMAC_TXCLK_DLY_ENABLE(id)	GRF_BIT(2 * (id) + 2)
> +#define RK3588_GMAC_TXCLK_DLY_DISABLE(id)	GRF_CLR_BIT(2 * (id) + 2)
> +
> +#define RK3588_GMAC_CLK_RX_DL_CFG(val)		HIWORD_UPDATE(val, 0xFF, 8)
> +#define RK3588_GMAC_CLK_TX_DL_CFG(val)		HIWORD_UPDATE(val, 0xFF, 0)
> +
> +/* php_grf */
> +#define RK3588_GRF_GMAC_CON0			0x0008
> +#define RK3588_GRF_CLK_CON1			0x0070
> +
> +#define RK3588_GMAC_PHY_INTF_SEL_RGMII(id)	\
> +	(GRF_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_CLR_BIT(5 + (id) * 6))
> +#define RK3588_GMAC_PHY_INTF_SEL_RMII(id)	\
> +	(GRF_CLR_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_BIT(5 + (id) * 6))
> +
> +#define RK3588_GMAC_CLK_RMII_MODE(id)		GRF_BIT(5 * (id))
> +#define RK3588_GMAC_CLK_RGMII_MODE(id)		GRF_CLR_BIT(5 * (id))
> +
> +#define RK3588_GMAC_CLK_SELET_CRU(id)		GRF_BIT(5 * (id) + 4)
> +#define RK3588_GMAC_CLK_SELET_IO(id)		GRF_CLR_BIT(5 * (id) + 4)
> +
> +#define RK3588_GMAC_CLK_RMII_DIV2(id)		GRF_BIT(5 * (id) + 2)
> +#define RK3588_GMAC_CLK_RMII_DIV20(id)		GRF_CLR_BIT(5 * (id) + 2)
> +
> +#define RK3588_GMAC_CLK_RGMII_DIV1(id)		\
> +			(GRF_CLR_BIT(5 * (id) + 2) | GRF_CLR_BIT(5 * (id) + 3))
> +#define RK3588_GMAC_CLK_RGMII_DIV5(id)		\
> +			(GRF_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3))
> +#define RK3588_GMAC_CLK_RGMII_DIV50(id)		\
> +			(GRF_CLR_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3))
> +
> +#define RK3588_GMAC_CLK_RMII_GATE(id)		GRF_BIT(5 * (id) + 1)
> +#define RK3588_GMAC_CLK_RMII_NOGATE(id)		GRF_CLR_BIT(5 * (id) + 1)
> +
> +static int rk3588_set_to_rgmii(struct udevice *dev,
> +			       int tx_delay, int rx_delay)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +	u32 offset_con, id = data->id;
> +
> +	offset_con = data->id == 1 ? RK3588_GRF_GMAC_CON9 :
> +				     RK3588_GRF_GMAC_CON8;
> +
> +	regmap_write(data->php_grf, RK3588_GRF_GMAC_CON0,
> +		     RK3588_GMAC_PHY_INTF_SEL_RGMII(id));
> +
> +	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1,
> +		     RK3588_GMAC_CLK_RGMII_MODE(id));
> +
> +	regmap_write(data->grf, RK3588_GRF_GMAC_CON7,
> +		     RK3588_GMAC_RXCLK_DLY_ENABLE(id) |
> +		     RK3588_GMAC_TXCLK_DLY_ENABLE(id));
> +
> +	regmap_write(data->grf, offset_con,
> +		     RK3588_GMAC_CLK_RX_DL_CFG(rx_delay) |
> +		     RK3588_GMAC_CLK_TX_DL_CFG(tx_delay));
> +
> +	return 0;
> +}
> +
> +static int rk3588_set_to_rmii(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	regmap_write(data->php_grf, RK3588_GRF_GMAC_CON0,
> +		     RK3588_GMAC_PHY_INTF_SEL_RMII(data->id));
> +
> +	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1,
> +		     RK3588_GMAC_CLK_RMII_MODE(data->id));
> +
> +	return 0;
> +}
> +
> +static int rk3588_set_gmac_speed(struct udevice *dev)
> +{
> +	struct eqos_priv *eqos = dev_get_priv(dev);
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +	u32 val = 0, id = data->id;
> +
> +	switch (eqos->phy->speed) {
> +	case SPEED_10:
> +		if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII)
> +			val = RK3588_GMAC_CLK_RMII_DIV20(id);
> +		else
> +			val = RK3588_GMAC_CLK_RGMII_DIV50(id);
> +		break;
> +	case SPEED_100:
> +		if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII)
> +			val = RK3588_GMAC_CLK_RMII_DIV2(id);
> +		else
> +			val = RK3588_GMAC_CLK_RGMII_DIV5(id);
> +		break;
> +	case SPEED_1000:
> +		if (pdata->phy_interface != PHY_INTERFACE_MODE_RMII)
> +			val = RK3588_GMAC_CLK_RGMII_DIV1(id);
> +		else
> +			return -EINVAL;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1, val);
> +
> +	return 0;
> +}
> +
> +static void rk3588_set_clock_selection(struct udevice *dev, bool enable)
> +{
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	u32 val = data->clock_input ? RK3588_GMAC_CLK_SELET_IO(data->id) :
> +				      RK3588_GMAC_CLK_SELET_CRU(data->id);
> +
> +	val |= enable ? RK3588_GMAC_CLK_RMII_NOGATE(data->id) :
> +			RK3588_GMAC_CLK_RMII_GATE(data->id);
> +
> +	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1, val);
> +}
> +
>   static const struct rk_gmac_ops rk_gmac_ops[] = {
>   	{
>   		.compatible = "rockchip,rk3568-gmac",
> @@ -133,6 +267,18 @@ static const struct rk_gmac_ops rk_gmac_ops[] = {
>   			0x0, /* sentinel */
>   		},
>   	},
> +	{
> +		.compatible = "rockchip,rk3588-gmac",
> +		.set_to_rgmii = rk3588_set_to_rgmii,
> +		.set_to_rmii = rk3588_set_to_rmii,
> +		.set_gmac_speed = rk3588_set_gmac_speed,
> +		.set_clock_selection = rk3588_set_clock_selection,
> +		.regs = {
> +			0xfe1b0000, /* gmac0 */
> +			0xfe1c0000, /* gmac1 */
> +			0x0, /* sentinel */
> +		},
> +	},
>   	{ }
>   };
>   
> @@ -154,6 +300,7 @@ static int eqos_probe_resources_rk(struct udevice *dev)
>   	struct eqos_priv *eqos = dev_get_priv(dev);
>   	struct eth_pdata *pdata = dev_get_plat(dev);
>   	struct rockchip_platform_data *data;
> +	const char *clock_in_out;
>   	int reset_flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
>   	int ret;
>   
> @@ -191,6 +338,16 @@ static int eqos_probe_resources_rk(struct udevice *dev)
>   		goto err_free;
>   	}
>   
> +	if (device_is_compatible(dev, "rockchip,rk3588-gmac")) {
> +		data->php_grf =
> +			syscon_regmap_lookup_by_phandle(dev, "rockchip,php-grf");
> +		if (IS_ERR(data->php_grf)) {
> +			dev_err(dev, "Missing rockchip,php-grf property\n");
> +			ret = -EINVAL;
> +			goto err_free;
> +		}
> +	}
> +
>   	ret = reset_get_bulk(dev, &data->resets);
>   	if (ret < 0)
>   		goto err_free;
> @@ -203,12 +360,20 @@ static int eqos_probe_resources_rk(struct udevice *dev)
>   		goto err_release_resets;
>   	}
>   
> -	ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
> -	if (ret) {
> -		dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
> -		goto err_free_clk_master_bus;
> +	if (device_is_compatible(dev, "rockchip,rk3568-gmac")) {
> +		ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
> +		if (ret) {
> +			dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
> +			goto err_free_clk_master_bus;
> +		}
>   	}
>   
> +	clock_in_out = dev_read_string(dev, "clock_in_out");
> +	if (clock_in_out && !strcmp(clock_in_out, "input"))
> +		data->clock_input = true;
> +	else
> +		data->clock_input = false;
> +
>   	if (dev_read_bool(dev, "snps,reset-active-low"))
>   		reset_flags |= GPIOD_ACTIVE_LOW;
>   
> @@ -264,6 +429,12 @@ static int eqos_start_resets_rk(struct udevice *dev)
>   
>   static int eqos_stop_clks_rk(struct udevice *dev)
>   {
> +	struct eth_pdata *pdata = dev_get_plat(dev);
> +	struct rockchip_platform_data *data = pdata->priv_pdata;
> +
> +	if (data->ops->set_clock_selection)
> +		data->ops->set_clock_selection(dev, false);
> +
>   	return 0;
>   }
>   
> @@ -284,6 +455,9 @@ static int eqos_start_clks_rk(struct udevice *dev)
>   		udelay(eqos->reset_delays[2]);
>   	}
>   
> +	if (data->ops->set_clock_selection)
> +		data->ops->set_clock_selection(dev, true);
> +
>   	tx_delay = dev_read_u32_default(dev, "tx_delay", 0x30);
>   	rx_delay = dev_read_u32_default(dev, "rx_delay", 0x10);
>   

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 6/7] configs: rockchip: Enable ethernet driver on RK356x boards
  2023-08-07  0:08 ` [PATCH 6/7] configs: rockchip: Enable ethernet driver on RK356x boards Jonas Karlman
@ 2023-09-27  3:01   ` Kever Yang
  0 siblings, 0 replies; 22+ messages in thread
From: Kever Yang @ 2023-09-27  3:01 UTC (permalink / raw)
  To: Jonas Karlman, Simon Glass, Philipp Tomsich, Joseph Chen,
	Tianling Shen, Nicolas Frattaroli, Jagan Teki, Akash Gajjar
  Cc: Eugen Hristev, Frank Wunderlich, u-boot


On 2023/8/7 08:08, Jonas Karlman wrote:
> Enable DWC_ETH_QOS_ROCKCHIP and related PHY driver on RK356x boards that
> have an enabled gmac node.
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever
> ---
>   configs/evb-rk3568_defconfig              | 5 +++--
>   configs/nanopi-r5s-rk3568_defconfig       | 3 +++
>   configs/odroid-m1-rk3568_defconfig        | 3 +++
>   configs/quartz64-a-rk3566_defconfig       | 3 +++
>   configs/quartz64-b-rk3566_defconfig       | 3 +++
>   configs/radxa-cm3-io-rk3566_defconfig     | 6 ++++--
>   configs/rock-3a-rk3568_defconfig          | 5 +++--
>   configs/soquartz-blade-rk3566_defconfig   | 3 +++
>   configs/soquartz-cm4-rk3566_defconfig     | 3 +++
>   configs/soquartz-model-a-rk3566_defconfig | 3 +++
>   10 files changed, 31 insertions(+), 6 deletions(-)
>
> diff --git a/configs/evb-rk3568_defconfig b/configs/evb-rk3568_defconfig
> index 5f3fab7304c2..43431ecdfed6 100644
> --- a/configs/evb-rk3568_defconfig
> +++ b/configs/evb-rk3568_defconfig
> @@ -58,8 +58,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
>   CONFIG_MMC_SDHCI=y
>   CONFIG_MMC_SDHCI_SDMA=y
>   CONFIG_MMC_SDHCI_ROCKCHIP=y
> -CONFIG_ETH_DESIGNWARE=y
> -CONFIG_GMAC_ROCKCHIP=y
> +CONFIG_PHY_REALTEK=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_DM_PMIC=y
>   CONFIG_PMIC_RK8XX=y
>   CONFIG_REGULATOR_RK8XX=y
> diff --git a/configs/nanopi-r5s-rk3568_defconfig b/configs/nanopi-r5s-rk3568_defconfig
> index c278ce083d9a..2736d382a352 100644
> --- a/configs/nanopi-r5s-rk3568_defconfig
> +++ b/configs/nanopi-r5s-rk3568_defconfig
> @@ -65,6 +65,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
>   CONFIG_MMC_SDHCI=y
>   CONFIG_MMC_SDHCI_SDMA=y
>   CONFIG_MMC_SDHCI_ROCKCHIP=y
> +CONFIG_PHY_REALTEK=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_RTL8169=y
>   CONFIG_NVME_PCI=y
>   CONFIG_PCIE_DW_ROCKCHIP=y
> diff --git a/configs/odroid-m1-rk3568_defconfig b/configs/odroid-m1-rk3568_defconfig
> index 3dda5c1f9170..96b4e9ecdaff 100644
> --- a/configs/odroid-m1-rk3568_defconfig
> +++ b/configs/odroid-m1-rk3568_defconfig
> @@ -82,6 +82,9 @@ CONFIG_SF_DEFAULT_BUS=4
>   CONFIG_SPI_FLASH_SFDP_SUPPORT=y
>   CONFIG_SPI_FLASH_MACRONIX=y
>   CONFIG_SPI_FLASH_MTD=y
> +CONFIG_PHY_REALTEK=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_NVME_PCI=y
>   CONFIG_PCIE_DW_ROCKCHIP=y
>   CONFIG_PHY_ROCKCHIP_INNO_USB2=y
> diff --git a/configs/quartz64-a-rk3566_defconfig b/configs/quartz64-a-rk3566_defconfig
> index 6853cd6c44b4..bf4d4cd2b8ed 100644
> --- a/configs/quartz64-a-rk3566_defconfig
> +++ b/configs/quartz64-a-rk3566_defconfig
> @@ -81,6 +81,9 @@ CONFIG_SPI_FLASH_SFDP_SUPPORT=y
>   CONFIG_SPI_FLASH_GIGADEVICE=y
>   CONFIG_SPI_FLASH_MACRONIX=y
>   CONFIG_SPI_FLASH_WINBOND=y
> +CONFIG_PHY_MOTORCOMM=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_NVME_PCI=y
>   CONFIG_PCIE_DW_ROCKCHIP=y
>   CONFIG_PHY_ROCKCHIP_INNO_USB2=y
> diff --git a/configs/quartz64-b-rk3566_defconfig b/configs/quartz64-b-rk3566_defconfig
> index aa29fff14643..358687ab5d7f 100644
> --- a/configs/quartz64-b-rk3566_defconfig
> +++ b/configs/quartz64-b-rk3566_defconfig
> @@ -79,6 +79,9 @@ CONFIG_SPI_FLASH_SFDP_SUPPORT=y
>   CONFIG_SPI_FLASH_GIGADEVICE=y
>   CONFIG_SPI_FLASH_MACRONIX=y
>   CONFIG_SPI_FLASH_WINBOND=y
> +CONFIG_PHY_REALTEK=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_NVME_PCI=y
>   CONFIG_PCIE_DW_ROCKCHIP=y
>   CONFIG_PHY_ROCKCHIP_INNO_USB2=y
> diff --git a/configs/radxa-cm3-io-rk3566_defconfig b/configs/radxa-cm3-io-rk3566_defconfig
> index f89777184ceb..4b606dcb8e94 100644
> --- a/configs/radxa-cm3-io-rk3566_defconfig
> +++ b/configs/radxa-cm3-io-rk3566_defconfig
> @@ -47,6 +47,7 @@ CONFIG_CMD_REGULATOR=y
>   CONFIG_SPL_OF_CONTROL=y
>   CONFIG_OF_LIVE=y
>   CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
> +CONFIG_SPL_DM_SEQ_ALIAS=y
>   CONFIG_SPL_REGMAP=y
>   CONFIG_SPL_SYSCON=y
>   CONFIG_SPL_CLK=y
> @@ -59,8 +60,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
>   CONFIG_MMC_SDHCI=y
>   CONFIG_MMC_SDHCI_SDMA=y
>   CONFIG_MMC_SDHCI_ROCKCHIP=y
> -CONFIG_ETH_DESIGNWARE=y
> -CONFIG_GMAC_ROCKCHIP=y
> +CONFIG_PHY_REALTEK=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_PHY_ROCKCHIP_INNO_USB2=y
>   CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
>   CONFIG_SPL_PINCTRL=y
> diff --git a/configs/rock-3a-rk3568_defconfig b/configs/rock-3a-rk3568_defconfig
> index 409aa95acf06..28d157dbd7a7 100644
> --- a/configs/rock-3a-rk3568_defconfig
> +++ b/configs/rock-3a-rk3568_defconfig
> @@ -77,8 +77,9 @@ CONFIG_SF_DEFAULT_BUS=4
>   CONFIG_SPI_FLASH_SFDP_SUPPORT=y
>   CONFIG_SPI_FLASH_MACRONIX=y
>   CONFIG_SPI_FLASH_XTX=y
> -CONFIG_ETH_DESIGNWARE=y
> -CONFIG_GMAC_ROCKCHIP=y
> +CONFIG_PHY_REALTEK=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_NVME_PCI=y
>   CONFIG_PCIE_DW_ROCKCHIP=y
>   CONFIG_PHY_ROCKCHIP_INNO_USB2=y
> diff --git a/configs/soquartz-blade-rk3566_defconfig b/configs/soquartz-blade-rk3566_defconfig
> index 181c284e73e9..1d993a5b71b0 100644
> --- a/configs/soquartz-blade-rk3566_defconfig
> +++ b/configs/soquartz-blade-rk3566_defconfig
> @@ -67,6 +67,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
>   CONFIG_MMC_SDHCI=y
>   CONFIG_MMC_SDHCI_SDMA=y
>   CONFIG_MMC_SDHCI_ROCKCHIP=y
> +CONFIG_PHY_MOTORCOMM=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_NVME_PCI=y
>   CONFIG_PCIE_DW_ROCKCHIP=y
>   CONFIG_PHY_ROCKCHIP_INNO_USB2=y
> diff --git a/configs/soquartz-cm4-rk3566_defconfig b/configs/soquartz-cm4-rk3566_defconfig
> index 7e290351477e..f01aa7269a1c 100644
> --- a/configs/soquartz-cm4-rk3566_defconfig
> +++ b/configs/soquartz-cm4-rk3566_defconfig
> @@ -67,6 +67,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
>   CONFIG_MMC_SDHCI=y
>   CONFIG_MMC_SDHCI_SDMA=y
>   CONFIG_MMC_SDHCI_ROCKCHIP=y
> +CONFIG_PHY_MOTORCOMM=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_NVME_PCI=y
>   CONFIG_PCIE_DW_ROCKCHIP=y
>   CONFIG_PHY_ROCKCHIP_INNO_USB2=y
> diff --git a/configs/soquartz-model-a-rk3566_defconfig b/configs/soquartz-model-a-rk3566_defconfig
> index a0884a797d58..2f3145745d58 100644
> --- a/configs/soquartz-model-a-rk3566_defconfig
> +++ b/configs/soquartz-model-a-rk3566_defconfig
> @@ -68,6 +68,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
>   CONFIG_MMC_SDHCI=y
>   CONFIG_MMC_SDHCI_SDMA=y
>   CONFIG_MMC_SDHCI_ROCKCHIP=y
> +CONFIG_PHY_MOTORCOMM=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_NVME_PCI=y
>   CONFIG_PCIE_DW_ROCKCHIP=y
>   CONFIG_PHY_ROCKCHIP_INNO_USB2=y

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 7/7] configs: rockchip: Enable ethernet driver on RK3588 boards
  2023-08-07  0:08 ` [PATCH 7/7] configs: rockchip: Enable ethernet driver on RK3588 boards Jonas Karlman
@ 2023-09-27  3:01   ` Kever Yang
  0 siblings, 0 replies; 22+ messages in thread
From: Kever Yang @ 2023-09-27  3:01 UTC (permalink / raw)
  To: Jonas Karlman, Simon Glass, Philipp Tomsich, Jagan Teki, Eugen Hristev
  Cc: Frank Wunderlich, Nicolas Frattaroli, u-boot


On 2023/8/7 08:08, Jonas Karlman wrote:
> Enable DWC_ETH_QOS_ROCKCHIP and related PHY driver on RK3588 boards that
> have an enabled gmac node and drop ETH_DESIGNWARE and GMAC_ROCKCHIP for
> remaining RK3588 boards.
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever
> ---
>   configs/evb-rk3588_defconfig      | 5 +++--
>   configs/neu6a-io-rk3588_defconfig | 2 --
>   configs/neu6b-io-rk3588_defconfig | 2 --
>   configs/rock5a-rk3588s_defconfig  | 6 +++---
>   4 files changed, 6 insertions(+), 9 deletions(-)
>
> diff --git a/configs/evb-rk3588_defconfig b/configs/evb-rk3588_defconfig
> index f49c2ca686a8..0b7b4f2f627a 100644
> --- a/configs/evb-rk3588_defconfig
> +++ b/configs/evb-rk3588_defconfig
> @@ -58,8 +58,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
>   CONFIG_MMC_SDHCI=y
>   CONFIG_MMC_SDHCI_SDMA=y
>   CONFIG_MMC_SDHCI_ROCKCHIP=y
> -CONFIG_ETH_DESIGNWARE=y
> -CONFIG_GMAC_ROCKCHIP=y
> +CONFIG_PHY_REALTEK=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_REGULATOR_PWM=y
>   CONFIG_PWM_ROCKCHIP=y
>   CONFIG_SPL_RAM=y
> diff --git a/configs/neu6a-io-rk3588_defconfig b/configs/neu6a-io-rk3588_defconfig
> index 09729a0ea429..d5301c630b2a 100644
> --- a/configs/neu6a-io-rk3588_defconfig
> +++ b/configs/neu6a-io-rk3588_defconfig
> @@ -53,8 +53,6 @@ CONFIG_MMC_DW_ROCKCHIP=y
>   CONFIG_MMC_SDHCI=y
>   CONFIG_MMC_SDHCI_SDMA=y
>   CONFIG_MMC_SDHCI_ROCKCHIP=y
> -CONFIG_ETH_DESIGNWARE=y
> -CONFIG_GMAC_ROCKCHIP=y
>   CONFIG_REGULATOR_PWM=y
>   CONFIG_PWM_ROCKCHIP=y
>   CONFIG_SPL_RAM=y
> diff --git a/configs/neu6b-io-rk3588_defconfig b/configs/neu6b-io-rk3588_defconfig
> index c7bc3b1965f0..b13c9b5db1b0 100644
> --- a/configs/neu6b-io-rk3588_defconfig
> +++ b/configs/neu6b-io-rk3588_defconfig
> @@ -53,8 +53,6 @@ CONFIG_MMC_DW_ROCKCHIP=y
>   CONFIG_MMC_SDHCI=y
>   CONFIG_MMC_SDHCI_SDMA=y
>   CONFIG_MMC_SDHCI_ROCKCHIP=y
> -CONFIG_ETH_DESIGNWARE=y
> -CONFIG_GMAC_ROCKCHIP=y
>   CONFIG_REGULATOR_PWM=y
>   CONFIG_PWM_ROCKCHIP=y
>   CONFIG_SPL_RAM=y
> diff --git a/configs/rock5a-rk3588s_defconfig b/configs/rock5a-rk3588s_defconfig
> index 6cbd9817c528..bccdb1e3ecd6 100644
> --- a/configs/rock5a-rk3588s_defconfig
> +++ b/configs/rock5a-rk3588s_defconfig
> @@ -11,7 +11,6 @@ CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000
>   CONFIG_DEFAULT_DEVICE_TREE="rk3588s-rock-5a"
>   CONFIG_ROCKCHIP_RK3588=y
>   CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y
> -CONFIG_SPL_MMC=y
>   CONFIG_SPL_SERIAL=y
>   CONFIG_SPL_STACK_R_ADDR=0x1000000
>   CONFIG_TARGET_ROCK5A_RK3588=y
> @@ -59,8 +58,9 @@ CONFIG_MMC_DW_ROCKCHIP=y
>   CONFIG_MMC_SDHCI=y
>   CONFIG_MMC_SDHCI_SDMA=y
>   CONFIG_MMC_SDHCI_ROCKCHIP=y
> -CONFIG_ETH_DESIGNWARE=y
> -CONFIG_GMAC_ROCKCHIP=y
> +CONFIG_PHY_REALTEK=y
> +CONFIG_DWC_ETH_QOS=y
> +CONFIG_DWC_ETH_QOS_ROCKCHIP=y
>   CONFIG_SPL_PINCTRL=y
>   CONFIG_REGULATOR_PWM=y
>   CONFIG_PWM_ROCKCHIP=y

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568
  2023-08-15 13:12   ` David Wu
@ 2023-10-01 19:04     ` Jonas Karlman
  0 siblings, 0 replies; 22+ messages in thread
From: Jonas Karlman @ 2023-10-01 19:04 UTC (permalink / raw)
  To: David Wu, Kever Yang, Simon Glass, Philipp Tomsich,
	Joe Hershberger, Ramon Fried
  Cc: Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli, u-boot,
	Ezequiel Garcia

Hi David,

On 2023-08-15 15:12, David Wu wrote:
> Hi Jonas,
> 
> Thank you for your help.
> 
> 在 2023/8/7 08:08, Jonas Karlman 写道:
>> Add a new glue driver for Rockchip SoCs, i.e RK3568, with a GMAC based
>> on Synopsys DWC Ethernet QoS IP.
>>
>> rk_gmac_ops was ported from linux commit:
>> 3bb3d6b1c195 ("net: stmmac: Add RK3566/RK3568 SoC support")
>>
>> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
>> ---
>> Cc: David Wu <david.wu@rock-chips.com>
>> Cc: Ezequiel Garcia <ezequiel@collabora.com>
>> ---
>>   drivers/net/Kconfig                |   8 +
>>   drivers/net/Makefile               |   1 +
>>   drivers/net/dwc_eth_qos.c          |   8 +-
>>   drivers/net/dwc_eth_qos.h          |   2 +
>>   drivers/net/dwc_eth_qos_rockchip.c | 348 +++++++++++++++++++++++++++++
>>   5 files changed, 365 insertions(+), 2 deletions(-)
>>   create mode 100644 drivers/net/dwc_eth_qos_rockchip.c
>>
>> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
>> index 0ed39a61e4de..29304fd77759 100644
>> --- a/drivers/net/Kconfig
>> +++ b/drivers/net/Kconfig
>> @@ -225,6 +225,14 @@ config DWC_ETH_QOS_IMX
>>   	  The Synopsys Designware Ethernet QOS IP block with the specific
>>   	  configuration used in IMX soc.
>>   
>> +config DWC_ETH_QOS_ROCKCHIP
>> +	bool "Synopsys DWC Ethernet QOS device support for Rockchip SoCs"
>> +	depends on DWC_ETH_QOS
>> +	select DM_ETH_PHY
>> +	help
>> +	  The Synopsys Designware Ethernet QOS IP block with specific
>> +	  configuration used in Rockchip SoCs.
>> +
>>   config DWC_ETH_QOS_STM32
>>   	bool "Synopsys DWC Ethernet QOS device support for STM32"
>>   	depends on DWC_ETH_QOS
>> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
>> index d4af253b6f28..1d444f5b4a69 100644
>> --- a/drivers/net/Makefile
>> +++ b/drivers/net/Makefile
>> @@ -20,6 +20,7 @@ obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
>>   obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
>>   obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
>>   obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o
>> +obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o
>>   obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
>>   obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o
>>   obj-$(CONFIG_E1000) += e1000.o
>> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
>> index 24fb3fac1f12..9fb98a2c3c74 100644
>> --- a/drivers/net/dwc_eth_qos.c
>> +++ b/drivers/net/dwc_eth_qos.c
>> @@ -1707,7 +1707,12 @@ static const struct udevice_id eqos_ids[] = {
>>   		.data = (ulong)&eqos_imx_config
>>   	},
>>   #endif
>> -
>> +#if IS_ENABLED(CONFIG_DWC_ETH_QOS_ROCKCHIP)
>> +	{
>> +		.compatible = "rockchip,rk3568-gmac",
>> +		.data = (ulong)&eqos_rockchip_config
>> +	},
>> +#endif
> 
> If this compatible could move to dwc_eth_qos_rockchip.c, it is better,
> we have other SoCs  that also use this driver in the feature,  and it 
> must increase
> this array all the time for new SoCs later, it will be better only change
> dwc_eth_qos_rockchip.c, we don't need to change the current file.

Agree that this could be improved, not sure how we should/could do it,
and is something that can be done in a follow-up series.

Will leave as-is for v2.

Regards,
Jonas

> 
>>   #if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
>>   	{
>>   		.compatible = "qcom,qcs404-ethqos",
>> @@ -1720,7 +1725,6 @@ static const struct udevice_id eqos_ids[] = {
>>   		.data = (ulong)&eqos_jh7110_config
>>   	},
>>   #endif
>> -
>>   	{ }
>>   };
>>   
>> diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
>> index 06a082da72ef..e3222e1e17e5 100644
>> --- a/drivers/net/dwc_eth_qos.h
>> +++ b/drivers/net/dwc_eth_qos.h
>> @@ -82,6 +82,7 @@ struct eqos_mac_regs {
>>   #define EQOS_MAC_MDIO_ADDRESS_PA_SHIFT			21
>>   #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT			16
>>   #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT			8
>> +#define EQOS_MAC_MDIO_ADDRESS_CR_100_150		1
>>   #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)
>> @@ -287,5 +288,6 @@ void eqos_flush_buffer_generic(void *buf, size_t size);
>>   int eqos_null_ops(struct udevice *dev);
>>   
>>   extern struct eqos_config eqos_imx_config;
>> +extern struct eqos_config eqos_rockchip_config;
>>   extern struct eqos_config eqos_qcom_config;
>>   extern struct eqos_config eqos_jh7110_config;
>> diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c
>> new file mode 100644
>> index 000000000000..c8abe351fc3e
>> --- /dev/null
>> +++ b/drivers/net/dwc_eth_qos_rockchip.c
>> @@ -0,0 +1,348 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <dm/device_compat.h>
>> +#include <net.h>
>> +#include <phy.h>
>> +#include <regmap.h>
>> +#include <reset.h>
>> +#include <syscon.h>
>> +#include <asm/gpio.h>
>> +#include <linux/delay.h>
>> +
>> +#include "dwc_eth_qos.h"
>> +
>> +struct rk_gmac_ops {
>> +	const char *compatible;
>> +	int (*set_to_rgmii)(struct udevice *dev,
>> +			    int tx_delay, int rx_delay);
>> +	int (*set_to_rmii)(struct udevice *dev);
>> +	int (*set_gmac_speed)(struct udevice *dev);
>> +	u32 regs[3];
>> +};
>> +
>> +struct rockchip_platform_data {
>> +	struct reset_ctl_bulk resets;
>> +	const struct rk_gmac_ops *ops;
>> +	int id;
>> +	struct regmap *grf;
>> +};
>> +
>> +#define HIWORD_UPDATE(val, mask, shift) \
>> +		((val) << (shift) | (mask) << ((shift) + 16))
>> +
>> +#define GRF_BIT(nr)	(BIT(nr) | BIT((nr) + 16))
>> +#define GRF_CLR_BIT(nr)	(BIT((nr) + 16))
>> +
>> +#define RK3568_GRF_GMAC0_CON0		0x0380
>> +#define RK3568_GRF_GMAC0_CON1		0x0384
>> +#define RK3568_GRF_GMAC1_CON0		0x0388
>> +#define RK3568_GRF_GMAC1_CON1		0x038c
>> +
>> +/* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */
>> +#define RK3568_GMAC_PHY_INTF_SEL_RGMII	\
>> +		(GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
>> +#define RK3568_GMAC_PHY_INTF_SEL_RMII	\
>> +		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
>> +#define RK3568_GMAC_FLOW_CTRL			GRF_BIT(3)
>> +#define RK3568_GMAC_FLOW_CTRL_CLR		GRF_CLR_BIT(3)
>> +#define RK3568_GMAC_RXCLK_DLY_ENABLE		GRF_BIT(1)
>> +#define RK3568_GMAC_RXCLK_DLY_DISABLE		GRF_CLR_BIT(1)
>> +#define RK3568_GMAC_TXCLK_DLY_ENABLE		GRF_BIT(0)
>> +#define RK3568_GMAC_TXCLK_DLY_DISABLE		GRF_CLR_BIT(0)
>> +
>> +/* RK3568_GRF_GMAC0_CON0 && RK3568_GRF_GMAC1_CON0 */
>> +#define RK3568_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
>> +#define RK3568_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
>> +
>> +static int rk3568_set_to_rgmii(struct udevice *dev,
>> +			       int tx_delay, int rx_delay)
>> +{
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +	u32 con0, con1;
>> +
>> +	con0 = (data->id == 1) ? RK3568_GRF_GMAC1_CON0 :
>> +				 RK3568_GRF_GMAC0_CON0;
>> +	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
>> +				 RK3568_GRF_GMAC0_CON1;
>> +
>> +	regmap_write(data->grf, con0,
>> +		     RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) |
>> +		     RK3568_GMAC_CLK_TX_DL_CFG(tx_delay));
>> +
>> +	regmap_write(data->grf, con1,
>> +		     RK3568_GMAC_PHY_INTF_SEL_RGMII |
>> +		     RK3568_GMAC_RXCLK_DLY_ENABLE |
>> +		     RK3568_GMAC_TXCLK_DLY_ENABLE);
>> +
>> +	return 0;
>> +}
>> +
>> +static int rk3568_set_to_rmii(struct udevice *dev)
>> +{
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +	u32 con1;
>> +
>> +	con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
>> +				 RK3568_GRF_GMAC0_CON1;
>> +	regmap_write(data->grf, con1, RK3568_GMAC_PHY_INTF_SEL_RMII);
>> +
>> +	return 0;
>> +}
>> +
>> +static int rk3568_set_gmac_speed(struct udevice *dev)
>> +{
>> +	struct eqos_priv *eqos = dev_get_priv(dev);
>> +	ulong rate;
>> +	int ret;
>> +
>> +	switch (eqos->phy->speed) {
>> +	case SPEED_10:
>> +		rate = 2500000;
>> +		break;
>> +	case SPEED_100:
>> +		rate = 25000000;
>> +		break;
>> +	case SPEED_1000:
>> +		rate = 125000000;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = clk_set_rate(&eqos->clk_tx, rate);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct rk_gmac_ops rk_gmac_ops[] = {
>> +	{
>> +		.compatible = "rockchip,rk3568-gmac",
>> +		.set_to_rgmii = rk3568_set_to_rgmii,
>> +		.set_to_rmii = rk3568_set_to_rmii,
>> +		.set_gmac_speed = rk3568_set_gmac_speed,
>> +		.regs = {
>> +			0xfe2a0000, /* gmac0 */
>> +			0xfe010000, /* gmac1 */
>> +			0x0, /* sentinel */
>> +		},
>> +	},
>> +	{ }
>> +};
>> +
>> +static const struct rk_gmac_ops *get_rk_gmac_ops(struct udevice *dev)
>> +{
>> +	const struct rk_gmac_ops *ops = rk_gmac_ops;
>> +
>> +	while (ops->compatible) {
>> +		if (device_is_compatible(dev, ops->compatible))
>> +			return ops;
>> +		ops++;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +static int eqos_probe_resources_rk(struct udevice *dev)
>> +{
>> +	struct eqos_priv *eqos = dev_get_priv(dev);
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data;
>> +	int reset_flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
>> +	int ret;
>> +
>> +	data = calloc(1, sizeof(struct rockchip_platform_data));
>> +	if (!data)
>> +		return -ENOMEM;
>> +
>> +	data->ops = get_rk_gmac_ops(dev);
>> +	if (!data->ops) {
>> +		ret = -EINVAL;
>> +		goto err_free;
>> +	}
>> +
>> +	for (int i = 0; data->ops->regs[i]; i++) {
>> +		if (data->ops->regs[i] == (u32)eqos->regs) {
>> +			data->id = i;
>> +			break;
>> +		}
>> +	}
>> +
>> +	pdata->priv_pdata = data;
>> +	pdata->phy_interface = eqos->config->interface(dev);
>> +	pdata->max_speed = eqos->max_speed;
>> +
>> +	if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
>> +		pr_err("Invalid PHY interface\n");
>> +		ret = -EINVAL;
>> +		goto err_free;
>> +	}
>> +
>> +	data->grf = syscon_regmap_lookup_by_phandle(dev, "rockchip,grf");
>> +	if (IS_ERR(data->grf)) {
>> +		dev_err(dev, "Missing rockchip,grf property\n");
>> +		ret = -EINVAL;
>> +		goto err_free;
>> +	}
>> +
>> +	ret = reset_get_bulk(dev, &data->resets);
>> +	if (ret < 0)
>> +		goto err_free;
>> +
>> +	reset_assert_bulk(&data->resets);
>> +
>> +	ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
>> +	if (ret) {
>> +		dev_dbg(dev, "clk_get_by_name(stmmaceth) failed: %d", ret);
>> +		goto err_release_resets;
>> +	}
>> +
>> +	ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
>> +	if (ret) {
>> +		dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
>> +		goto err_free_clk_master_bus;
>> +	}
>> +
>> +	if (dev_read_bool(dev, "snps,reset-active-low"))
>> +		reset_flags |= GPIOD_ACTIVE_LOW;
>> +
>> +	dev_read_u32_array(dev, "snps,reset-delays-us", eqos->reset_delays, 3);
>> +
>> +	gpio_request_by_name(dev, "snps,reset-gpio", 0,
>> +			     &eqos->phy_reset_gpio, reset_flags);
>> +
>> +	return 0;
>> +
>> +err_free_clk_master_bus:
>> +	clk_free(&eqos->clk_master_bus);
>> +err_release_resets:
>> +	reset_release_bulk(&data->resets);
>> +err_free:
>> +	free(data);
>> +
>> +	return ret;
>> +}
>> +
>> +static int eqos_remove_resources_rk(struct udevice *dev)
>> +{
>> +	struct eqos_priv *eqos = dev_get_priv(dev);
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +
>> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio))
>> +		dm_gpio_free(dev, &eqos->phy_reset_gpio);
>> +
>> +	clk_free(&eqos->clk_tx);
>> +	clk_free(&eqos->clk_master_bus);
>> +	reset_release_bulk(&data->resets);
>> +	free(data);
>> +
>> +	return 0;
>> +}
>> +
>> +static int eqos_stop_resets_rk(struct udevice *dev)
>> +{
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +
>> +	return reset_assert_bulk(&data->resets);
>> +}
>> +
>> +static int eqos_start_resets_rk(struct udevice *dev)
>> +{
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +
>> +	return reset_deassert_bulk(&data->resets);
>> +}
>> +
>> +static int eqos_stop_clks_rk(struct udevice *dev)
>> +{
>> +	return 0;
>> +}
>> +
>> +static int eqos_start_clks_rk(struct udevice *dev)
>> +{
>> +	struct eqos_priv *eqos = dev_get_priv(dev);
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +	int tx_delay, rx_delay, ret;
>> +
>> +	if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
>> +		udelay(eqos->reset_delays[1]);
>> +
>> +		ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		udelay(eqos->reset_delays[2]);
>> +	}
>> +
>> +	tx_delay = dev_read_u32_default(dev, "tx_delay", 0x30);
>> +	rx_delay = dev_read_u32_default(dev, "rx_delay", 0x10);
>> +
>> +	switch (pdata->phy_interface) {
>> +	case PHY_INTERFACE_MODE_RGMII:
>> +		return data->ops->set_to_rgmii(dev, tx_delay, rx_delay);
>> +	case PHY_INTERFACE_MODE_RGMII_ID:
>> +		return data->ops->set_to_rgmii(dev, 0, 0);
>> +	case PHY_INTERFACE_MODE_RGMII_RXID:
>> +		return data->ops->set_to_rgmii(dev, tx_delay, 0);
>> +	case PHY_INTERFACE_MODE_RGMII_TXID:
>> +		return data->ops->set_to_rgmii(dev, 0, rx_delay);
>> +	case PHY_INTERFACE_MODE_RMII:
>> +		return data->ops->set_to_rmii(dev);
>> +	}
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static int eqos_set_tx_clk_speed_rk(struct udevice *dev)
>> +{
>> +	struct eth_pdata *pdata = dev_get_plat(dev);
>> +	struct rockchip_platform_data *data = pdata->priv_pdata;
>> +
>> +	return data->ops->set_gmac_speed(dev);
>> +}
>> +
>> +static ulong eqos_get_tick_clk_rate_rk(struct udevice *dev)
>> +{
>> +	struct eqos_priv *eqos = dev_get_priv(dev);
>> +
>> +	return clk_get_rate(&eqos->clk_master_bus);
>> +}
>> +
>> +static struct eqos_ops eqos_rockchip_ops = {
>> +	.eqos_inval_desc = eqos_inval_desc_generic,
>> +	.eqos_flush_desc = eqos_flush_desc_generic,
>> +	.eqos_inval_buffer = eqos_inval_buffer_generic,
>> +	.eqos_flush_buffer = eqos_flush_buffer_generic,
>> +	.eqos_probe_resources = eqos_probe_resources_rk,
>> +	.eqos_remove_resources = eqos_remove_resources_rk,
>> +	.eqos_stop_resets = eqos_stop_resets_rk,
>> +	.eqos_start_resets = eqos_start_resets_rk,
>> +	.eqos_stop_clks = eqos_stop_clks_rk,
>> +	.eqos_start_clks = eqos_start_clks_rk,
>> +	.eqos_calibrate_pads = eqos_null_ops,
>> +	.eqos_disable_calibration = eqos_null_ops,
>> +	.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_rk,
>> +	.eqos_get_enetaddr = eqos_null_ops,
>> +	.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_rk,
>> +};
>> +
>> +struct eqos_config eqos_rockchip_config = {
>> +	.reg_access_always_ok = false,
>> +	.mdio_wait = 10,
>> +	.swr_wait = 50,
>> +	.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
>> +	.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_100_150,
>> +	.axi_bus_width = EQOS_AXI_WIDTH_64,
>> +	.interface = dev_read_phy_mode,
>> +	.ops = &eqos_rockchip_ops,
>> +};


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 5/7] net: dwc_eth_qos_rockchip: Add support for RK3588
  2023-09-27  3:01   ` Kever Yang
@ 2023-10-01 19:26     ` Sebastian Reichel
  0 siblings, 0 replies; 22+ messages in thread
From: Sebastian Reichel @ 2023-10-01 19:26 UTC (permalink / raw)
  To: Kever Yang
  Cc: Jonas Karlman, Simon Glass, Philipp Tomsich, Joe Hershberger,
	Ramon Fried, Eugen Hristev, Frank Wunderlich, Nicolas Frattaroli,
	u-boot, David Wu, Benjamin Gaignard

[-- Attachment #1: Type: text/plain, Size: 10584 bytes --]

Hi,

On Wed, Sep 27, 2023 at 11:01:10AM +0800, Kever Yang wrote:
> On 2023/8/7 08:08, Jonas Karlman wrote:
> > Add rk_gmac_ops and other special handling that is needed for GMAC to
> > work on RK3588.
> > 
> > rk_gmac_ops was ported from linux commits:
> > 2f2b60a0ec28 ("net: ethernet: stmmac: dwmac-rk: Add gmac support for rk3588")
> > 88619e77b33d ("net: stmmac: rk3588: Allow multiple gmac controller")
> > 
> > Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
> Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

FWIW it's also

Reviewed-by: <sebastian.reichel@collabora.com>

-- Sebastian

> 
> Thanks,
> - Kever
> > ---
> > Cc: David Wu <david.wu@rock-chips.com>
> > Cc: Sebastian Reichel <sebastian.reichel@collabora.com>
> > Cc: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> > ---
> >   drivers/net/dwc_eth_qos.c          |   4 +
> >   drivers/net/dwc_eth_qos_rockchip.c | 182 ++++++++++++++++++++++++++++-
> >   2 files changed, 182 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> > index 9fb98a2c3c74..dc04416865dd 100644
> > --- a/drivers/net/dwc_eth_qos.c
> > +++ b/drivers/net/dwc_eth_qos.c
> > @@ -1712,6 +1712,10 @@ static const struct udevice_id eqos_ids[] = {
> >   		.compatible = "rockchip,rk3568-gmac",
> >   		.data = (ulong)&eqos_rockchip_config
> >   	},
> > +	{
> > +		.compatible = "rockchip,rk3588-gmac",
> > +		.data = (ulong)&eqos_rockchip_config
> > +	},
> >   #endif
> >   #if IS_ENABLED(CONFIG_DWC_ETH_QOS_QCOM)
> >   	{
> > diff --git a/drivers/net/dwc_eth_qos_rockchip.c b/drivers/net/dwc_eth_qos_rockchip.c
> > index c8abe351fc3e..34020496bde6 100644
> > --- a/drivers/net/dwc_eth_qos_rockchip.c
> > +++ b/drivers/net/dwc_eth_qos_rockchip.c
> > @@ -20,6 +20,7 @@ struct rk_gmac_ops {
> >   			    int tx_delay, int rx_delay);
> >   	int (*set_to_rmii)(struct udevice *dev);
> >   	int (*set_gmac_speed)(struct udevice *dev);
> > +	void (*set_clock_selection)(struct udevice *dev, bool enable);
> >   	u32 regs[3];
> >   };
> > @@ -27,7 +28,9 @@ struct rockchip_platform_data {
> >   	struct reset_ctl_bulk resets;
> >   	const struct rk_gmac_ops *ops;
> >   	int id;
> > +	bool clock_input;
> >   	struct regmap *grf;
> > +	struct regmap *php_grf;
> >   };
> >   #define HIWORD_UPDATE(val, mask, shift) \
> > @@ -121,6 +124,137 @@ static int rk3568_set_gmac_speed(struct udevice *dev)
> >   	return 0;
> >   }
> > +/* sys_grf */
> > +#define RK3588_GRF_GMAC_CON7			0x031c
> > +#define RK3588_GRF_GMAC_CON8			0x0320
> > +#define RK3588_GRF_GMAC_CON9			0x0324
> > +
> > +#define RK3588_GMAC_RXCLK_DLY_ENABLE(id)	GRF_BIT(2 * (id) + 3)
> > +#define RK3588_GMAC_RXCLK_DLY_DISABLE(id)	GRF_CLR_BIT(2 * (id) + 3)
> > +#define RK3588_GMAC_TXCLK_DLY_ENABLE(id)	GRF_BIT(2 * (id) + 2)
> > +#define RK3588_GMAC_TXCLK_DLY_DISABLE(id)	GRF_CLR_BIT(2 * (id) + 2)
> > +
> > +#define RK3588_GMAC_CLK_RX_DL_CFG(val)		HIWORD_UPDATE(val, 0xFF, 8)
> > +#define RK3588_GMAC_CLK_TX_DL_CFG(val)		HIWORD_UPDATE(val, 0xFF, 0)
> > +
> > +/* php_grf */
> > +#define RK3588_GRF_GMAC_CON0			0x0008
> > +#define RK3588_GRF_CLK_CON1			0x0070
> > +
> > +#define RK3588_GMAC_PHY_INTF_SEL_RGMII(id)	\
> > +	(GRF_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_CLR_BIT(5 + (id) * 6))
> > +#define RK3588_GMAC_PHY_INTF_SEL_RMII(id)	\
> > +	(GRF_CLR_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_BIT(5 + (id) * 6))
> > +
> > +#define RK3588_GMAC_CLK_RMII_MODE(id)		GRF_BIT(5 * (id))
> > +#define RK3588_GMAC_CLK_RGMII_MODE(id)		GRF_CLR_BIT(5 * (id))
> > +
> > +#define RK3588_GMAC_CLK_SELET_CRU(id)		GRF_BIT(5 * (id) + 4)
> > +#define RK3588_GMAC_CLK_SELET_IO(id)		GRF_CLR_BIT(5 * (id) + 4)
> > +
> > +#define RK3588_GMAC_CLK_RMII_DIV2(id)		GRF_BIT(5 * (id) + 2)
> > +#define RK3588_GMAC_CLK_RMII_DIV20(id)		GRF_CLR_BIT(5 * (id) + 2)
> > +
> > +#define RK3588_GMAC_CLK_RGMII_DIV1(id)		\
> > +			(GRF_CLR_BIT(5 * (id) + 2) | GRF_CLR_BIT(5 * (id) + 3))
> > +#define RK3588_GMAC_CLK_RGMII_DIV5(id)		\
> > +			(GRF_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3))
> > +#define RK3588_GMAC_CLK_RGMII_DIV50(id)		\
> > +			(GRF_CLR_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3))
> > +
> > +#define RK3588_GMAC_CLK_RMII_GATE(id)		GRF_BIT(5 * (id) + 1)
> > +#define RK3588_GMAC_CLK_RMII_NOGATE(id)		GRF_CLR_BIT(5 * (id) + 1)
> > +
> > +static int rk3588_set_to_rgmii(struct udevice *dev,
> > +			       int tx_delay, int rx_delay)
> > +{
> > +	struct eth_pdata *pdata = dev_get_plat(dev);
> > +	struct rockchip_platform_data *data = pdata->priv_pdata;
> > +	u32 offset_con, id = data->id;
> > +
> > +	offset_con = data->id == 1 ? RK3588_GRF_GMAC_CON9 :
> > +				     RK3588_GRF_GMAC_CON8;
> > +
> > +	regmap_write(data->php_grf, RK3588_GRF_GMAC_CON0,
> > +		     RK3588_GMAC_PHY_INTF_SEL_RGMII(id));
> > +
> > +	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1,
> > +		     RK3588_GMAC_CLK_RGMII_MODE(id));
> > +
> > +	regmap_write(data->grf, RK3588_GRF_GMAC_CON7,
> > +		     RK3588_GMAC_RXCLK_DLY_ENABLE(id) |
> > +		     RK3588_GMAC_TXCLK_DLY_ENABLE(id));
> > +
> > +	regmap_write(data->grf, offset_con,
> > +		     RK3588_GMAC_CLK_RX_DL_CFG(rx_delay) |
> > +		     RK3588_GMAC_CLK_TX_DL_CFG(tx_delay));
> > +
> > +	return 0;
> > +}
> > +
> > +static int rk3588_set_to_rmii(struct udevice *dev)
> > +{
> > +	struct eth_pdata *pdata = dev_get_plat(dev);
> > +	struct rockchip_platform_data *data = pdata->priv_pdata;
> > +
> > +	regmap_write(data->php_grf, RK3588_GRF_GMAC_CON0,
> > +		     RK3588_GMAC_PHY_INTF_SEL_RMII(data->id));
> > +
> > +	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1,
> > +		     RK3588_GMAC_CLK_RMII_MODE(data->id));
> > +
> > +	return 0;
> > +}
> > +
> > +static int rk3588_set_gmac_speed(struct udevice *dev)
> > +{
> > +	struct eqos_priv *eqos = dev_get_priv(dev);
> > +	struct eth_pdata *pdata = dev_get_plat(dev);
> > +	struct rockchip_platform_data *data = pdata->priv_pdata;
> > +	u32 val = 0, id = data->id;
> > +
> > +	switch (eqos->phy->speed) {
> > +	case SPEED_10:
> > +		if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII)
> > +			val = RK3588_GMAC_CLK_RMII_DIV20(id);
> > +		else
> > +			val = RK3588_GMAC_CLK_RGMII_DIV50(id);
> > +		break;
> > +	case SPEED_100:
> > +		if (pdata->phy_interface == PHY_INTERFACE_MODE_RMII)
> > +			val = RK3588_GMAC_CLK_RMII_DIV2(id);
> > +		else
> > +			val = RK3588_GMAC_CLK_RGMII_DIV5(id);
> > +		break;
> > +	case SPEED_1000:
> > +		if (pdata->phy_interface != PHY_INTERFACE_MODE_RMII)
> > +			val = RK3588_GMAC_CLK_RGMII_DIV1(id);
> > +		else
> > +			return -EINVAL;
> > +		break;
> > +	default:
> > +		return -EINVAL;
> > +	}
> > +
> > +	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1, val);
> > +
> > +	return 0;
> > +}
> > +
> > +static void rk3588_set_clock_selection(struct udevice *dev, bool enable)
> > +{
> > +	struct eth_pdata *pdata = dev_get_plat(dev);
> > +	struct rockchip_platform_data *data = pdata->priv_pdata;
> > +
> > +	u32 val = data->clock_input ? RK3588_GMAC_CLK_SELET_IO(data->id) :
> > +				      RK3588_GMAC_CLK_SELET_CRU(data->id);
> > +
> > +	val |= enable ? RK3588_GMAC_CLK_RMII_NOGATE(data->id) :
> > +			RK3588_GMAC_CLK_RMII_GATE(data->id);
> > +
> > +	regmap_write(data->php_grf, RK3588_GRF_CLK_CON1, val);
> > +}
> > +
> >   static const struct rk_gmac_ops rk_gmac_ops[] = {
> >   	{
> >   		.compatible = "rockchip,rk3568-gmac",
> > @@ -133,6 +267,18 @@ static const struct rk_gmac_ops rk_gmac_ops[] = {
> >   			0x0, /* sentinel */
> >   		},
> >   	},
> > +	{
> > +		.compatible = "rockchip,rk3588-gmac",
> > +		.set_to_rgmii = rk3588_set_to_rgmii,
> > +		.set_to_rmii = rk3588_set_to_rmii,
> > +		.set_gmac_speed = rk3588_set_gmac_speed,
> > +		.set_clock_selection = rk3588_set_clock_selection,
> > +		.regs = {
> > +			0xfe1b0000, /* gmac0 */
> > +			0xfe1c0000, /* gmac1 */
> > +			0x0, /* sentinel */
> > +		},
> > +	},
> >   	{ }
> >   };
> > @@ -154,6 +300,7 @@ static int eqos_probe_resources_rk(struct udevice *dev)
> >   	struct eqos_priv *eqos = dev_get_priv(dev);
> >   	struct eth_pdata *pdata = dev_get_plat(dev);
> >   	struct rockchip_platform_data *data;
> > +	const char *clock_in_out;
> >   	int reset_flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
> >   	int ret;
> > @@ -191,6 +338,16 @@ static int eqos_probe_resources_rk(struct udevice *dev)
> >   		goto err_free;
> >   	}
> > +	if (device_is_compatible(dev, "rockchip,rk3588-gmac")) {
> > +		data->php_grf =
> > +			syscon_regmap_lookup_by_phandle(dev, "rockchip,php-grf");
> > +		if (IS_ERR(data->php_grf)) {
> > +			dev_err(dev, "Missing rockchip,php-grf property\n");
> > +			ret = -EINVAL;
> > +			goto err_free;
> > +		}
> > +	}
> > +
> >   	ret = reset_get_bulk(dev, &data->resets);
> >   	if (ret < 0)
> >   		goto err_free;
> > @@ -203,12 +360,20 @@ static int eqos_probe_resources_rk(struct udevice *dev)
> >   		goto err_release_resets;
> >   	}
> > -	ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
> > -	if (ret) {
> > -		dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
> > -		goto err_free_clk_master_bus;
> > +	if (device_is_compatible(dev, "rockchip,rk3568-gmac")) {
> > +		ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
> > +		if (ret) {
> > +			dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
> > +			goto err_free_clk_master_bus;
> > +		}
> >   	}
> > +	clock_in_out = dev_read_string(dev, "clock_in_out");
> > +	if (clock_in_out && !strcmp(clock_in_out, "input"))
> > +		data->clock_input = true;
> > +	else
> > +		data->clock_input = false;
> > +
> >   	if (dev_read_bool(dev, "snps,reset-active-low"))
> >   		reset_flags |= GPIOD_ACTIVE_LOW;
> > @@ -264,6 +429,12 @@ static int eqos_start_resets_rk(struct udevice *dev)
> >   static int eqos_stop_clks_rk(struct udevice *dev)
> >   {
> > +	struct eth_pdata *pdata = dev_get_plat(dev);
> > +	struct rockchip_platform_data *data = pdata->priv_pdata;
> > +
> > +	if (data->ops->set_clock_selection)
> > +		data->ops->set_clock_selection(dev, false);
> > +
> >   	return 0;
> >   }
> > @@ -284,6 +455,9 @@ static int eqos_start_clks_rk(struct udevice *dev)
> >   		udelay(eqos->reset_delays[2]);
> >   	}
> > +	if (data->ops->set_clock_selection)
> > +		data->ops->set_clock_selection(dev, true);
> > +
> >   	tx_delay = dev_read_u32_default(dev, "tx_delay", 0x30);
> >   	rx_delay = dev_read_u32_default(dev, "rx_delay", 0x10);

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 5/7] net: dwc_eth_qos_rockchip: Add support for RK3588
  2023-08-07  0:08 ` [PATCH 5/7] net: dwc_eth_qos_rockchip: Add support for RK3588 Jonas Karlman
  2023-09-27  3:01   ` Kever Yang
@ 2023-10-06 14:43   ` Tom Fitzhenry
  1 sibling, 0 replies; 22+ messages in thread
From: Tom Fitzhenry @ 2023-10-06 14:43 UTC (permalink / raw)
  To: jonas
  Cc: benjamin.gaignard, david.wu, eugen.hristev, frank-w,
	frattaroli.nicolas, joe.hershberger, kever.yang, philipp.tomsich,
	rfried.dev, sebastian.reichel, sjg, u-boot

Tested to work (DHCP, ping) on RK3588 QuartzPro64 (DTS coming soon!),
thanks!

Tested-by: Tom Fitzhenry <tom@tom-fitzhenry.me.uk>

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2023-10-06 21:32 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-07  0:08 [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Jonas Karlman
2023-08-07  0:08 ` [PATCH 1/7] net: dwc_eth_qos: Drop unused rx_pkt from eqos_priv Jonas Karlman
2023-09-27  3:00   ` Kever Yang
2023-08-07  0:08 ` [PATCH 2/7] net: dwc_eth_qos: Return error code when start fails Jonas Karlman
2023-09-27  3:00   ` Kever Yang
2023-08-07  0:08 ` [PATCH 3/7] net: dwc_eth_qos: Stop spam of RX packet not available message Jonas Karlman
2023-09-27  3:00   ` Kever Yang
2023-08-07  0:08 ` [PATCH 4/7] net: dwc_eth_qos: Add glue driver for GMAC on Rockchip RK3568 Jonas Karlman
2023-08-07 14:41   ` Eugen Hristev
2023-08-07 23:38     ` Jonas Karlman
2023-08-15 13:12   ` David Wu
2023-10-01 19:04     ` Jonas Karlman
2023-09-27  3:01   ` Kever Yang
2023-08-07  0:08 ` [PATCH 5/7] net: dwc_eth_qos_rockchip: Add support for RK3588 Jonas Karlman
2023-09-27  3:01   ` Kever Yang
2023-10-01 19:26     ` Sebastian Reichel
2023-10-06 14:43   ` Tom Fitzhenry
2023-08-07  0:08 ` [PATCH 6/7] configs: rockchip: Enable ethernet driver on RK356x boards Jonas Karlman
2023-09-27  3:01   ` Kever Yang
2023-08-07  0:08 ` [PATCH 7/7] configs: rockchip: Enable ethernet driver on RK3588 boards Jonas Karlman
2023-09-27  3:01   ` Kever Yang
2023-08-12  3:04 ` [PATCH 0/7] rockchip: Add GMAC support for RK3568 and RK3588 Kever Yang

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.