[PATCH v2 08/11] net: gmac_rockchip: Add dwc_eth_qos support
David Wu
david.wu at rock-chips.com
Mon May 11 09:07:12 CEST 2020
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>
---
Changes in v2:
- None
drivers/net/Kconfig | 2 +-
drivers/net/gmac_rockchip.c | 160 ++++++++++++++++++++++++++++++------
2 files changed, 135 insertions(+), 27 deletions(-)
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,
};
--
2.19.1
More information about the U-Boot
mailing list