Skip to content

Commit

Permalink
net: xilinx: axiethernet: Enable dynamic MDIO MDC
Browse files Browse the repository at this point in the history
MDIO spec does not require an MDC at all times, only when MDIO
transactions are occurring. This patch allows the xilinx_axienet
driver to disable the MDC when not in use, and re-enable it when
needed. It also simplifies the driver by removing MDC disable
and enable in device reset sequence.

Signed-off-by: Clayton Rayment <clayton.rayment@xilinx.com>
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Clayton Rayment authored and Jakub Kicinski committed Nov 7, 2020
1 parent 6c3cbaa commit 253761a
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 23 deletions.
21 changes: 4 additions & 17 deletions drivers/net/ethernet/xilinx/xilinx_axienet_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1049,20 +1049,13 @@ static int axienet_open(struct net_device *ndev)

dev_dbg(&ndev->dev, "axienet_open()\n");

/* Disable the MDIO interface till Axi Ethernet Reset is completed.
* When we do an Axi Ethernet reset, it resets the complete core
* including the MDIO. MDIO must be disabled before resetting
* and re-enabled afterwards.
/* When we do an Axi Ethernet reset, it resets the complete core
* including the MDIO. MDIO must be disabled before resetting.
* Hold MDIO bus lock to avoid MDIO accesses during the reset.
*/
mutex_lock(&lp->mii_bus->mdio_lock);
axienet_mdio_disable(lp);
ret = axienet_device_reset(ndev);
if (ret == 0)
ret = axienet_mdio_enable(lp);
mutex_unlock(&lp->mii_bus->mdio_lock);
if (ret < 0)
return ret;

ret = phylink_of_phy_connect(lp->phylink, lp->dev->of_node, 0);
if (ret) {
Expand Down Expand Up @@ -1156,9 +1149,7 @@ static int axienet_stop(struct net_device *ndev)

/* Do a reset to ensure DMA is really stopped */
mutex_lock(&lp->mii_bus->mdio_lock);
axienet_mdio_disable(lp);
__axienet_device_reset(lp);
axienet_mdio_enable(lp);
mutex_unlock(&lp->mii_bus->mdio_lock);

cancel_work_sync(&lp->dma_err_task);
Expand Down Expand Up @@ -1669,16 +1660,12 @@ static void axienet_dma_err_handler(struct work_struct *work)

axienet_setoptions(ndev, lp->options &
~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
/* Disable the MDIO interface till Axi Ethernet Reset is completed.
* When we do an Axi Ethernet reset, it resets the complete core
* including the MDIO. MDIO must be disabled before resetting
* and re-enabled afterwards.
/* When we do an Axi Ethernet reset, it resets the complete core
* including the MDIO. MDIO must be disabled before resetting.
* Hold MDIO bus lock to avoid MDIO accesses during the reset.
*/
mutex_lock(&lp->mii_bus->mdio_lock);
axienet_mdio_disable(lp);
__axienet_device_reset(lp);
axienet_mdio_enable(lp);
mutex_unlock(&lp->mii_bus->mdio_lock);

for (i = 0; i < lp->tx_bd_num; i++) {
Expand Down
27 changes: 21 additions & 6 deletions drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,13 @@ static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg)
int ret;
struct axienet_local *lp = bus->priv;

axienet_mdio_mdc_enable(lp);

ret = axienet_mdio_wait_until_ready(lp);
if (ret < 0)
if (ret < 0) {
axienet_mdio_mdc_disable(lp);
return ret;
}

axienet_iow(lp, XAE_MDIO_MCR_OFFSET,
(((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) &
Expand All @@ -78,14 +82,17 @@ static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg)
XAE_MDIO_MCR_OP_READ_MASK));

ret = axienet_mdio_wait_until_ready(lp);
if (ret < 0)
if (ret < 0) {
axienet_mdio_mdc_disable(lp);
return ret;
}

rc = axienet_ior(lp, XAE_MDIO_MRD_OFFSET) & 0x0000FFFF;

dev_dbg(lp->dev, "axienet_mdio_read(phy_id=%i, reg=%x) == %x\n",
phy_id, reg, rc);

axienet_mdio_mdc_disable(lp);
return rc;
}

Expand All @@ -111,9 +118,13 @@ static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
dev_dbg(lp->dev, "axienet_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
phy_id, reg, val);

axienet_mdio_mdc_enable(lp);

ret = axienet_mdio_wait_until_ready(lp);
if (ret < 0)
if (ret < 0) {
axienet_mdio_mdc_disable(lp);
return ret;
}

axienet_iow(lp, XAE_MDIO_MWD_OFFSET, (u32) val);
axienet_iow(lp, XAE_MDIO_MCR_OFFSET,
Expand All @@ -125,8 +136,11 @@ static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
XAE_MDIO_MCR_OP_WRITE_MASK));

ret = axienet_mdio_wait_until_ready(lp);
if (ret < 0)
if (ret < 0) {
axienet_mdio_mdc_disable(lp);
return ret;
}
axienet_mdio_mdc_disable(lp);
return 0;
}

Expand Down Expand Up @@ -230,8 +244,8 @@ void axienet_mdio_disable(struct axienet_local *lp)
* Return: 0 on success, -ETIMEDOUT on a timeout, -ENOMEM when
* mdiobus_alloc (to allocate memory for mii bus structure) fails.
*
* Sets up the MDIO interface by initializing the MDIO clock and enabling the
* MDIO interface in hardware. Register the MDIO interface.
* Sets up the MDIO interface by initializing the MDIO clock.
* Register the MDIO interface.
**/
int axienet_mdio_setup(struct axienet_local *lp)
{
Expand Down Expand Up @@ -265,6 +279,7 @@ int axienet_mdio_setup(struct axienet_local *lp)
lp->mii_bus = NULL;
return ret;
}
axienet_mdio_mdc_disable(lp);
return 0;
}

Expand Down

0 comments on commit 253761a

Please sign in to comment.