diff mbox series

[SRU,F,PULL,v2,14/23] Revert "UBUNTU: SAUCE: Address upstream comments from patch v6 for PHY driver"

Message ID 20210709190830.5405-15-asmaa@nvidia.com
State New
Headers show
Series Cherry-pick the upstreamed mlxbf-gige driver | expand

Commit Message

Asmaa Mnebhi July 9, 2021, 7:08 p.m. UTC
BugLink: https://bugs.launchpad.net/bugs/1934923

This reverts commit e65518a6eeb7dc24198700b1ec7e96ffdeab2b46.

Signed-off-by: Asmaa Mnebhi <asmaa@nvidia.com>
---
 .../net/ethernet/mellanox/mlxbf_gige/Kconfig  |   2 +-
 .../net/ethernet/mellanox/mlxbf_gige/Makefile |   2 +-
 .../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h |  10 +-
 .../mellanox/mlxbf_gige/mlxbf_gige_main.c     | 103 ++-------
 .../mellanox/mlxbf_gige/mlxbf_gige_mdio.c     | 208 ++++++++++++++----
 .../mellanox/mlxbf_gige/mlxbf_gige_regs.h     |   4 +-
 6 files changed, 192 insertions(+), 137 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/Kconfig b/drivers/net/ethernet/mellanox/mlxbf_gige/Kconfig
index 41c7a8997190..73c5d74081ee 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/Kconfig
@@ -1,4 +1,4 @@ 
-# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
+# SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB
 #
 # Mellanox GigE driver configuration
 #
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile
index e99fc19ac819..f6be6c692093 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/Makefile
@@ -1,4 +1,4 @@ 
-# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
+# SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB
 
 obj-$(CONFIG_MLXBF_GIGE) += mlxbf_gige.o
 
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h
index 63e07e60108d..f89199d562ad 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h
@@ -1,10 +1,10 @@ 
-/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */
+/* SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB */
 
 /* Header file for Gigabit Ethernet driver for Mellanox BlueField SoC
  * - this file contains software data structures and any chip-specific
  *   data structures (e.g. TX WQE format) that are memory resident.
  *
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020 Mellanox Technologies Ltd.
  */
 
 #ifndef __MLXBF_GIGE_H__
@@ -101,13 +101,9 @@  struct mlxbf_gige {
 	int error_irq;
 	int rx_irq;
 	int llu_plu_irq;
-	int phy_irq;
 	bool promisc_enabled;
 	struct napi_struct napi;
 	struct mlxbf_gige_stats stats;
-	u32 tx_pause;
-	u32 rx_pause;
-	u32 aneg_pause;
 };
 
 /* Rx Work Queue Element definitions */
@@ -155,6 +151,6 @@  enum mlxbf_gige_res {
 int mlxbf_gige_mdio_probe(struct platform_device *pdev,
 			  struct mlxbf_gige *priv);
 void mlxbf_gige_mdio_remove(struct mlxbf_gige *priv);
-irqreturn_t mlxbf_gige_mdio_handle_phy_interrupt(int irq, void *dev_id);
+irqreturn_t mlxbf_gige_mdio_handle_phy_interrupt(struct mlxbf_gige *priv);
 
 #endif /* !defined(__MLXBF_GIGE_H__) */
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
index 0fd540bc50f7..d650e9c0a57f 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
@@ -1,8 +1,8 @@ 
-// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
+// SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB
 
 /* Gigabit Ethernet driver for Mellanox BlueField SoC
  *
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020 Mellanox Technologies Ltd.
  */
 
 #include <linux/acpi.h>
@@ -18,7 +18,7 @@ 
 #include "mlxbf_gige_regs.h"
 
 #define DRV_NAME    "mlxbf_gige"
-#define DRV_VERSION "1.3"
+#define DRV_VERSION "1.2"
 
 static void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv,
 					 unsigned int index, u64 dmac)
@@ -474,11 +474,9 @@  static void mlxbf_gige_get_ethtool_stats(struct net_device *netdev,
 static void mlxbf_gige_get_pauseparam(struct net_device *netdev,
 				      struct ethtool_pauseparam *pause)
 {
-	struct mlxbf_gige *priv = netdev_priv(netdev);
-
-	pause->autoneg = priv->aneg_pause;
-	pause->rx_pause = priv->tx_pause;
-	pause->tx_pause = priv->rx_pause;
+	pause->autoneg = AUTONEG_ENABLE;
+	pause->rx_pause = 1;
+	pause->tx_pause = 1;
 }
 
 static const struct ethtool_ops mlxbf_gige_ethtool_ops = {
@@ -496,6 +494,20 @@  static const struct ethtool_ops mlxbf_gige_ethtool_ops = {
 	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
 };
 
+static void mlxbf_gige_handle_link_change(struct net_device *netdev)
+{
+	struct mlxbf_gige *priv = netdev_priv(netdev);
+	struct phy_device *phydev = netdev->phydev;
+	irqreturn_t ret;
+
+	ret = mlxbf_gige_mdio_handle_phy_interrupt(priv);
+	if (ret != IRQ_HANDLED)
+		return;
+
+	/* print new link status only if the interrupt came from the PHY */
+	phy_print_status(phydev);
+}
+
 /* Start of struct net_device_ops functions */
 static irqreturn_t mlxbf_gige_error_intr(int irq, void *dev_id)
 {
@@ -789,15 +801,6 @@  static int mlxbf_gige_request_irqs(struct mlxbf_gige *priv)
 		return err;
 	}
 
-	err = request_threaded_irq(priv->phy_irq, NULL,
-			       mlxbf_gige_mdio_handle_phy_interrupt,
-			       IRQF_ONESHOT | IRQF_SHARED, "mlxbf_gige_phy",
-			       priv);
-	if (err) {
-		dev_err(priv->dev, "Request phy_irq failure\n");
-		return err;
-	}
-
 	return 0;
 }
 
@@ -806,7 +809,6 @@  static void mlxbf_gige_free_irqs(struct mlxbf_gige *priv)
 	devm_free_irq(priv->dev, priv->error_irq, priv);
 	devm_free_irq(priv->dev, priv->rx_irq, priv);
 	devm_free_irq(priv->dev, priv->llu_plu_irq, priv);
-	free_irq(priv->phy_irq, priv);
 }
 
 static void mlxbf_gige_cache_stats(struct mlxbf_gige *priv)
@@ -848,38 +850,6 @@  static void mlxbf_gige_clean_port(struct mlxbf_gige *priv)
 	writeq(control, priv->base + MLXBF_GIGE_CONTROL);
 }
 
-static int mlxbf_gige_phy_enable_interrupt(struct phy_device *phydev)
-{
-	int ret = 0;
-
-	if (phydev->drv->ack_interrupt)
-		ret = phydev->drv->ack_interrupt(phydev);
-	if (ret < 0)
-		return ret;
-
-	phydev->interrupts = PHY_INTERRUPT_ENABLED;
-	if (phydev->drv->config_intr)
-		ret = phydev->drv->config_intr(phydev);
-
-	return ret;
-}
-
-static int mlxbf_gige_phy_disable_interrupt(struct phy_device *phydev)
-{
-	int ret = 0;
-
-	if (phydev->drv->ack_interrupt)
-		ret = phydev->drv->ack_interrupt(phydev);
-	if (ret < 0)
-		return ret;
-
-	phydev->interrupts = PHY_INTERRUPT_DISABLED;
-	if (phydev->drv->config_intr)
-		ret = phydev->drv->config_intr(phydev);
-
-	return ret;
-}
-
 static int mlxbf_gige_open(struct net_device *netdev)
 {
 	struct mlxbf_gige *priv = netdev_priv(netdev);
@@ -900,14 +870,6 @@  static int mlxbf_gige_open(struct net_device *netdev)
 		return err;
 
 	phy_start(phydev);
-	/* Always make sure interrupts are enabled since phy_start calls
-	 * __phy_resume which may reset the PHY interrupt control reg.
-	 * __phy_resume only reenables the interrupts if
-	 * phydev->irq != IRQ_IGNORE_INTERRUPT.
-	 */
-	err = mlxbf_gige_phy_enable_interrupt(phydev);
-	if (err)
-		return err;
 
 	/* Set bits in INT_EN that we care about */
 	int_en = MLXBF_GIGE_INT_EN_HW_ACCESS_ERROR |
@@ -932,8 +894,8 @@  static int mlxbf_gige_stop(struct net_device *netdev)
 	netif_napi_del(&priv->napi);
 	mlxbf_gige_free_irqs(priv);
 
-	phy_stop(netdev->phydev);
-	mlxbf_gige_phy_disable_interrupt(netdev->phydev);
+	if (netdev->phydev)
+		phy_stop(netdev->phydev);
 
 	mlxbf_gige_rx_deinit(priv);
 	mlxbf_gige_tx_deinit(priv);
@@ -1111,12 +1073,6 @@  static void mlxbf_gige_initial_mac(struct mlxbf_gige *priv)
 				     local_mac);
 }
 
-static void mlxbf_gige_adjust_link(struct net_device *netdev)
-{
-	/* Only one speed and one duplex supported */
-	return;
-}
-
 static int mlxbf_gige_probe(struct platform_device *pdev)
 {
 	struct phy_device *phydev;
@@ -1130,7 +1086,6 @@  static int mlxbf_gige_probe(struct platform_device *pdev)
 	void __iomem *base;
 	u64 control;
 	int err = 0;
-	int addr;
 
 	mac_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_MAC);
 	if (!mac_res)
@@ -1202,21 +1157,16 @@  static int mlxbf_gige_probe(struct platform_device *pdev)
 	priv->error_irq = platform_get_irq(pdev, MLXBF_GIGE_ERROR_INTR_IDX);
 	priv->rx_irq = platform_get_irq(pdev, MLXBF_GIGE_RECEIVE_PKT_INTR_IDX);
 	priv->llu_plu_irq = platform_get_irq(pdev, MLXBF_GIGE_LLU_PLU_INTR_IDX);
-	priv->phy_irq = platform_get_irq(pdev, MLXBF_GIGE_PHY_INT_N);
 
 	phydev = phy_find_first(priv->mdiobus);
 	if (!phydev)
-		return -ENODEV;
-
-	addr = phydev->mdio.addr;
-	phydev->irq = priv->mdiobus->irq[addr] = PHY_IGNORE_INTERRUPT;
+		return -EIO;
 
 	/* Sets netdev->phydev to phydev; which will eventually
 	 * be used in ioctl calls.
-	 * Cannot pass NULL handler.
 	 */
 	err = phy_connect_direct(netdev, phydev,
-				 mlxbf_gige_adjust_link,
+				 mlxbf_gige_handle_link_change,
 				 PHY_INTERFACE_MODE_GMII);
 	if (err) {
 		dev_err(&pdev->dev, "Could not attach to PHY\n");
@@ -1233,11 +1183,6 @@  static int mlxbf_gige_probe(struct platform_device *pdev)
 	/* MAC supports symmetric flow control */
 	phy_support_sym_pause(phydev);
 
-	/* Enable pause */
-	priv->rx_pause = phydev->pause;
-	priv->tx_pause = phydev->pause;
-	priv->aneg_pause = AUTONEG_ENABLE;
-
 	/* Display information about attached PHY device */
 	phy_attached_info(phydev);
 
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c
index 464bfac9a650..7a225036ab59 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c
@@ -1,7 +1,7 @@ 
-// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
+// SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB
 /*  MDIO support for Mellanox GigE driver
  *
- *  Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *  Copyright (c) 2020 Mellanox Technologies Ltd.
  */
 
 #include <linux/acpi.h>
@@ -10,7 +10,6 @@ 
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/iopoll.h>
 #include <linux/ioport.h>
 #include <linux/irqreturn.h>
 #include <linux/jiffies.h>
@@ -22,6 +21,9 @@ 
 
 #include "mlxbf_gige.h"
 
+#define MLXBF_GIGE_MDIO_POLL_BUSY_TIMEOUT	100 /* ms */
+#define MLXBF_GIGE_MDIO_POLL_DELAY_USEC		100 /* us */
+
 #define MLXBF_GIGE_MDIO_GW_OFFSET	0x0
 #define MLXBF_GIGE_MDIO_CFG_OFFSET	0x4
 
@@ -32,6 +34,8 @@ 
 
 /* Busy bit is set by software and cleared by hardware */
 #define MLXBF_GIGE_MDIO_SET_BUSY	0x1
+/* Lock bit should be set/cleared by software */
+#define MLXBF_GIGE_MDIO_SET_LOCK	0x1
 
 /* MDIO GW register bits */
 #define MLXBF_GIGE_MDIO_GW_AD_MASK	GENMASK(15, 0)
@@ -40,6 +44,7 @@ 
 #define MLXBF_GIGE_MDIO_GW_OPCODE_MASK	GENMASK(27, 26)
 #define MLXBF_GIGE_MDIO_GW_ST1_MASK	GENMASK(28, 28)
 #define MLXBF_GIGE_MDIO_GW_BUSY_MASK	GENMASK(30, 30)
+#define MLXBF_GIGE_MDIO_GW_LOCK_MASK	GENMASK(31, 31)
 
 /* MDIO config register bits */
 #define MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK		GENMASK(1, 0)
@@ -63,13 +68,20 @@ 
 
 #define MLXBF_GIGE_MDIO_PERIOD	(((MLXBF_GIGE_MDC_CLK_NS * MLXBF_GIGE_I1CLK_MHZ / 1000) / 2) - 1)
 
-#define MLXBF_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \
-				 FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \
-				 FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \
-				 FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK, \
-				 	    MLXBF_GIGE_MDIO_PERIOD) | \
-				 FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \
-				 FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13))
+/* PHY should operate in master mode only */
+#define MLXBF_GIGE_MDIO_MODE_MASTER	1
+
+/* PHY input voltage has to be 3.3V */
+#define MLXBF_GIGE_MDIO3_3		1
+
+/* Operate in full drive mode */
+#define MLXBF_GIGE_MDIO_FULL_DRIVE	1
+
+/* 6 cycles before the i1clk (core clock) rising edge that triggers the mdc */
+#define	MLXBF_GIGE_MDIO_IN_SAMP 	6
+
+/* 13 cycles after the i1clk (core clock) rising edge that triggers the mdc */
+#define MLXBF_GIGE_MDIO_OUT_SAMP 	13
 
 /* The PHY interrupt line is shared with other interrupt lines such
  * as GPIO and SMBus. So use YU registers to determine whether the
@@ -87,10 +99,6 @@ 
 #define MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE	0x98
 
 #define MLXBF_GIGE_GPIO12_BIT			12
-#define MLXBF_GIGE_CAUSE_OR_CAUSE_EVTEN0_MASK	BIT(MLXBF_GIGE_GPIO12_BIT)
-#define MLXBF_GIGE_CAUSE_OR_EVTEN0_MASK		BIT(MLXBF_GIGE_GPIO12_BIT)
-#define MLXBF_GIGE_CAUSE_FALL_EN_MASK		BIT(MLXBF_GIGE_GPIO12_BIT)
-#define MLXBF_GIGE_CAUSE_OR_CLRCAUSE_MASK	BIT(MLXBF_GIGE_GPIO12_BIT)
 
 static u32 mlxbf_gige_mdio_create_cmd(u16 data, int phy_add,
 				      int phy_reg, u32 opcode)
@@ -106,36 +114,65 @@  static u32 mlxbf_gige_mdio_create_cmd(u16 data, int phy_add,
 	gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_BUSY_MASK,
 			     MLXBF_GIGE_MDIO_SET_BUSY);
 
+	/* Hold the lock until the read/write is completed so that no other
+	 * program accesses the mdio bus.
+	 */
+	gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_LOCK_MASK,
+			     MLXBF_GIGE_MDIO_SET_LOCK);
+
 	return gw_reg;
 }
 
+static int mlxbf_gige_mdio_poll_bit(struct mlxbf_gige *priv, u32 bit_mask)
+{
+	unsigned long timeout;
+	u32 val;
+
+	timeout = jiffies + msecs_to_jiffies(MLXBF_GIGE_MDIO_POLL_BUSY_TIMEOUT);
+	do {
+		val = readl(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
+		if (!(val & bit_mask))
+			return 0;
+		udelay(MLXBF_GIGE_MDIO_POLL_DELAY_USEC);
+	} while (time_before(jiffies, timeout));
+
+	return -ETIME;
+}
+
 static int mlxbf_gige_mdio_read(struct mii_bus *bus, int phy_add, int phy_reg)
 {
 	struct mlxbf_gige *priv = bus->priv;
 	u32 cmd;
-	int ret;
-	u32 val;
+	u32 ret;
 
-	if (phy_reg & MII_ADDR_C45)
-		return -EOPNOTSUPP;
+	/* If the lock is held by something else, drop the request.
+	 * If the lock is cleared, that means the busy bit was cleared.
+	 */
+	ret = mlxbf_gige_mdio_poll_bit(priv, MLXBF_GIGE_MDIO_GW_LOCK_MASK);
+	if (ret)
+		return -EBUSY;
 
 	/* Send mdio read request */
 	cmd = mlxbf_gige_mdio_create_cmd(0, phy_add, phy_reg, MLXBF_GIGE_MDIO_CL22_READ);
 
 	writel(cmd, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
 
-	ret = readl_poll_timeout_atomic(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET,
-					val, !(val & MLXBF_GIGE_MDIO_GW_BUSY_MASK), 100, 1000000);
-
+	ret = mlxbf_gige_mdio_poll_bit(priv, MLXBF_GIGE_MDIO_GW_BUSY_MASK);
 	if (ret) {
 		writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
-		return ret;
+		return -EBUSY;
 	}
 
 	ret = readl(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
 	/* Only return ad bits of the gw register */
 	ret &= MLXBF_GIGE_MDIO_GW_AD_MASK;
 
+	/* To release the YU MDIO lock, clear gw register,
+	 * so that the YU does not confuse this write with a new
+	 * MDIO read/write request.
+	 */
+	writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
+
 	return ret;
 }
 
@@ -145,10 +182,13 @@  static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add,
 	struct mlxbf_gige *priv = bus->priv;
 	u32 cmd;
 	int ret;
-	u32 temp;
 
-	if (phy_reg & MII_ADDR_C45)
-		return -EOPNOTSUPP;
+	/* If the lock is held by something else, drop the request.
+	 * If the lock is cleared, that means the busy bit was cleared.
+	 */
+	ret = mlxbf_gige_mdio_poll_bit(priv, MLXBF_GIGE_MDIO_GW_LOCK_MASK);
+	if (ret)
+		return -EBUSY;
 
 	/* Send mdio write request */
 	cmd = mlxbf_gige_mdio_create_cmd(val, phy_add, phy_reg,
@@ -156,8 +196,13 @@  static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add,
 	writel(cmd, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
 
 	/* If the poll timed out, drop the request */
-	ret = readl_poll_timeout_atomic(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET,
-					temp, !(temp & MLXBF_GIGE_MDIO_GW_BUSY_MASK), 100, 1000000);
+	ret = mlxbf_gige_mdio_poll_bit(priv, MLXBF_GIGE_MDIO_GW_BUSY_MASK);
+
+	/* To release the YU MDIO lock, clear gw register,
+	 * so that the YU does not confuse this write as a new
+	 * MDIO read/write request.
+	 */
+	writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
 
 	return ret;
 }
@@ -169,7 +214,7 @@  static void mlxbf_gige_mdio_disable_phy_int(struct mlxbf_gige *priv)
 
 	spin_lock_irqsave(&priv->gpio_lock, flags);
 	val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0);
-	val &= ~MLXBF_GIGE_CAUSE_OR_EVTEN0_MASK;
+	val &= ~priv->phy_int_gpio_mask;
 	writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0);
 	spin_unlock_irqrestore(&priv->gpio_lock, flags);
 }
@@ -185,13 +230,13 @@  static void mlxbf_gige_mdio_enable_phy_int(struct mlxbf_gige *priv)
 	 * state goes low.
 	 */
 	val = readl(priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_FALL_EN);
-	val |= MLXBF_GIGE_CAUSE_FALL_EN_MASK;
+	val |= priv->phy_int_gpio_mask;
 	writel(val, priv->gpio_io + MLXBF_GIGE_GPIO_CAUSE_FALL_EN);
 
 	/* Enable PHY interrupt by setting the priority level */
 	val = readl(priv->gpio_io +
 			MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0);
-	val |= MLXBF_GIGE_CAUSE_OR_EVTEN0_MASK;
+	val |= priv->phy_int_gpio_mask;
 	writel(val, priv->gpio_io +
 			MLXBF_GIGE_GPIO_CAUSE_OR_EVTEN0);
 	spin_unlock_irqrestore(&priv->gpio_lock, flags);
@@ -200,25 +245,33 @@  static void mlxbf_gige_mdio_enable_phy_int(struct mlxbf_gige *priv)
 /* Interrupt handler is called from mlxbf_gige_main.c
  * driver whenever a phy interrupt is received.
  */
-irqreturn_t mlxbf_gige_mdio_handle_phy_interrupt(int irq, void *dev_id)
+irqreturn_t mlxbf_gige_mdio_handle_phy_interrupt(struct mlxbf_gige *priv)
 {
-	struct phy_device *phydev;
-	struct mlxbf_gige *priv;
 	u32 val;
 
-	priv = dev_id;
-	phydev = priv->netdev->phydev;
+	/* The YU interrupt is shared between SMBus and GPIOs.
+	 * So first, determine whether this is a GPIO interrupt.
+	 */
+	val = readl(priv->cause_rsh_coalesce0_io);
+	if (!MLXBF_GIGE_GPIO_CAUSE_IRQ_IS_SET(val)) {
+		/* Nothing to do here, not a GPIO interrupt */
+		return IRQ_NONE;
+	}
+	/* Then determine which gpio register this interrupt is for.
+	 * Return if the interrupt is not for gpio block 0.
+	 */
+	val = readl(priv->cause_gpio_arm_coalesce0_io);
+	if (!(val & MLXBF_GIGE_GPIO_BLOCK0_MASK))
+		return IRQ_NONE;
 
-	/* Check if this interrupt is from PHY device.
+	/* Finally check if this interrupt is from PHY device.
 	 * Return if it is not.
 	 */
 	val = readl(priv->gpio_io +
 			MLXBF_GIGE_GPIO_CAUSE_OR_CAUSE_EVTEN0);
-	if (!(val & MLXBF_GIGE_CAUSE_OR_CAUSE_EVTEN0_MASK))
+	if (!(val & priv->phy_int_gpio_mask))
 		return IRQ_NONE;
 
-	phy_mac_interrupt(phydev);
-
 	/* Clear interrupt when done, otherwise, no further interrupt
 	 * will be triggered.
 	 * Writing 0x1 to the clear cause register also clears the
@@ -228,22 +281,67 @@  irqreturn_t mlxbf_gige_mdio_handle_phy_interrupt(int irq, void *dev_id)
 	 */
 	val = readl(priv->gpio_io +
 			MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE);
-	val |= MLXBF_GIGE_CAUSE_OR_CLRCAUSE_MASK;
+	val |= priv->phy_int_gpio_mask;
 	writel(val, priv->gpio_io +
 			MLXBF_GIGE_GPIO_CAUSE_OR_CLRCAUSE);
 
-	/* Make sure to clear the PHY device interrupt */
-	if (phydev->drv->ack_interrupt)
-		phydev->drv->ack_interrupt(phydev);
-
 	return IRQ_HANDLED;
 }
 
+static void mlxbf_gige_mdio_init_config(struct mlxbf_gige *priv)
+{
+	struct device *dev = priv->dev;
+	u32 mdio_full_drive;
+	u32 mdio_out_sample;
+	u32 mdio_in_sample;
+	u32 mdio_voltage;
+	u32 mdc_period;
+	u32 mdio_mode;
+	u32 mdio_cfg;
+	int ret;
+
+	ret = device_property_read_u32(dev, "mdio-mode", &mdio_mode);
+	if (ret < 0)
+		mdio_mode = MLXBF_GIGE_MDIO_MODE_MASTER;
+
+	ret = device_property_read_u32(dev, "mdio-voltage", &mdio_voltage);
+	if (ret < 0)
+		mdio_voltage = MLXBF_GIGE_MDIO3_3;
+
+	ret = device_property_read_u32(dev, "mdio-full-drive", &mdio_full_drive);
+	if (ret < 0)
+		mdio_full_drive = MLXBF_GIGE_MDIO_FULL_DRIVE;
+
+	ret = device_property_read_u32(dev, "mdc-period", &mdc_period);
+	if (ret < 0)
+		mdc_period = MLXBF_GIGE_MDIO_PERIOD;
+
+	ret = device_property_read_u32(dev, "mdio-in-sample", &mdio_in_sample);
+	if (ret < 0)
+		mdio_in_sample = MLXBF_GIGE_MDIO_IN_SAMP;
+
+	ret = device_property_read_u32(dev, "mdio-out-sample", &mdio_out_sample);
+	if (ret < 0)
+		mdio_out_sample = MLXBF_GIGE_MDIO_OUT_SAMP;
+
+	mdio_cfg = FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, mdio_mode) |
+		   FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, mdio_voltage) |
+		   FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, mdio_full_drive) |
+		   FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK, mdc_period) |
+		   FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, mdio_in_sample) |
+		   FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, mdio_out_sample);
+
+	writel(mdio_cfg, priv->mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET);
+}
+
 int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
 {
 	struct device *dev = &pdev->dev;
 	struct resource *res;
+	u32 phy_int_gpio;
+	u32 phy_addr;
 	int ret;
+	int irq;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_MDIO9);
 	if (!res)
@@ -281,9 +379,12 @@  int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
 	if (!priv->cause_gpio_arm_coalesce0_io)
 		return -ENOMEM;
 
-	/* Configure mdio parameters */
-	writel(MLXBF_GIGE_MDIO_CFG_VAL,
-	       priv->mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET);
+	mlxbf_gige_mdio_init_config(priv);
+
+	ret = device_property_read_u32(dev, "phy-int-gpio", &phy_int_gpio);
+	if (ret < 0)
+		phy_int_gpio = MLXBF_GIGE_GPIO12_BIT;
+	priv->phy_int_gpio_mask = BIT(phy_int_gpio);
 
 	mlxbf_gige_mdio_enable_phy_int(priv);
 
@@ -301,6 +402,19 @@  int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
 	snprintf(priv->mdiobus->id, MII_BUS_ID_SIZE, "%s",
 		 dev_name(dev));
 
+	ret = device_property_read_u32(dev, "phy-addr", &phy_addr);
+	if (ret < 0)
+		phy_addr = MLXBF_GIGE_MDIO_DEFAULT_PHY_ADDR;
+
+	irq = platform_get_irq(pdev, MLXBF_GIGE_PHY_INT_N);
+	if (irq < 0) {
+		dev_err(dev, "Failed to retrieve irq 0x%x\n", irq);
+		return -ENODEV;
+	}
+	priv->mdiobus->irq[phy_addr] = PHY_POLL;
+
+	/* Auto probe PHY at the corresponding address */
+	priv->mdiobus->phy_mask = ~(1 << phy_addr);
 	ret = mdiobus_register(priv->mdiobus);
 	if (ret)
 		dev_err(dev, "Failed to register MDIO bus\n");
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h
index 06e3c7145bbd..9c7af820c197 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h
@@ -1,8 +1,8 @@ 
-/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */
+/* SPDX-License-Identifier: GPL-2.0-only OR Linux-OpenIB */
 
 /* Header file for Mellanox BlueField GigE register defines
  *
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020 Mellanox Technologies Ltd.
  */
 
 #ifndef __MLXBF_GIGE_REGS_H__