Commit 253761a0 authored by Clayton Rayment's avatar Clayton Rayment Committed by Jakub Kicinski

net: xilinx: axiethernet: Enable dynamic MDIO MDC

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: default avatarClayton Rayment <clayton.rayment@xilinx.com>
Signed-off-by: default avatarRadhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 6c3cbaa0
...@@ -1049,20 +1049,13 @@ static int axienet_open(struct net_device *ndev) ...@@ -1049,20 +1049,13 @@ static int axienet_open(struct net_device *ndev)
dev_dbg(&ndev->dev, "axienet_open()\n"); 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
* When we do an Axi Ethernet reset, it resets the complete core * including the MDIO. MDIO must be disabled before resetting.
* including the MDIO. MDIO must be disabled before resetting
* and re-enabled afterwards.
* Hold MDIO bus lock to avoid MDIO accesses during the reset. * Hold MDIO bus lock to avoid MDIO accesses during the reset.
*/ */
mutex_lock(&lp->mii_bus->mdio_lock); mutex_lock(&lp->mii_bus->mdio_lock);
axienet_mdio_disable(lp);
ret = axienet_device_reset(ndev); ret = axienet_device_reset(ndev);
if (ret == 0)
ret = axienet_mdio_enable(lp);
mutex_unlock(&lp->mii_bus->mdio_lock); mutex_unlock(&lp->mii_bus->mdio_lock);
if (ret < 0)
return ret;
ret = phylink_of_phy_connect(lp->phylink, lp->dev->of_node, 0); ret = phylink_of_phy_connect(lp->phylink, lp->dev->of_node, 0);
if (ret) { if (ret) {
...@@ -1156,9 +1149,7 @@ static int axienet_stop(struct net_device *ndev) ...@@ -1156,9 +1149,7 @@ static int axienet_stop(struct net_device *ndev)
/* Do a reset to ensure DMA is really stopped */ /* Do a reset to ensure DMA is really stopped */
mutex_lock(&lp->mii_bus->mdio_lock); mutex_lock(&lp->mii_bus->mdio_lock);
axienet_mdio_disable(lp);
__axienet_device_reset(lp); __axienet_device_reset(lp);
axienet_mdio_enable(lp);
mutex_unlock(&lp->mii_bus->mdio_lock); mutex_unlock(&lp->mii_bus->mdio_lock);
cancel_work_sync(&lp->dma_err_task); cancel_work_sync(&lp->dma_err_task);
...@@ -1669,16 +1660,12 @@ static void axienet_dma_err_handler(struct work_struct *work) ...@@ -1669,16 +1660,12 @@ static void axienet_dma_err_handler(struct work_struct *work)
axienet_setoptions(ndev, lp->options & axienet_setoptions(ndev, lp->options &
~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); ~(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
* When we do an Axi Ethernet reset, it resets the complete core * including the MDIO. MDIO must be disabled before resetting.
* including the MDIO. MDIO must be disabled before resetting
* and re-enabled afterwards.
* Hold MDIO bus lock to avoid MDIO accesses during the reset. * Hold MDIO bus lock to avoid MDIO accesses during the reset.
*/ */
mutex_lock(&lp->mii_bus->mdio_lock); mutex_lock(&lp->mii_bus->mdio_lock);
axienet_mdio_disable(lp);
__axienet_device_reset(lp); __axienet_device_reset(lp);
axienet_mdio_enable(lp);
mutex_unlock(&lp->mii_bus->mdio_lock); mutex_unlock(&lp->mii_bus->mdio_lock);
for (i = 0; i < lp->tx_bd_num; i++) { for (i = 0; i < lp->tx_bd_num; i++) {
......
...@@ -65,9 +65,13 @@ static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg) ...@@ -65,9 +65,13 @@ static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg)
int ret; int ret;
struct axienet_local *lp = bus->priv; struct axienet_local *lp = bus->priv;
axienet_mdio_mdc_enable(lp);
ret = axienet_mdio_wait_until_ready(lp); ret = axienet_mdio_wait_until_ready(lp);
if (ret < 0) if (ret < 0) {
axienet_mdio_mdc_disable(lp);
return ret; return ret;
}
axienet_iow(lp, XAE_MDIO_MCR_OFFSET, axienet_iow(lp, XAE_MDIO_MCR_OFFSET,
(((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) & (((phy_id << XAE_MDIO_MCR_PHYAD_SHIFT) &
...@@ -78,14 +82,17 @@ static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg) ...@@ -78,14 +82,17 @@ static int axienet_mdio_read(struct mii_bus *bus, int phy_id, int reg)
XAE_MDIO_MCR_OP_READ_MASK)); XAE_MDIO_MCR_OP_READ_MASK));
ret = axienet_mdio_wait_until_ready(lp); ret = axienet_mdio_wait_until_ready(lp);
if (ret < 0) if (ret < 0) {
axienet_mdio_mdc_disable(lp);
return ret; return ret;
}
rc = axienet_ior(lp, XAE_MDIO_MRD_OFFSET) & 0x0000FFFF; rc = axienet_ior(lp, XAE_MDIO_MRD_OFFSET) & 0x0000FFFF;
dev_dbg(lp->dev, "axienet_mdio_read(phy_id=%i, reg=%x) == %x\n", dev_dbg(lp->dev, "axienet_mdio_read(phy_id=%i, reg=%x) == %x\n",
phy_id, reg, rc); phy_id, reg, rc);
axienet_mdio_mdc_disable(lp);
return rc; return rc;
} }
...@@ -111,9 +118,13 @@ static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg, ...@@ -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", dev_dbg(lp->dev, "axienet_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
phy_id, reg, val); phy_id, reg, val);
axienet_mdio_mdc_enable(lp);
ret = axienet_mdio_wait_until_ready(lp); ret = axienet_mdio_wait_until_ready(lp);
if (ret < 0) if (ret < 0) {
axienet_mdio_mdc_disable(lp);
return ret; return ret;
}
axienet_iow(lp, XAE_MDIO_MWD_OFFSET, (u32) val); axienet_iow(lp, XAE_MDIO_MWD_OFFSET, (u32) val);
axienet_iow(lp, XAE_MDIO_MCR_OFFSET, axienet_iow(lp, XAE_MDIO_MCR_OFFSET,
...@@ -125,8 +136,11 @@ static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg, ...@@ -125,8 +136,11 @@ static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
XAE_MDIO_MCR_OP_WRITE_MASK)); XAE_MDIO_MCR_OP_WRITE_MASK));
ret = axienet_mdio_wait_until_ready(lp); ret = axienet_mdio_wait_until_ready(lp);
if (ret < 0) if (ret < 0) {
axienet_mdio_mdc_disable(lp);
return ret; return ret;
}
axienet_mdio_mdc_disable(lp);
return 0; return 0;
} }
...@@ -230,8 +244,8 @@ void axienet_mdio_disable(struct axienet_local *lp) ...@@ -230,8 +244,8 @@ void axienet_mdio_disable(struct axienet_local *lp)
* Return: 0 on success, -ETIMEDOUT on a timeout, -ENOMEM when * Return: 0 on success, -ETIMEDOUT on a timeout, -ENOMEM when
* mdiobus_alloc (to allocate memory for mii bus structure) fails. * mdiobus_alloc (to allocate memory for mii bus structure) fails.
* *
* Sets up the MDIO interface by initializing the MDIO clock and enabling the * Sets up the MDIO interface by initializing the MDIO clock.
* MDIO interface in hardware. Register the MDIO interface. * Register the MDIO interface.
**/ **/
int axienet_mdio_setup(struct axienet_local *lp) int axienet_mdio_setup(struct axienet_local *lp)
{ {
...@@ -265,6 +279,7 @@ int axienet_mdio_setup(struct axienet_local *lp) ...@@ -265,6 +279,7 @@ int axienet_mdio_setup(struct axienet_local *lp)
lp->mii_bus = NULL; lp->mii_bus = NULL;
return ret; return ret;
} }
axienet_mdio_mdc_disable(lp);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment