diff mbox series

[v2,1/2] net: mdio: Handle bus level GPIO Reset

Message ID 20240228-for-2024-07-am65-cpsw-mdio-v2-1-f74f972eafeb@kernel.org
State Accepted
Commit a0e02c66194593a9983229781c2c6fb51f5b052f
Delegated to: Tom Rini
Headers show
Series net: ti: am65-cpsw / cpsw-mdio: Switch to DM MDIO | expand

Commit Message

Roger Quadros Feb. 28, 2024, 10:35 a.m. UTC
Some platforms have bus level Reset controlled
by a GPIO line. If available then handle bus reset
via GPIO.

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
Changelog:
v2:
- Fix build if DM_GPIO not set
- Fix build on platforms that don't have <asm/gpio.h>
  by using <asm-generic/gpio.h>
---
 include/phy.h     |  7 +++++++
 net/mdio-uclass.c | 37 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 43 insertions(+), 1 deletion(-)

Comments

Tom Rini March 7, 2024, 5:12 p.m. UTC | #1
On Wed, Feb 28, 2024 at 12:35:26PM +0200, Roger Quadros wrote:

> Some platforms have bus level Reset controlled
> by a GPIO line. If available then handle bus reset
> via GPIO.
> 
> Signed-off-by: Roger Quadros <rogerq@kernel.org>

Applied to u-boot/next, thanks!
diff mbox series

Patch

diff --git a/include/phy.h b/include/phy.h
index e02cbdb58c..ae23814bbf 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -9,6 +9,7 @@ 
 #ifndef _PHY_H
 #define _PHY_H
 
+#include <asm-generic/gpio.h>
 #include <log.h>
 #include <phy_interface.h>
 #include <dm/ofnode.h>
@@ -76,6 +77,12 @@  struct mii_dev {
 	int (*reset)(struct mii_dev *bus);
 	struct phy_device *phymap[PHY_MAX_ADDR];
 	u32 phy_mask;
+	/** @reset_delay_us: Bus GPIO reset pulse width in microseconds */
+	int reset_delay_us;
+	/** @reset_post_delay_us: Bus GPIO reset deassert delay in microseconds */
+	int reset_post_delay_us;
+	/** @reset_gpiod: Bus Reset GPIO descriptor pointer */
+	struct gpio_desc reset_gpiod;
 };
 
 /* struct phy_driver: a structure which defines PHY behavior
diff --git a/net/mdio-uclass.c b/net/mdio-uclass.c
index e758cc66d7..6fc7034111 100644
--- a/net/mdio-uclass.c
+++ b/net/mdio-uclass.c
@@ -14,6 +14,9 @@ 
 #include <dm/of_extra.h>
 #include <dm/uclass-internal.h>
 #include <linux/compat.h>
+#include <linux/delay.h>
+
+#define DEFAULT_GPIO_RESET_DELAY	10	/* in microseconds */
 
 void dm_mdio_probe_devices(void)
 {
@@ -80,6 +83,16 @@  int dm_mdio_write(struct udevice *mdio_dev, int addr, int devad, int reg,
 int dm_mdio_reset(struct udevice *mdio_dev)
 {
 	struct mdio_ops *ops = mdio_get_ops(mdio_dev);
+	struct mdio_perdev_priv *pdata = dev_get_uclass_priv(mdio_dev);
+	struct mii_dev *mii_bus = pdata->mii_bus;
+
+	if (CONFIG_IS_ENABLED(DM_GPIO) && dm_gpio_is_valid(&mii_bus->reset_gpiod)) {
+		dm_gpio_set_value(&mii_bus->reset_gpiod, 1);
+		udelay(mii_bus->reset_delay_us);
+		dm_gpio_set_value(&mii_bus->reset_gpiod, 0);
+		if (mii_bus->reset_post_delay_us > 0)
+			udelay(mii_bus->reset_post_delay_us);
+	}
 
 	if (!ops->reset)
 		return 0;
@@ -111,14 +124,36 @@  static int mdio_reset(struct mii_dev *mii_bus)
 static int dm_mdio_post_probe(struct udevice *dev)
 {
 	struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
+	struct mii_dev *mii_bus;
+	int ret;
 
-	pdata->mii_bus = mdio_alloc();
+	mii_bus = mdio_alloc();
+	if (!mii_bus) {
+		dev_err(dev, "couldn't allocate mii_bus\n");
+		return -ENOMEM;
+	}
+	pdata->mii_bus = mii_bus;
 	pdata->mii_bus->read = mdio_read;
 	pdata->mii_bus->write = mdio_write;
 	pdata->mii_bus->reset = mdio_reset;
 	pdata->mii_bus->priv = dev;
 	strlcpy(pdata->mii_bus->name, dev->name, MDIO_NAME_LEN);
 
+	if (IS_ENABLED(CONFIG_DM_GPIO)) {
+		/* Get bus level PHY reset GPIO details */
+		mii_bus->reset_delay_us = dev_read_u32_default(dev, "reset-delay-us",
+							       DEFAULT_GPIO_RESET_DELAY);
+		mii_bus->reset_post_delay_us = dev_read_u32_default(dev,
+								    "reset-post-delay-us",
+								    0);
+		ret = gpio_request_by_name(dev, "reset-gpios", 0, &mii_bus->reset_gpiod,
+					   GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+		if (ret && ret != -ENOENT) {
+			dev_err(dev, "couldn't get reset-gpios: %d\n", ret);
+			return ret;
+		}
+	}
+
 	return mdio_register(pdata->mii_bus);
 }