From a4e06c3c7a9bbc2eff59a57cd3b395b2754ebec2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Petr=20=C5=A0tetiar?= Date: Tue, 21 May 2019 00:18:29 +0200 Subject: [PATCH] generic: ar8327: add optional gpio reset support MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Some devices like Linksys EA8500 use designated GPIO to reset the switch and if the switch isn't reset properly before first access, it can lead to unusable switch after soft reboot of the device: libphy: GPIO Bitbanged MDIO: probed mdio_bus gpio-0: MDIO device at address 0 is missing. mdio_bus gpio-0: MDIO device at address 4 is missing. Working case: libphy: GPIO Bitbanged MDIO: probed switch0: Atheros AR8337 rev. 2 switch registered on gpio-0 So this patch introduces reset GPIO, along with duration and active high/low properties which fixes the problem. Ref: https://github.com/openwrt/openwrt/pull/2047 Ref: https://bugs.openwrt.org/index.php?do=details&task_id=2168 Signed-off-by: Petr Å tetiar [ remove invalid tested-by and reported-by ] Signed-off-by: Christian Marangi --- .../generic/files/drivers/net/phy/ar8327.c | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/target/linux/generic/files/drivers/net/phy/ar8327.c b/target/linux/generic/files/drivers/net/phy/ar8327.c index 3313149559..825a9e0be9 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8327.c +++ b/target/linux/generic/files/drivers/net/phy/ar8327.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -609,6 +610,29 @@ ar8327_hw_config_pdata(struct ar8xxx_priv *priv, } #ifdef CONFIG_OF +static void +ar8327_gpio_reset(struct ar8xxx_priv *priv, struct device_node *np) +{ + int msec; + int reset_init; + bool active_high; + struct gpio_desc *reset; + + active_high = of_property_read_bool(np, "reset-active-high"); + reset_init = active_high ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; + reset = devm_gpiod_get_optional(priv->pdev, "reset", reset_init); + if (!reset) + return; + + of_property_read_u32(np, "reset-duration", &msec); + if (msec > 20) + msleep(msec); + else + usleep_range(msec * 1000, msec * 1000 + 1000); + + gpiod_set_value_cansleep(reset, !active_high); +} + static int ar8327_hw_config_of(struct ar8xxx_priv *priv, struct device_node *np) { @@ -617,6 +641,8 @@ ar8327_hw_config_of(struct ar8xxx_priv *priv, struct device_node *np) int len; int i; + ar8327_gpio_reset(priv, np); + paddr = of_get_property(np, "qca,ar8327-initvals", &len); if (!paddr || len < (2 * sizeof(*paddr))) return -EINVAL; -- 2.30.2