diff mbox series

[8/8] net: gmac_rockchip: Add dwc_eth_qos support

Message ID 20200430104527.31248-1-david.wu@rock-chips.com
State Superseded
Headers show
Series Add dwc_eth_qos support for rockchip | expand

Commit Message

David Wu April 30, 2020, 10:45 a.m. UTC
Change the original data structure so that Rockchip's Soc
gmac controller can support the designware.c and dwc_eth_qos.c
drivers, a Soc can only support one.

Signed-off-by: David Wu <david.wu at rock-chips.com>
---

 drivers/net/Kconfig         |   2 +-
 drivers/net/gmac_rockchip.c | 160 ++++++++++++++++++++++++++++++------
 2 files changed, 135 insertions(+), 27 deletions(-)

Comments

Stephen Warren April 30, 2020, 10:52 p.m. UTC | #1
On 4/30/20 4:45 AM, David Wu wrote:
> Change the original data structure so that Rockchip's Soc
> gmac controller can support the designware.c and dwc_eth_qos.c
> drivers, a Soc can only support one.

I'm really confused; with a filename like gmac_rockchip.c that sounds
like it's driver for a MAC device. DWC EQoS is also a MAC device. The
two shouldn't be related or coupled in any way.

I think what you need is to completely drop this patch (and the patch
which creates dwc_eth_qos.h), and instead make the DWC EQoS driver
itself directly support the Rockchip SoC by adding RK's compatible value
to the list of compatible values that the EQoS driver supports, along
with new probe functions etc.

Maybe this requires splitting some PHY code out of gmac_rockchip into a
common/separate PHY driver? I haven't looked at the code to know if
that's required.
David Wu May 9, 2020, 6:56 a.m. UTC | #2
Hi Stephen,

? 2020/5/1 ??6:52, Stephen Warren ??:
> I'm really confused; with a filename like gmac_rockchip.c that sounds
> like it's driver for a MAC device. DWC EQoS is also a MAC device. The
> two shouldn't be related or coupled in any way.
> 
> I think what you need is to completely drop this patch (and the patch
> which creates dwc_eth_qos.h), and instead make the DWC EQoS driver
> itself directly support the Rockchip SoC by adding RK's compatible value
> to the list of compatible values that the EQoS driver supports, along
> with new probe functions etc.
> 
> Maybe this requires splitting some PHY code out of gmac_rockchip into a
> common/separate PHY driver? I haven't looked at the code to know if
> that's required.

I think this relationship is like the current designware.c and 
gmac_rockchip.c, except that the designware driver becomes DWC EQoS. In 
fact, most of the code is the same, because it is the same controller, 
and there are a few differences related to Soc implemented in 
gmac_rockchip.c, this is the purpose of my series of patches, and the 
code must be compatible with the previous Rockchip Socs.
diff mbox series

Patch

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 4d1013c984..07d2b0787c 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -482,7 +482,7 @@  config PIC32_ETH
 
 config GMAC_ROCKCHIP
 	bool "Rockchip Synopsys Designware Ethernet MAC"
-	depends on DM_ETH && ETH_DESIGNWARE
+	depends on DM_ETH && (ETH_DESIGNWARE || DWC_ETH_QOS)
 	help
 	  This driver provides Rockchip SoCs network support based on the
 	  Synopsys Designware driver.
diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
index e152faf083..aa2bab4203 100644
--- a/drivers/net/gmac_rockchip.c
+++ b/drivers/net/gmac_rockchip.c
@@ -25,26 +25,39 @@ 
 #include <dm/pinctrl.h>
 #include <dt-bindings/clock/rk3288-cru.h>
 #include "designware.h"
+#include "dwc_eth_qos.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 #define DELAY_ENABLE(soc, tx, rx) \
 	(((tx) ? soc##_TXCLK_DLY_ENA_GMAC_ENABLE : soc##_TXCLK_DLY_ENA_GMAC_DISABLE) | \
 	((rx) ? soc##_RXCLK_DLY_ENA_GMAC_ENABLE : soc##_RXCLK_DLY_ENA_GMAC_DISABLE))
 
+struct rockchip_eth_dev {
+	union {
+		struct eqos_priv eqos;
+		struct dw_eth_dev dw;
+	};
+};
+
 /*
  * Platform data for the gmac
  *
  * dw_eth_pdata: Required platform data for designware driver (must be first)
  */
 struct gmac_rockchip_platdata {
-	struct dw_eth_pdata dw_eth_pdata;
+	union {
+		struct dw_eth_pdata dw_eth_pdata;
+		struct eth_pdata eth_pdata;
+	};
+	bool has_gmac4;
 	bool clock_input;
 	int tx_delay;
 	int rx_delay;
 };
 
 struct rk_gmac_ops {
-	int (*fix_mac_speed)(struct dw_eth_dev *priv);
+	const struct eqos_config config;
+	int (*fix_mac_speed)(struct rockchip_eth_dev *dev);
 	void (*set_to_rmii)(struct gmac_rockchip_platdata *pdata);
 	void (*set_to_rgmii)(struct gmac_rockchip_platdata *pdata);
 };
@@ -55,6 +68,9 @@  static int gmac_rockchip_ofdata_to_platdata(struct udevice *dev)
 	struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
 	const char *string;
 
+	if (device_is_compatible(dev, "snps,dwmac-4.20a"))
+		pdata->has_gmac4 = true;
+
 	string = dev_read_string(dev, "clock_in_out");
 	if (!strcmp(string, "input"))
 		pdata->clock_input = true;
@@ -71,11 +87,15 @@  static int gmac_rockchip_ofdata_to_platdata(struct udevice *dev)
 	if (pdata->rx_delay == -ENOENT)
 		pdata->rx_delay = dev_read_u32_default(dev, "rx-delay", 0x10);
 
-	return designware_eth_ofdata_to_platdata(dev);
+	if (!pdata->has_gmac4)
+		return designware_eth_ofdata_to_platdata(dev);
+
+	return 0;
 }
 
-static int px30_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int px30_gmac_fix_mac_speed(struct rockchip_eth_dev *dev)
 {
+	struct dw_eth_dev *priv = &dev->dw;
 	struct px30_grf *grf;
 	struct clk clk_speed;
 	int speed, ret;
@@ -115,8 +135,9 @@  static int px30_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 	return 0;
 }
 
-static int rk3228_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3228_gmac_fix_mac_speed(struct rockchip_eth_dev *dev)
 {
+	struct dw_eth_dev *priv = &dev->dw;
 	struct rk322x_grf *grf;
 	int clk;
 	enum {
@@ -148,8 +169,9 @@  static int rk3228_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 	return 0;
 }
 
-static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3288_gmac_fix_mac_speed(struct rockchip_eth_dev *dev)
 {
+	struct dw_eth_dev *priv = &dev->dw;
 	struct rk3288_grf *grf;
 	int clk;
 
@@ -174,8 +196,9 @@  static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 	return 0;
 }
 
-static int rk3308_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3308_gmac_fix_mac_speed(struct rockchip_eth_dev *dev)
 {
+	struct dw_eth_dev *priv = &dev->dw;
 	struct rk3308_grf *grf;
 	struct clk clk_speed;
 	int speed, ret;
@@ -215,8 +238,9 @@  static int rk3308_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 	return 0;
 }
 
-static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3328_gmac_fix_mac_speed(struct rockchip_eth_dev *dev)
 {
+	struct dw_eth_dev *priv = &dev->dw;
 	struct rk3328_grf_regs *grf;
 	int clk;
 	enum {
@@ -248,8 +272,9 @@  static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 	return 0;
 }
 
-static int rk3368_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3368_gmac_fix_mac_speed(struct rockchip_eth_dev *dev)
 {
+	struct dw_eth_dev *priv = &dev->dw;
 	struct rk3368_grf *grf;
 	int clk;
 	enum {
@@ -280,8 +305,9 @@  static int rk3368_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 	return 0;
 }
 
-static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv)
+static int rk3399_gmac_fix_mac_speed(struct rockchip_eth_dev *dev)
 {
+	struct dw_eth_dev *priv = &dev->dw;
 	struct rk3399_grf_regs *grf;
 	int clk;
 
@@ -306,8 +332,9 @@  static int rk3399_gmac_fix_mac_speed(struct dw_eth_dev *priv)
 	return 0;
 }
 
-static int rv1108_set_rmii_speed(struct dw_eth_dev *priv)
+static int rv1108_set_rmii_speed(struct rockchip_eth_dev *dev)
 {
+	struct dw_eth_dev *priv = &dev->dw;
 	struct rv1108_grf *grf;
 	int clk, speed;
 	enum {
@@ -555,12 +582,22 @@  static int gmac_rockchip_probe(struct udevice *dev)
 	struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
 	struct rk_gmac_ops *ops =
 		(struct rk_gmac_ops *)dev_get_driver_data(dev);
-	struct dw_eth_pdata *dw_pdata = dev_get_platdata(dev);
-	struct eth_pdata *eth_pdata = &dw_pdata->eth_pdata;
+	struct dw_eth_pdata *dw_pdata;
+	struct eth_pdata *eth_pdata;
+	struct eqos_config *config;
 	struct clk clk;
 	ulong rate;
 	int ret;
 
+	if (pdata->has_gmac4) {
+		eth_pdata = &pdata->eth_pdata;
+		config = (struct eqos_config *)&ops->config;
+		eth_pdata->phy_interface = config->ops->eqos_get_interface(dev);
+	} else {
+		dw_pdata = &pdata->dw_eth_pdata;
+		eth_pdata = &dw_pdata->eth_pdata;
+	}
+
 	ret = clk_set_defaults(dev, 0);
 	if (ret)
 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
@@ -656,37 +693,108 @@  static int gmac_rockchip_probe(struct udevice *dev)
 		return -ENXIO;
 	}
 
-	return designware_eth_probe(dev);
+	if (pdata->has_gmac4)
+		return eqos_probe(dev);
+	else
+		return designware_eth_probe(dev);
+}
+
+static int gmac_rockchip_eth_write_hwaddr(struct udevice *dev)
+{
+	struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
+
+	if (pdata->has_gmac4)
+		return eqos_write_hwaddr(dev);
+	else
+		return designware_eth_write_hwaddr(dev);
+}
+
+static int gmac_rockchip_eth_free_pkt(struct udevice *dev, uchar *packet,
+				      int length)
+{
+	struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
+
+	if (pdata->has_gmac4)
+		return eqos_free_pkt(dev, packet, length);
+	else
+		return designware_eth_free_pkt(dev, packet, length);
+}
+
+static int gmac_rockchip_eth_send(struct udevice *dev, void *packet,
+				  int length)
+{
+	struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
+
+	if (pdata->has_gmac4)
+		return eqos_send(dev, packet, length);
+	else
+		return designware_eth_send(dev, packet, length);
+}
+
+static int gmac_rockchip_eth_recv(struct udevice *dev, int flags,
+				  uchar **packetp)
+{
+	struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
+
+	if (pdata->has_gmac4)
+		return eqos_recv(dev, flags, packetp);
+	else
+		return designware_eth_recv(dev, flags, packetp);
 }
 
 static int gmac_rockchip_eth_start(struct udevice *dev)
 {
-	struct eth_pdata *pdata = dev_get_platdata(dev);
-	struct dw_eth_dev *priv = dev_get_priv(dev);
+	struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
+	struct rockchip_eth_dev *priv = dev_get_priv(dev);
 	struct rk_gmac_ops *ops =
 		(struct rk_gmac_ops *)dev_get_driver_data(dev);
+	struct dw_eth_pdata *dw_pdata;
+	struct eth_pdata *eth_pdata;
 	int ret;
 
-	ret = designware_eth_init(priv, pdata->enetaddr);
+	if (pdata->has_gmac4) {
+		ret = eqos_init(dev);
+	} else {
+		dw_pdata = &pdata->dw_eth_pdata;
+		eth_pdata = &dw_pdata->eth_pdata;
+		ret = designware_eth_init((struct dw_eth_dev *)priv,
+					  eth_pdata->enetaddr);
+	}
 	if (ret)
 		return ret;
+
 	ret = ops->fix_mac_speed(priv);
 	if (ret)
 		return ret;
-	ret = designware_eth_enable(priv);
-	if (ret)
-		return ret;
+
+	if (pdata->has_gmac4) {
+		eqos_enable(dev);
+	} else {
+		ret = designware_eth_enable((struct dw_eth_dev *)priv);
+		if (ret)
+			return ret;
+	}
 
 	return 0;
 }
 
+static void gmac_rockchip_eth_stop(struct udevice *dev)
+{
+	struct gmac_rockchip_platdata *pdata = dev_get_platdata(dev);
+
+	if (pdata->has_gmac4)
+		eqos_stop(dev);
+	else
+		designware_eth_stop(dev);
+}
+
 const struct eth_ops gmac_rockchip_eth_ops = {
 	.start			= gmac_rockchip_eth_start,
-	.send			= designware_eth_send,
-	.recv			= designware_eth_recv,
-	.free_pkt		= designware_eth_free_pkt,
-	.stop			= designware_eth_stop,
-	.write_hwaddr		= designware_eth_write_hwaddr,
+	.send			= gmac_rockchip_eth_send,
+	.recv			= gmac_rockchip_eth_recv,
+	.free_pkt		= gmac_rockchip_eth_free_pkt,
+	.stop			= gmac_rockchip_eth_stop,
+	.write_hwaddr		= gmac_rockchip_eth_write_hwaddr,
 };
 
 const struct rk_gmac_ops px30_gmac_ops = {
@@ -756,7 +864,7 @@  U_BOOT_DRIVER(eth_gmac_rockchip) = {
 	.ofdata_to_platdata = gmac_rockchip_ofdata_to_platdata,
 	.probe	= gmac_rockchip_probe,
 	.ops	= &gmac_rockchip_eth_ops,
-	.priv_auto_alloc_size = sizeof(struct dw_eth_dev),
+	.priv_auto_alloc_size = sizeof(struct rockchip_eth_dev),
 	.platdata_auto_alloc_size = sizeof(struct gmac_rockchip_platdata),
 	.flags = DM_FLAG_ALLOC_PRIV_DMA,
 };