From patchwork Thu Apr 30 10:45:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Wu X-Patchwork-Id: 238977 List-Id: U-Boot discussion From: david.wu at rock-chips.com (David Wu) Date: Thu, 30 Apr 2020 18:45:27 +0800 Subject: [PATCH 8/8] net: gmac_rockchip: Add dwc_eth_qos support In-Reply-To: <20200430103656.29728-1-david.wu@rock-chips.com> References: <20200430103656.29728-1-david.wu@rock-chips.com> Message-ID: <20200430104527.31248-1-david.wu@rock-chips.com> 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 --- 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 #include #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, };