Skip to content

Commit 6d7130e

Browse files
robhancocksedclaudiubeznea
authored andcommitted
net: macb: Added ZynqMP-specific initialization
The GEM controllers on ZynqMP were missing some initialization steps which are required in some cases when using SGMII mode, which uses the PS-GTR transceivers managed by the phy-zynqmp driver. The GEM core appears to need a hardware-level reset in order to work properly in SGMII mode in cases where the GT reference clock was not present at initial power-on. This can be done using a reset mapped to the zynqmp-reset driver in the device tree. Also, when in SGMII mode, the GEM driver needs to ensure the PHY is initialized and powered on. Signed-off-by: Robert Hancock <robert.hancock@calian.com> Reviewed-by: Claudiu Beznea <claudiu.beznea@microchip.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 0b2da3b commit 6d7130e

2 files changed

Lines changed: 64 additions & 3 deletions

File tree

drivers/net/ethernet/cadence/macb.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/ptp_clock_kernel.h>
1313
#include <linux/net_tstamp.h>
1414
#include <linux/interrupt.h>
15+
#include <linux/phy/phy.h>
1516

1617
#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) || defined(CONFIG_MACB_USE_HWSTAMP)
1718
#define MACB_EXT_DESC
@@ -1290,6 +1291,9 @@ struct macb {
12901291
u32 wol;
12911292

12921293
struct macb_ptp_info *ptp_info; /* macb-ptp interface */
1294+
1295+
struct phy *sgmii_phy; /* for ZynqMP SGMII mode */
1296+
12931297
#ifdef MACB_EXT_DESC
12941298
uint8_t hw_dma_cap;
12951299
#endif

drivers/net/ethernet/cadence/macb_main.c

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
#include <linux/udp.h>
3535
#include <linux/tcp.h>
3636
#include <linux/iopoll.h>
37+
#include <linux/phy/phy.h>
3738
#include <linux/pm_runtime.h>
39+
#include <linux/reset.h>
3840
#include "macb.h"
3941

4042
/* This structure is only used for MACB on SiFive FU540 devices */
@@ -2785,17 +2787,24 @@ static int macb_open(struct net_device *dev)
27852787

27862788
macb_init_hw(bp);
27872789

2788-
err = macb_phylink_connect(bp);
2790+
err = phy_power_on(bp->sgmii_phy);
27892791
if (err)
27902792
goto reset_hw;
27912793

2794+
err = macb_phylink_connect(bp);
2795+
if (err)
2796+
goto phy_off;
2797+
27922798
netif_tx_start_all_queues(dev);
27932799

27942800
if (bp->ptp_info)
27952801
bp->ptp_info->ptp_init(dev);
27962802

27972803
return 0;
27982804

2805+
phy_off:
2806+
phy_power_off(bp->sgmii_phy);
2807+
27992808
reset_hw:
28002809
macb_reset_hw(bp);
28012810
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
@@ -2821,6 +2830,8 @@ static int macb_close(struct net_device *dev)
28212830
phylink_stop(bp->phylink);
28222831
phylink_disconnect_phy(bp->phylink);
28232832

2833+
phy_power_off(bp->sgmii_phy);
2834+
28242835
spin_lock_irqsave(&bp->lock, flags);
28252836
macb_reset_hw(bp);
28262837
netif_carrier_off(dev);
@@ -4586,13 +4597,55 @@ static const struct macb_config np4_config = {
45864597
.usrio = &macb_default_usrio,
45874598
};
45884599

4600+
static int zynqmp_init(struct platform_device *pdev)
4601+
{
4602+
struct net_device *dev = platform_get_drvdata(pdev);
4603+
struct macb *bp = netdev_priv(dev);
4604+
int ret;
4605+
4606+
if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) {
4607+
/* Ensure PS-GTR PHY device used in SGMII mode is ready */
4608+
bp->sgmii_phy = devm_phy_get(&pdev->dev, "sgmii-phy");
4609+
4610+
if (IS_ERR(bp->sgmii_phy)) {
4611+
ret = PTR_ERR(bp->sgmii_phy);
4612+
dev_err_probe(&pdev->dev, ret,
4613+
"failed to get PS-GTR PHY\n");
4614+
return ret;
4615+
}
4616+
4617+
ret = phy_init(bp->sgmii_phy);
4618+
if (ret) {
4619+
dev_err(&pdev->dev, "failed to init PS-GTR PHY: %d\n",
4620+
ret);
4621+
return ret;
4622+
}
4623+
}
4624+
4625+
/* Fully reset GEM controller at hardware level using zynqmp-reset driver,
4626+
* if mapped in device tree.
4627+
*/
4628+
ret = device_reset_optional(&pdev->dev);
4629+
if (ret) {
4630+
dev_err_probe(&pdev->dev, ret, "failed to reset controller");
4631+
phy_exit(bp->sgmii_phy);
4632+
return ret;
4633+
}
4634+
4635+
ret = macb_init(pdev);
4636+
if (ret)
4637+
phy_exit(bp->sgmii_phy);
4638+
4639+
return ret;
4640+
}
4641+
45894642
static const struct macb_config zynqmp_config = {
45904643
.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
45914644
MACB_CAPS_JUMBO |
45924645
MACB_CAPS_GEM_HAS_PTP | MACB_CAPS_BD_RD_PREFETCH,
45934646
.dma_burst_length = 16,
45944647
.clk_init = macb_clk_init,
4595-
.init = macb_init,
4648+
.init = zynqmp_init,
45964649
.jumbo_max_len = 10240,
45974650
.usrio = &macb_default_usrio,
45984651
};
@@ -4809,7 +4862,7 @@ static int macb_probe(struct platform_device *pdev)
48094862

48104863
err = macb_mii_init(bp);
48114864
if (err)
4812-
goto err_out_free_netdev;
4865+
goto err_out_phy_exit;
48134866

48144867
netif_carrier_off(dev);
48154868

@@ -4834,6 +4887,9 @@ static int macb_probe(struct platform_device *pdev)
48344887
mdiobus_unregister(bp->mii_bus);
48354888
mdiobus_free(bp->mii_bus);
48364889

4890+
err_out_phy_exit:
4891+
phy_exit(bp->sgmii_phy);
4892+
48374893
err_out_free_netdev:
48384894
free_netdev(dev);
48394895

@@ -4855,6 +4911,7 @@ static int macb_remove(struct platform_device *pdev)
48554911

48564912
if (dev) {
48574913
bp = netdev_priv(dev);
4914+
phy_exit(bp->sgmii_phy);
48584915
mdiobus_unregister(bp->mii_bus);
48594916
mdiobus_free(bp->mii_bus);
48604917

0 commit comments

Comments
 (0)