diff options
| author | David S. Miller <davem@davemloft.net> | 2022-01-29 17:49:21 +0000 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2022-01-29 17:49:21 +0000 | 
| commit | ff58831fa02deb42fd731f830d8d9ec545573c7c (patch) | |
| tree | dab150a236619d781a34fbfc46a896fdb1b2d15e /drivers/net/ethernet/cadence/macb_main.c | |
| parent | 0a78117213c4bb85dfebf89b924226883597bc60 (diff) | |
| parent | e461bd6f43f4e568f7436a8b6bc21c4ce6914c36 (diff) | |
Merge branch 'Cadence-ZyncMP-SGMII'
Robert Hancock says:
====================
Cadence MACB/GEM support for ZynqMP SGMII
Changes to allow SGMII mode to work properly in the GEM driver on the
Xilinx ZynqMP platform.
Changes since v3:
-more code formatting and error handling fixes
Changes since v2:
-fixed missing includes in DT binding example
-fixed phy_init and phy_power_on error handling/cleanup, moved
phy_power_on to open rather than probe
Changes since v1:
-changed order of controller reset and PHY init as per suggestion
-switched device reset to be optional
-updated bindings doc patch for switch to YAML
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/cadence/macb_main.c')
| -rw-r--r-- | drivers/net/ethernet/cadence/macb_main.c | 63 | 
1 files changed, 60 insertions, 3 deletions
| diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index a363da928e8b..1ce20bf52f72 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -34,7 +34,9 @@  #include <linux/udp.h>  #include <linux/tcp.h>  #include <linux/iopoll.h> +#include <linux/phy/phy.h>  #include <linux/pm_runtime.h> +#include <linux/reset.h>  #include "macb.h"  /* This structure is only used for MACB on SiFive FU540 devices */ @@ -2739,10 +2741,14 @@ static int macb_open(struct net_device *dev)  	macb_init_hw(bp); -	err = macb_phylink_connect(bp); +	err = phy_power_on(bp->sgmii_phy);  	if (err)  		goto reset_hw; +	err = macb_phylink_connect(bp); +	if (err) +		goto phy_off; +  	netif_tx_start_all_queues(dev);  	if (bp->ptp_info) @@ -2750,6 +2756,9 @@ static int macb_open(struct net_device *dev)  	return 0; +phy_off: +	phy_power_off(bp->sgmii_phy); +  reset_hw:  	macb_reset_hw(bp);  	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) @@ -2775,6 +2784,8 @@ static int macb_close(struct net_device *dev)  	phylink_stop(bp->phylink);  	phylink_disconnect_phy(bp->phylink); +	phy_power_off(bp->sgmii_phy); +  	spin_lock_irqsave(&bp->lock, flags);  	macb_reset_hw(bp);  	netif_carrier_off(dev); @@ -4544,13 +4555,55 @@ static const struct macb_config np4_config = {  	.usrio = &macb_default_usrio,  }; +static int zynqmp_init(struct platform_device *pdev) +{ +	struct net_device *dev = platform_get_drvdata(pdev); +	struct macb *bp = netdev_priv(dev); +	int ret; + +	if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { +		/* Ensure PS-GTR PHY device used in SGMII mode is ready */ +		bp->sgmii_phy = devm_phy_get(&pdev->dev, "sgmii-phy"); + +		if (IS_ERR(bp->sgmii_phy)) { +			ret = PTR_ERR(bp->sgmii_phy); +			dev_err_probe(&pdev->dev, ret, +				      "failed to get PS-GTR PHY\n"); +			return ret; +		} + +		ret = phy_init(bp->sgmii_phy); +		if (ret) { +			dev_err(&pdev->dev, "failed to init PS-GTR PHY: %d\n", +				ret); +			return ret; +		} +	} + +	/* Fully reset GEM controller at hardware level using zynqmp-reset driver, +	 * if mapped in device tree. +	 */ +	ret = device_reset_optional(&pdev->dev); +	if (ret) { +		dev_err_probe(&pdev->dev, ret, "failed to reset controller"); +		phy_exit(bp->sgmii_phy); +		return ret; +	} + +	ret = macb_init(pdev); +	if (ret) +		phy_exit(bp->sgmii_phy); + +	return ret; +} +  static const struct macb_config zynqmp_config = {  	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |  			MACB_CAPS_JUMBO |  			MACB_CAPS_GEM_HAS_PTP | MACB_CAPS_BD_RD_PREFETCH,  	.dma_burst_length = 16,  	.clk_init = macb_clk_init, -	.init = macb_init, +	.init = zynqmp_init,  	.jumbo_max_len = 10240,  	.usrio = &macb_default_usrio,  }; @@ -4767,7 +4820,7 @@ static int macb_probe(struct platform_device *pdev)  	err = macb_mii_init(bp);  	if (err) -		goto err_out_free_netdev; +		goto err_out_phy_exit;  	netif_carrier_off(dev); @@ -4792,6 +4845,9 @@ err_out_unregister_mdio:  	mdiobus_unregister(bp->mii_bus);  	mdiobus_free(bp->mii_bus); +err_out_phy_exit: +	phy_exit(bp->sgmii_phy); +  err_out_free_netdev:  	free_netdev(dev); @@ -4813,6 +4869,7 @@ static int macb_remove(struct platform_device *pdev)  	if (dev) {  		bp = netdev_priv(dev); +		phy_exit(bp->sgmii_phy);  		mdiobus_unregister(bp->mii_bus);  		mdiobus_free(bp->mii_bus); | 
