All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 1/2] net: dsa: realtek: support reset controller
@ 2023-10-24 20:58 Luiz Angelo Daros de Luca
  2023-10-24 20:58 ` [PATCH net-next 2/2] dt-bindings: net: dsa: realtek: add " Luiz Angelo Daros de Luca
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-10-24 20:58 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, alsi, andrew, vivien.didelot, f.fainelli, olteanv,
	davem, kuba, pabeni, robh+dt, krzk+dt, arinc.unal,
	Luiz Angelo Daros de Luca

The 'reset-gpios' will not work when the switch reset is controlled by a
reset controller.

Although the reset is optional and the driver performs a soft reset
during setup, if the initial reset state was asserted, the driver will
not detect it.

This is an example of how to use the reset controller:

        switch {
                compatible = "realtek,rtl8366rb";

                resets = <&rst 8>;
                reset-names = "switch";

		...
	}

The reset controller will take precedence over the reset GPIO.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
---
 drivers/net/dsa/realtek/realtek-mdio.c | 36 +++++++++++++++++++++-----
 drivers/net/dsa/realtek/realtek-smi.c  | 34 +++++++++++++++++++-----
 drivers/net/dsa/realtek/realtek.h      |  6 +++++
 3 files changed, 63 insertions(+), 13 deletions(-)

diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
index 292e6d087e8b..600124c58c00 100644
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -140,6 +140,23 @@ static const struct regmap_config realtek_mdio_nolock_regmap_config = {
 	.disable_locking = true,
 };
 
+static int realtek_mdio_hwreset(struct realtek_priv *priv, bool active)
+{
+#ifdef CONFIG_RESET_CONTROLLER
+	if (priv->reset_ctl) {
+		if (active)
+			return reset_control_assert(priv->reset_ctl);
+		else
+			return reset_control_deassert(priv->reset_ctl);
+	}
+#endif
+
+	if (priv->reset)
+		gpiod_set_value(priv->reset, active);
+
+	return 0;
+}
+
 static int realtek_mdio_probe(struct mdio_device *mdiodev)
 {
 	struct realtek_priv *priv;
@@ -194,20 +211,26 @@ static int realtek_mdio_probe(struct mdio_device *mdiodev)
 
 	dev_set_drvdata(dev, priv);
 
-	/* TODO: if power is software controlled, set up any regulators here */
 	priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
 
+#ifdef CONFIG_RESET_CONTROLLER
+	priv->reset_ctl = devm_reset_control_get(dev, "switch");
+	if (IS_ERR(priv->reset_ctl)) {
+		dev_err(dev, "failed to get switch reset control\n");
+		return PTR_ERR(priv->reset_ctl);
+	}
+#endif
+
 	priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(priv->reset)) {
 		dev_err(dev, "failed to get RESET GPIO\n");
 		return PTR_ERR(priv->reset);
 	}
-
-	if (priv->reset) {
-		gpiod_set_value(priv->reset, 1);
+	if (priv->reset_ctl || priv->reset) {
+		realtek_mdio_hwreset(priv, 1);
 		dev_dbg(dev, "asserted RESET\n");
 		msleep(REALTEK_HW_STOP_DELAY);
-		gpiod_set_value(priv->reset, 0);
+		realtek_mdio_hwreset(priv, 0);
 		msleep(REALTEK_HW_START_DELAY);
 		dev_dbg(dev, "deasserted RESET\n");
 	}
@@ -246,8 +269,7 @@ static void realtek_mdio_remove(struct mdio_device *mdiodev)
 	dsa_unregister_switch(priv->ds);
 
 	/* leave the device reset asserted */
-	if (priv->reset)
-		gpiod_set_value(priv->reset, 1);
+	realtek_mdio_hwreset(priv, 1);
 }
 
 static void realtek_mdio_shutdown(struct mdio_device *mdiodev)
diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
index bfd11591faf4..751159d71223 100644
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -408,6 +408,23 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
 	return ret;
 }
 
+static int realtek_smi_hwreset(struct realtek_priv *priv, bool active)
+{
+#ifdef CONFIG_RESET_CONTROLLER
+	if (priv->reset_ctl) {
+		if (active)
+			return reset_control_assert(priv->reset_ctl);
+		else
+			return reset_control_deassert(priv->reset_ctl);
+	}
+#endif
+
+	if (priv->reset)
+		gpiod_set_value(priv->reset, active);
+
+	return 0;
+}
+
 static int realtek_smi_probe(struct platform_device *pdev)
 {
 	const struct realtek_variant *var;
@@ -457,18 +474,24 @@ static int realtek_smi_probe(struct platform_device *pdev)
 	dev_set_drvdata(dev, priv);
 	spin_lock_init(&priv->lock);
 
-	/* TODO: if power is software controlled, set up any regulators here */
+#ifdef CONFIG_RESET_CONTROLLER
+	priv->reset_ctl = devm_reset_control_get(dev, "switch");
+	if (IS_ERR(priv->reset_ctl)) {
+		dev_err(dev, "failed to get switch reset control\n");
+		return PTR_ERR(priv->reset_ctl);
+	}
+#endif
 
 	priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(priv->reset)) {
 		dev_err(dev, "failed to get RESET GPIO\n");
 		return PTR_ERR(priv->reset);
 	}
-	if (priv->reset) {
-		gpiod_set_value(priv->reset, 1);
+	if (priv->reset_ctl || priv->reset) {
+		realtek_smi_hwreset(priv, 1);
 		dev_dbg(dev, "asserted RESET\n");
 		msleep(REALTEK_HW_STOP_DELAY);
-		gpiod_set_value(priv->reset, 0);
+		realtek_smi_hwreset(priv, 0);
 		msleep(REALTEK_HW_START_DELAY);
 		dev_dbg(dev, "deasserted RESET\n");
 	}
@@ -518,8 +541,7 @@ static void realtek_smi_remove(struct platform_device *pdev)
 		of_node_put(priv->slave_mii_bus->dev.of_node);
 
 	/* leave the device reset asserted */
-	if (priv->reset)
-		gpiod_set_value(priv->reset, 1);
+	realtek_smi_hwreset(priv, 1);
 }
 
 static void realtek_smi_shutdown(struct platform_device *pdev)
diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
index 4fa7c6ba874a..ad61e5c13f96 100644
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -12,6 +12,9 @@
 #include <linux/platform_device.h>
 #include <linux/gpio/consumer.h>
 #include <net/dsa.h>
+#ifdef CONFIG_RESET_CONTROLLER
+#include <linux/reset.h>
+#endif
 
 #define REALTEK_HW_STOP_DELAY		25	/* msecs */
 #define REALTEK_HW_START_DELAY		100	/* msecs */
@@ -48,6 +51,9 @@ struct rtl8366_vlan_4k {
 
 struct realtek_priv {
 	struct device		*dev;
+#ifdef CONFIG_RESET_CONTROLLER
+	struct reset_control    *reset_ctl;
+#endif
 	struct gpio_desc	*reset;
 	struct gpio_desc	*mdc;
 	struct gpio_desc	*mdio;
-- 
2.42.0


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

end of thread, other threads:[~2023-10-26 22:03 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-24 20:58 [PATCH net-next 1/2] net: dsa: realtek: support reset controller Luiz Angelo Daros de Luca
2023-10-24 20:58 ` [PATCH net-next 2/2] dt-bindings: net: dsa: realtek: add " Luiz Angelo Daros de Luca
2023-10-24 22:39   ` Vladimir Oltean
2023-10-26 10:34   ` Arınç ÜNAL
2023-10-26 20:09     ` Luiz Angelo Daros de Luca
2023-10-26 20:58   ` Rob Herring
2023-10-26 22:03     ` Luiz Angelo Daros de Luca
2023-10-24 21:09 ` [PATCH net-next 1/2] net: dsa: realtek: support " Florian Fainelli
2023-10-24 22:02   ` Luiz Angelo Daros de Luca
2023-10-24 22:06     ` Florian Fainelli
2023-10-24 22:07     ` Vladimir Oltean
2023-10-24 22:17 ` Luiz Angelo Daros de Luca
2023-10-24 22:32   ` Andrew Lunn
2023-10-24 22:33 ` Vladimir Oltean
2023-10-25 18:30   ` Luiz Angelo Daros de Luca

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.