kernel: backport some upstream at803x fixes
authorFelix Fietkau <nbd@nbd.name>
Tue, 29 Nov 2016 16:55:41 +0000 (17:55 +0100)
committerFelix Fietkau <nbd@nbd.name>
Sun, 4 Dec 2016 10:41:49 +0000 (11:41 +0100)
Signed-off-by: Felix Fietkau <nbd@nbd.name>
target/linux/generic/patches-4.4/736-at803x-fix-reset-handling.patch [new file with mode: 0644]
target/linux/generic/patches-4.4/737-net-phy-at803x-Request-reset-GPIO-only-for-AT8030-PH.patch [new file with mode: 0644]
target/linux/generic/patches-4.4/738-net-phy-at803x-only-the-AT8030-needs-a-hardware-rese.patch [new file with mode: 0644]

diff --git a/target/linux/generic/patches-4.4/736-at803x-fix-reset-handling.patch b/target/linux/generic/patches-4.4/736-at803x-fix-reset-handling.patch
new file mode 100644 (file)
index 0000000..91c2334
--- /dev/null
@@ -0,0 +1,43 @@
+From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Date: Wed, 23 Mar 2016 00:44:40 +0300
+Subject: [PATCH] at803x: fix reset handling
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The driver of course "knows" that the chip's reset signal is active low,
+so  it drives the GPIO to 0  to reset the PHY and to 1 otherwise; however
+all this will only work iff the GPIO  is  specified as active-high in the
+device tree!  I think both the driver and the device trees (if there are
+any -- I was unable to find them) need to be fixed in this case...
+
+Fixes: 13a56b449325 ("net: phy: at803x: Add support for hardware reset")
+Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -250,7 +250,7 @@ static int at803x_probe(struct phy_devic
+       if (!priv)
+               return -ENOMEM;
+-      gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
++      gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(gpiod_reset))
+               return PTR_ERR(gpiod_reset);
+@@ -377,10 +377,10 @@ static void at803x_link_change_notify(st
+                               at803x_context_save(phydev, &context);
+-                              gpiod_set_value(priv->gpiod_reset, 0);
+-                              msleep(1);
+                               gpiod_set_value(priv->gpiod_reset, 1);
+                               msleep(1);
++                              gpiod_set_value(priv->gpiod_reset, 0);
++                              msleep(1);
+                               at803x_context_restore(phydev, &context);
diff --git a/target/linux/generic/patches-4.4/737-net-phy-at803x-Request-reset-GPIO-only-for-AT8030-PH.patch b/target/linux/generic/patches-4.4/737-net-phy-at803x-Request-reset-GPIO-only-for-AT8030-PH.patch
new file mode 100644 (file)
index 0000000..b30ba7a
--- /dev/null
@@ -0,0 +1,42 @@
+From: Sebastian Frias <sf84@laposte.net>
+Date: Wed, 23 Mar 2016 11:49:09 +0100
+Subject: [PATCH] net: phy: at803x: Request 'reset' GPIO only for AT8030 PHY
+
+This removes the dependency on GPIOLIB for non faulty PHYs.
+
+Indeed, without this patch, if GPIOLIB is not selected
+devm_gpiod_get_optional() will return -ENOSYS and the driver probe
+call will fail, regardless of the actual PHY hardware.
+
+Out of the 3 PHYs supported by this driver (AT8030, AT8031, AT8035),
+only AT8030 presents the issues that commit 13a56b449325 ("net: phy:
+at803x: Add support for hardware reset") attempts to work-around by
+using a 'reset' GPIO line.
+
+Hence, only AT8030 should depend on GPIOLIB operating properly.
+
+Fixes: 13a56b449325 ("net: phy: at803x: Add support for hardware reset")
+
+Signed-off-by: Sebastian Frias <sf84@laposte.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -250,12 +250,16 @@ static int at803x_probe(struct phy_devic
+       if (!priv)
+               return -ENOMEM;
++      if (phydev->drv->phy_id != ATH8030_PHY_ID)
++              goto does_not_require_reset_workaround;
++
+       gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(gpiod_reset))
+               return PTR_ERR(gpiod_reset);
+       priv->gpiod_reset = gpiod_reset;
++does_not_require_reset_workaround:
+       phydev->priv = priv;
+       return 0;
diff --git a/target/linux/generic/patches-4.4/738-net-phy-at803x-only-the-AT8030-needs-a-hardware-rese.patch b/target/linux/generic/patches-4.4/738-net-phy-at803x-only-the-AT8030-needs-a-hardware-rese.patch
new file mode 100644 (file)
index 0000000..c49d53e
--- /dev/null
@@ -0,0 +1,77 @@
+From: Timur Tabi <timur@codeaurora.org>
+Date: Tue, 26 Apr 2016 12:44:18 -0500
+Subject: [PATCH] net: phy: at803x: only the AT8030 needs a hardware reset on
+ link change
+
+Commit 13a56b44 ("at803x: Add support for hardware reset") added a
+work-around for a hardware bug on the AT8030.  However, the work-around
+was being called for all 803x PHYs, even those that don't need it.
+Function at803x_link_change_notify() checks to make sure that it only
+resets the PHY on the 8030, but it makes more sense to not call that
+function at all if it isn't needed.
+
+Signed-off-by: Timur Tabi <timur@codeaurora.org>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -374,27 +374,25 @@ static void at803x_link_change_notify(st
+        * in the FIFO. In such cases, the FIFO enters an error mode it
+        * cannot recover from by software.
+        */
+-      if (phydev->drv->phy_id == ATH8030_PHY_ID) {
+-              if (phydev->state == PHY_NOLINK) {
+-                      if (priv->gpiod_reset && !priv->phy_reset) {
+-                              struct at803x_context context;
++      if (phydev->state == PHY_NOLINK) {
++              if (priv->gpiod_reset && !priv->phy_reset) {
++                      struct at803x_context context;
+-                              at803x_context_save(phydev, &context);
++                      at803x_context_save(phydev, &context);
+-                              gpiod_set_value(priv->gpiod_reset, 1);
+-                              msleep(1);
+-                              gpiod_set_value(priv->gpiod_reset, 0);
+-                              msleep(1);
++                      gpiod_set_value(priv->gpiod_reset, 1);
++                      msleep(1);
++                      gpiod_set_value(priv->gpiod_reset, 0);
++                      msleep(1);
+-                              at803x_context_restore(phydev, &context);
++                      at803x_context_restore(phydev, &context);
+-                              dev_dbg(&phydev->dev, "%s(): phy was reset\n",
+-                                      __func__);
+-                              priv->phy_reset = true;
+-                      }
+-              } else {
+-                      priv->phy_reset = false;
++                      dev_dbg(&phydev->dev, "%s(): phy was reset\n",
++                              __func__);
++                      priv->phy_reset = true;
+               }
++      } else {
++              priv->phy_reset = false;
+       }
+       if (pdata && pdata->fixup_rgmii_tx_delay &&
+           phydev->speed != priv->prev_speed) {
+@@ -426,7 +424,6 @@ static struct phy_driver at803x_driver[]
+       .phy_id_mask            = AT803X_PHY_ID_MASK,
+       .probe                  = at803x_probe,
+       .config_init            = at803x_config_init,
+-      .link_change_notify     = at803x_link_change_notify,
+       .set_wol                = at803x_set_wol,
+       .get_wol                = at803x_get_wol,
+       .suspend                = at803x_suspend,
+@@ -468,7 +465,6 @@ static struct phy_driver at803x_driver[]
+       .phy_id_mask            = AT803X_PHY_ID_MASK,
+       .probe                  = at803x_probe,
+       .config_init            = at803x_config_init,
+-      .link_change_notify     = at803x_link_change_notify,
+       .set_wol                = at803x_set_wol,
+       .get_wol                = at803x_get_wol,
+       .suspend                = at803x_suspend,