linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/2] net: axienet: Dynamically enable MDIO interface
@ 2020-11-03 11:26 Radhey Shyam Pandey
  2020-11-03 11:26 ` [PATCH net-next 1/2] net: xilinx: axiethernet: Introduce helper functions for MDC enable/disable Radhey Shyam Pandey
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Radhey Shyam Pandey @ 2020-11-03 11:26 UTC (permalink / raw)
  To: davem, kuba, netdev
  Cc: michal.simek, mchehab+samsung, gregkh, nicolas.ferre,
	linux-arm-kernel, linux-kernel, git, Radhey Shyam Pandey


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


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH net-next 1/2] net: xilinx: axiethernet: Introduce helper functions for MDC enable/disable
  2020-11-03 11:26 [PATCH net-next 0/2] net: axienet: Dynamically enable MDIO interface Radhey Shyam Pandey
@ 2020-11-03 11:26 ` Radhey Shyam Pandey
  2020-11-03 11:26 ` [PATCH net-next 2/2] net: xilinx: axiethernet: Enable dynamic MDIO MDC Radhey Shyam Pandey
  2020-11-07 19:17 ` [PATCH net-next 0/2] net: axienet: Dynamically enable MDIO interface Jakub Kicinski
  2 siblings, 0 replies; 4+ messages in thread
From: Radhey Shyam Pandey @ 2020-11-03 11:26 UTC (permalink / raw)
  To: davem, kuba, netdev
  Cc: michal.simek, mchehab+samsung, gregkh, nicolas.ferre,
	linux-arm-kernel, linux-kernel, git, Radhey Shyam Pandey

Introduce helper functions to enable/disable MDIO interface clock. This
change serves a preparatory patch for the coming feature to dynamically
control the management bus clock.

Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
---
 drivers/net/ethernet/xilinx/xilinx_axienet.h      |  2 ++
 drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c | 29 +++++++++++++++++++----
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h
index 7326ad4..a03c3ca 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
@@ -378,6 +378,7 @@ struct axidma_bd {
  * @dev:	Pointer to device structure
  * @phy_node:	Pointer to device node structure
  * @mii_bus:	Pointer to MII bus structure
+ * @mii_clk_div: MII bus clock divider value
  * @regs_start: Resource start for axienet device addresses
  * @regs:	Base address for the axienet_local device address space
  * @dma_regs:	Base address for the axidma device address space
@@ -427,6 +428,7 @@ struct axienet_local {
 
 	/* MDIO bus data */
 	struct mii_bus *mii_bus;	/* MII bus reference */
+	u8 mii_clk_div; /* MII bus clock divider value */
 
 	/* IO registers, dma functions and IRQs */
 	resource_size_t regs_start;
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
index 435ed30..84d06bf 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
@@ -30,6 +30,23 @@ static int axienet_mdio_wait_until_ready(struct axienet_local *lp)
 				  1, 20000);
 }
 
+/* Enable the MDIO MDC. Called prior to a read/write operation */
+static void axienet_mdio_mdc_enable(struct axienet_local *lp)
+{
+	axienet_iow(lp, XAE_MDIO_MC_OFFSET,
+		    ((u32)lp->mii_clk_div | XAE_MDIO_MC_MDIOEN_MASK));
+}
+
+/* Disable the MDIO MDC. Called after a read/write operation*/
+static void axienet_mdio_mdc_disable(struct axienet_local *lp)
+{
+	u32 mc_reg;
+
+	mc_reg = axienet_ior(lp, XAE_MDIO_MC_OFFSET);
+	axienet_iow(lp, XAE_MDIO_MC_OFFSET,
+		    (mc_reg & ~XAE_MDIO_MC_MDIOEN_MASK));
+}
+
 /**
  * axienet_mdio_read - MDIO interface read function
  * @bus:	Pointer to mii bus structure
@@ -124,7 +141,9 @@ static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
  **/
 int axienet_mdio_enable(struct axienet_local *lp)
 {
-	u32 clk_div, host_clock;
+	u32 host_clock;
+
+	lp->mii_clk_div = 0;
 
 	if (lp->clk) {
 		host_clock = clk_get_rate(lp->clk);
@@ -176,19 +195,19 @@ int axienet_mdio_enable(struct axienet_local *lp)
 	 * "clock-frequency" from the CPU
 	 */
 
-	clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1;
+	lp->mii_clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1;
 	/* If there is any remainder from the division of
 	 * fHOST / (MAX_MDIO_FREQ * 2), then we need to add
 	 * 1 to the clock divisor or we will surely be above 2.5 MHz
 	 */
 	if (host_clock % (MAX_MDIO_FREQ * 2))
-		clk_div++;
+		lp->mii_clk_div++;
 
 	netdev_dbg(lp->ndev,
 		   "Setting MDIO clock divisor to %u/%u Hz host clock.\n",
-		   clk_div, host_clock);
+		   lp->mii_clk_div, host_clock);
 
-	axienet_iow(lp, XAE_MDIO_MC_OFFSET, clk_div | XAE_MDIO_MC_MDIOEN_MASK);
+	axienet_iow(lp, XAE_MDIO_MC_OFFSET, lp->mii_clk_div | XAE_MDIO_MC_MDIOEN_MASK);
 
 	return axienet_mdio_wait_until_ready(lp);
 }
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH net-next 2/2] net: xilinx: axiethernet: Enable dynamic MDIO MDC
  2020-11-03 11:26 [PATCH net-next 0/2] net: axienet: Dynamically enable MDIO interface Radhey Shyam Pandey
  2020-11-03 11:26 ` [PATCH net-next 1/2] net: xilinx: axiethernet: Introduce helper functions for MDC enable/disable Radhey Shyam Pandey
@ 2020-11-03 11:26 ` Radhey Shyam Pandey
  2020-11-07 19:17 ` [PATCH net-next 0/2] net: axienet: Dynamically enable MDIO interface Jakub Kicinski
  2 siblings, 0 replies; 4+ messages in thread
From: Radhey Shyam Pandey @ 2020-11-03 11:26 UTC (permalink / raw)
  To: davem, kuba, netdev
  Cc: michal.simek, mchehab+samsung, gregkh, nicolas.ferre,
	linux-arm-kernel, linux-kernel, git, Clayton Rayment,
	Radhey Shyam Pandey

From: Clayton Rayment <clayton.rayment@xilinx.com>

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>
---
 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


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net-next 0/2] net: axienet: Dynamically enable MDIO interface
  2020-11-03 11:26 [PATCH net-next 0/2] net: axienet: Dynamically enable MDIO interface Radhey Shyam Pandey
  2020-11-03 11:26 ` [PATCH net-next 1/2] net: xilinx: axiethernet: Introduce helper functions for MDC enable/disable Radhey Shyam Pandey
  2020-11-03 11:26 ` [PATCH net-next 2/2] net: xilinx: axiethernet: Enable dynamic MDIO MDC Radhey Shyam Pandey
@ 2020-11-07 19:17 ` Jakub Kicinski
  2 siblings, 0 replies; 4+ messages in thread
From: Jakub Kicinski @ 2020-11-07 19:17 UTC (permalink / raw)
  To: Radhey Shyam Pandey
  Cc: davem, netdev, michal.simek, mchehab+samsung, gregkh,
	nicolas.ferre, linux-arm-kernel, linux-kernel, git

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!

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-11-07 19:17 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-03 11:26 [PATCH net-next 0/2] net: axienet: Dynamically enable MDIO interface Radhey Shyam Pandey
2020-11-03 11:26 ` [PATCH net-next 1/2] net: xilinx: axiethernet: Introduce helper functions for MDC enable/disable Radhey Shyam Pandey
2020-11-03 11:26 ` [PATCH net-next 2/2] net: xilinx: axiethernet: Enable dynamic MDIO MDC Radhey Shyam Pandey
2020-11-07 19:17 ` [PATCH net-next 0/2] net: axienet: Dynamically enable MDIO interface Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).