2020-11-03 11:28:32

by Radhey Shyam Pandey

[permalink] [raw]
Subject: [PATCH net-next 0/2] net: axienet: Dynamically enable MDIO interface


This patchset dynamically enable MDIO interface. The background for this
change is coming from Cadence GEM controller(macb) in which MDC is active
only during MDIO read or write operations while the PHY registers are
read or written. It is implemented as an IP feature.

For axiethernet as dynamic MDC enable/disable is not supported in hw
we are implementing it in sw. This change doesn't affect any existing
functionality.

Clayton Rayment (1):
net: xilinx: axiethernet: Enable dynamic MDIO MDC

Radhey Shyam Pandey (1):
net: xilinx: axiethernet: Introduce helper functions for MDC
enable/disable

drivers/net/ethernet/xilinx/xilinx_axienet.h | 2 +
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 21 ++-------
drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c | 56 ++++++++++++++++++-----
3 files changed, 51 insertions(+), 28 deletions(-)

--
2.7.4


2020-11-03 11:30:13

by Radhey Shyam Pandey

[permalink] [raw]
Subject: [PATCH net-next 2/2] net: xilinx: axiethernet: Enable dynamic MDIO MDC

From: Clayton Rayment <[email protected]>

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 <[email protected]>
Signed-off-by: Radhey Shyam Pandey <[email protected]>
---
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 21 ++++--------------
drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c | 27 ++++++++++++++++++-----
2 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 529c167..6fea980 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -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) {
@@ -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);
@@ -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++) {
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
index 84d06bf..9c014ce 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
@@ -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) &
@@ -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;
}

@@ -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,
@@ -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;
}

@@ -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)
{
@@ -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;
}

--
2.7.4

2020-11-07 19:20:13

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH net-next 0/2] net: axienet: Dynamically enable MDIO interface

On Tue, 3 Nov 2020 16:56:08 +0530 Radhey Shyam Pandey wrote:
> This patchset dynamically enable MDIO interface. The background for this
> change is coming from Cadence GEM controller(macb) in which MDC is active
> only during MDIO read or write operations while the PHY registers are
> read or written. It is implemented as an IP feature.
>
> For axiethernet as dynamic MDC enable/disable is not supported in hw
> we are implementing it in sw. This change doesn't affect any existing
> functionality.

Applied, thank you!