From 56998aa6b7f0f31ce8df23c00701af2d8e8a1f1a Mon Sep 17 00:00:00 2001 From: Luiz Angelo Daros de Luca Date: Sun, 25 Feb 2024 13:29:55 -0300 Subject: [PATCH 3/3] net: dsa: realtek: support reset controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for resetting the device using a reset controller, complementing the existing GPIO reset functionality (reset-gpios). Although the reset is optional and the driver performs a soft reset during setup, if the initial reset pin state was asserted, the driver will not detect the device until the reset is deasserted. Signed-off-by: Luiz Angelo Daros de Luca Reviewed-by: Linus Walleij Reviewed-by: Alvin Šipraga Signed-off-by: David S. Miller --- drivers/net/dsa/realtek/realtek.h | 2 ++ drivers/net/dsa/realtek/rtl83xx.c | 42 +++++++++++++++++++++++++++---- drivers/net/dsa/realtek/rtl83xx.h | 2 ++ 3 files changed, 41 insertions(+), 5 deletions(-) --- a/drivers/net/dsa/realtek/realtek.h +++ b/drivers/net/dsa/realtek/realtek.h @@ -12,6 +12,7 @@ #include #include #include +#include #define REALTEK_HW_STOP_DELAY 25 /* msecs */ #define REALTEK_HW_START_DELAY 100 /* msecs */ @@ -48,6 +49,7 @@ struct rtl8366_vlan_4k { struct realtek_priv { struct device *dev; + struct reset_control *reset_ctl; struct gpio_desc *reset; struct gpio_desc *mdc; struct gpio_desc *mdio; --- a/drivers/net/dsa/realtek/rtl83xx.c +++ b/drivers/net/dsa/realtek/rtl83xx.c @@ -185,6 +185,13 @@ rtl83xx_probe(struct device *dev, "realtek,disable-leds"); /* TODO: if power is software controlled, set up any regulators here */ + priv->reset_ctl = devm_reset_control_get_optional(dev, NULL); + if (IS_ERR(priv->reset_ctl)) { + ret = PTR_ERR(priv->reset_ctl); + dev_err_probe(dev, ret, "failed to get reset control\n"); + return ERR_CAST(priv->reset_ctl); + } + 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"); @@ -193,11 +200,11 @@ rtl83xx_probe(struct device *dev, dev_set_drvdata(dev, priv); - if (priv->reset) { - gpiod_set_value(priv->reset, 1); + if (priv->reset_ctl || priv->reset) { + rtl83xx_reset_assert(priv); dev_dbg(dev, "asserted RESET\n"); msleep(REALTEK_HW_STOP_DELAY); - gpiod_set_value(priv->reset, 0); + rtl83xx_reset_deassert(priv); msleep(REALTEK_HW_START_DELAY); dev_dbg(dev, "deasserted RESET\n"); } @@ -293,11 +300,36 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, R void rtl83xx_remove(struct realtek_priv *priv) { /* leave the device reset asserted */ - if (priv->reset) - gpiod_set_value(priv->reset, 1); + rtl83xx_reset_assert(priv); } EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA); +void rtl83xx_reset_assert(struct realtek_priv *priv) +{ + int ret; + + ret = reset_control_assert(priv->reset_ctl); + if (ret) + dev_warn(priv->dev, + "Failed to assert the switch reset control: %pe\n", + ERR_PTR(ret)); + + gpiod_set_value(priv->reset, true); +} + +void rtl83xx_reset_deassert(struct realtek_priv *priv) +{ + int ret; + + ret = reset_control_deassert(priv->reset_ctl); + if (ret) + dev_warn(priv->dev, + "Failed to deassert the switch reset control: %pe\n", + ERR_PTR(ret)); + + gpiod_set_value(priv->reset, false); +} + MODULE_AUTHOR("Luiz Angelo Daros de Luca "); MODULE_AUTHOR("Linus Walleij "); MODULE_DESCRIPTION("Realtek DSA switches common module"); --- a/drivers/net/dsa/realtek/rtl83xx.h +++ b/drivers/net/dsa/realtek/rtl83xx.h @@ -18,5 +18,7 @@ int rtl83xx_register_switch(struct realt void rtl83xx_unregister_switch(struct realtek_priv *priv); void rtl83xx_shutdown(struct realtek_priv *priv); void rtl83xx_remove(struct realtek_priv *priv); +void rtl83xx_reset_assert(struct realtek_priv *priv); +void rtl83xx_reset_deassert(struct realtek_priv *priv); #endif /* _RTL83XX_H */