diff mbox series

[v4,net-next,2/3] net: axienet: set mdio clock according to bus-frequency

Message ID 20221117034751.1347105-3-andy.chiu@sifive.com (mailing list archive)
State New, archived
Headers show
Series net: axienet: Use a DT property to configure frequency of the MDIO bus | expand

Commit Message

Andy Chiu Nov. 17, 2022, 3:47 a.m. UTC
Some FPGA platforms have 80KHz MDIO bus frequency constraint when
connecting Ethernet to its on-board external Marvell PHY. Thus, we may
have to set MDIO clock according to the DT. Otherwise, use the default
2.5 MHz, as specified by 802.3, if the entry is not present.

Also, change MAX_MDIO_FREQ to DEFAULT_MDIO_FREQ because we may actually
set MDIO bus frequency higher than 2.5MHz if undelying devices support
it.

Signed-off-by: Andy Chiu <andy.chiu@sifive.com>
Reviewed-by: Greentime Hu <greentime.hu@sifive.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 .../net/ethernet/xilinx/xilinx_axienet_mdio.c | 48 +++++++++++++------
 1 file changed, 33 insertions(+), 15 deletions(-)

Comments

Radhey Shyam Pandey Nov. 17, 2022, 6:06 a.m. UTC | #1
> -----Original Message-----
> From: Andy Chiu <andy.chiu@sifive.com>
> Sent: Thursday, November 17, 2022 9:18 AM
> To: davem@davemloft.net; andrew@lunn.ch; kuba@kernel.org;
> michal.simek@xilinx.com; radhey.shyam.pandey@xilinx.com
> Cc: netdev@vger.kernel.org; devicetree@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org; robh+dt@kernel.org; pabeni@redhat.com;
> edumazet@google.com; andy.chiu@sifive.com; greentime.hu@sifive.com
> Subject: [PATCH v4 net-next 2/3] net: axienet: set mdio clock according to
> bus-frequency
> 
> CAUTION: This message has originated from an External Source. Please use
> proper judgment and caution when opening attachments, clicking links, or
> responding to this email.
> 
> 
> Some FPGA platforms have 80KHz MDIO bus frequency constraint when
> connecting Ethernet to its on-board external Marvell PHY. Thus, we may have
> to set MDIO clock according to the DT. Otherwise, use the default
> 2.5 MHz, as specified by 802.3, if the entry is not present.
> 
> Also, change MAX_MDIO_FREQ to DEFAULT_MDIO_FREQ because we may
> actually set MDIO bus frequency higher than 2.5MHz if undelying devices
> support it.
> 
> Signed-off-by: Andy Chiu <andy.chiu@sifive.com>
> Reviewed-by: Greentime Hu <greentime.hu@sifive.com>
> Reviewed-by: Andrew Lunn <andrew@lunn.ch>
> ---
>  .../net/ethernet/xilinx/xilinx_axienet_mdio.c | 48 +++++++++++++------
>  1 file changed, 33 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
> b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
> index e1f51a071888..789a90997f4b 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
> @@ -17,7 +17,7 @@
> 
>  #include "xilinx_axienet.h"
> 
> -#define MAX_MDIO_FREQ          2500000 /* 2.5 MHz */
> +#define DEFAULT_MDIO_FREQ      2500000 /* 2.5 MHz */
>  #define DEFAULT_HOST_CLOCK     150000000 /* 150 MHz */
> 
>  /* Wait till MDIO interface is ready to accept a new transaction.*/ @@ -
> 147,15 +147,18 @@ static int axienet_mdio_write(struct mii_bus *bus, int
> phy_id, int reg,
>  /**
>   * axienet_mdio_enable - MDIO hardware setup function
>   * @lp:                Pointer to axienet local data structure.
> + * @np:                Pointer to mdio device tree node.
>   *
>   * Return:     0 on success, -ETIMEDOUT on a timeout.

We are now also returning -EOVERFLOW. Please update the description.

>   *
>   * Sets up the MDIO interface by initializing the MDIO clock and enabling the
>   * MDIO interface in hardware.
>   **/
> -static int axienet_mdio_enable(struct axienet_local *lp)
> +static int axienet_mdio_enable(struct axienet_local *lp, struct
> +device_node *np)
>  {
> +       u32 mdio_freq = DEFAULT_MDIO_FREQ;
>         u32 host_clock;
> +       u32 clk_div;
> 
>         lp->mii_clk_div = 0;
> 
> @@ -184,6 +187,12 @@ static int axienet_mdio_enable(struct axienet_local
> *lp)
>                             host_clock);
>         }
> 
Binding 3/3 patch should be before this patch. 

> +       if (np)
> +               of_property_read_u32(np, "clock-frequency", &mdio_freq);
> +       if (mdio_freq != DEFAULT_MDIO_FREQ)
> +               netdev_info(lp->ndev, "Setting non-standard mdio bus frequency
> to %u Hz\n",
> +                           mdio_freq);
> +
>         /* clk_div can be calculated by deriving it from the equation:
>          * fMDIO = fHOST / ((1 + clk_div) * 2)
>          *
> @@ -209,13 +218,20 @@ static int axienet_mdio_enable(struct axienet_local
> *lp)
>          * "clock-frequency" from the CPU
>          */
> 
> -       lp->mii_clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1;
> +       clk_div = (host_clock / (mdio_freq * 2)) - 1;
>         /* If there is any remainder from the division of
> -        * fHOST / (MAX_MDIO_FREQ * 2), then we need to add
> +        * fHOST / (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))
> -               lp->mii_clk_div++;
> +       if (host_clock % (mdio_freq * 2))
> +               clk_div++;
> +
> +       /* Check for overflow of mii_clk_div */
> +       if (clk_div & ~XAE_MDIO_MC_CLOCK_DIVIDE_MAX) {
> +               netdev_warn(lp->ndev, "MDIO clock divisor overflow\n");
> +               return -EOVERFLOW;
> +       }
> +       lp->mii_clk_div = (u8)clk_div;
> 
>         netdev_dbg(lp->ndev,
>                    "Setting MDIO clock divisor to %u/%u Hz host clock.\n", @@ -
> 242,10 +258,6 @@ int axienet_mdio_setup(struct axienet_local *lp)
>         struct mii_bus *bus;
>         int ret;
> 
> -       ret = axienet_mdio_enable(lp);
> -       if (ret < 0)
> -               return ret;
> -
>         bus = mdiobus_alloc();
>         if (!bus)
>                 return -ENOMEM;
> @@ -261,15 +273,21 @@ int axienet_mdio_setup(struct axienet_local *lp)
>         lp->mii_bus = bus;
> 
>         mdio_node = of_get_child_by_name(lp->dev->of_node, "mdio");
> +       ret = axienet_mdio_enable(lp, mdio_node);
> +       if (ret < 0)
> +               goto unregister;
>         ret = of_mdiobus_register(bus, mdio_node);
> +       if (ret)
> +               goto unregister;

Missing axienet_mdio_mdc_disable in error path. 

Also return documentation of axienet_mdio_setup needs a update.

>         of_node_put(mdio_node);
> -       if (ret) {
> -               mdiobus_free(bus);
> -               lp->mii_bus = NULL;
> -               return ret;
> -       }
>         axienet_mdio_mdc_disable(lp);
>         return 0;
> +
> +unregister:
> +       of_node_put(mdio_node);
> +       mdiobus_free(bus);
> +       lp->mii_bus = NULL;
> +       return ret;
>  }
> 
>  /**
> --
> 2.36.0
diff mbox series

Patch

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
index e1f51a071888..789a90997f4b 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
@@ -17,7 +17,7 @@ 
 
 #include "xilinx_axienet.h"
 
-#define MAX_MDIO_FREQ		2500000 /* 2.5 MHz */
+#define DEFAULT_MDIO_FREQ	2500000 /* 2.5 MHz */
 #define DEFAULT_HOST_CLOCK	150000000 /* 150 MHz */
 
 /* Wait till MDIO interface is ready to accept a new transaction.*/
@@ -147,15 +147,18 @@  static int axienet_mdio_write(struct mii_bus *bus, int phy_id, int reg,
 /**
  * axienet_mdio_enable - MDIO hardware setup function
  * @lp:		Pointer to axienet local data structure.
+ * @np:		Pointer to mdio device tree node.
  *
  * Return:	0 on success, -ETIMEDOUT on a timeout.
  *
  * Sets up the MDIO interface by initializing the MDIO clock and enabling the
  * MDIO interface in hardware.
  **/
-static int axienet_mdio_enable(struct axienet_local *lp)
+static int axienet_mdio_enable(struct axienet_local *lp, struct device_node *np)
 {
+	u32 mdio_freq = DEFAULT_MDIO_FREQ;
 	u32 host_clock;
+	u32 clk_div;
 
 	lp->mii_clk_div = 0;
 
@@ -184,6 +187,12 @@  static int axienet_mdio_enable(struct axienet_local *lp)
 			    host_clock);
 	}
 
+	if (np)
+		of_property_read_u32(np, "clock-frequency", &mdio_freq);
+	if (mdio_freq != DEFAULT_MDIO_FREQ)
+		netdev_info(lp->ndev, "Setting non-standard mdio bus frequency to %u Hz\n",
+			    mdio_freq);
+
 	/* clk_div can be calculated by deriving it from the equation:
 	 * fMDIO = fHOST / ((1 + clk_div) * 2)
 	 *
@@ -209,13 +218,20 @@  static int axienet_mdio_enable(struct axienet_local *lp)
 	 * "clock-frequency" from the CPU
 	 */
 
-	lp->mii_clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1;
+	clk_div = (host_clock / (mdio_freq * 2)) - 1;
 	/* If there is any remainder from the division of
-	 * fHOST / (MAX_MDIO_FREQ * 2), then we need to add
+	 * fHOST / (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))
-		lp->mii_clk_div++;
+	if (host_clock % (mdio_freq * 2))
+		clk_div++;
+
+	/* Check for overflow of mii_clk_div */
+	if (clk_div & ~XAE_MDIO_MC_CLOCK_DIVIDE_MAX) {
+		netdev_warn(lp->ndev, "MDIO clock divisor overflow\n");
+		return -EOVERFLOW;
+	}
+	lp->mii_clk_div = (u8)clk_div;
 
 	netdev_dbg(lp->ndev,
 		   "Setting MDIO clock divisor to %u/%u Hz host clock.\n",
@@ -242,10 +258,6 @@  int axienet_mdio_setup(struct axienet_local *lp)
 	struct mii_bus *bus;
 	int ret;
 
-	ret = axienet_mdio_enable(lp);
-	if (ret < 0)
-		return ret;
-
 	bus = mdiobus_alloc();
 	if (!bus)
 		return -ENOMEM;
@@ -261,15 +273,21 @@  int axienet_mdio_setup(struct axienet_local *lp)
 	lp->mii_bus = bus;
 
 	mdio_node = of_get_child_by_name(lp->dev->of_node, "mdio");
+	ret = axienet_mdio_enable(lp, mdio_node);
+	if (ret < 0)
+		goto unregister;
 	ret = of_mdiobus_register(bus, mdio_node);
+	if (ret)
+		goto unregister;
 	of_node_put(mdio_node);
-	if (ret) {
-		mdiobus_free(bus);
-		lp->mii_bus = NULL;
-		return ret;
-	}
 	axienet_mdio_mdc_disable(lp);
 	return 0;
+
+unregister:
+	of_node_put(mdio_node);
+	mdiobus_free(bus);
+	lp->mii_bus = NULL;
+	return ret;
 }
 
 /**