mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-24 15:56:49 +00:00
20c64dabb6
The patch was wrongly removed by a kernel version bump to 4.9.106 in the believe that it was merged upstream thow it wasn't. This lead to unrecoverable link losses on devices which use those PHYs such as many ubnt single-port CPEs. Fixes:6f8eb1b50f
("kernel: bump 4.9 to 4.9.106 for 18.06") Signed-off-by: Daniel Golle <daniel@makrotopia.org> (cherry picked from commita497e47762
)
69 lines
2.1 KiB
Diff
69 lines
2.1 KiB
Diff
Add support for configuring AT803x GPIO reset via platform data.
|
|
This is necessary, because ath79 is not converted to device tree yet.
|
|
|
|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
|
|
--- a/include/linux/platform_data/phy-at803x.h
|
|
+++ b/include/linux/platform_data/phy-at803x.h
|
|
@@ -6,6 +6,8 @@ struct at803x_platform_data {
|
|
int enable_rgmii_tx_delay:1;
|
|
int enable_rgmii_rx_delay:1;
|
|
int fixup_rgmii_tx_delay:1;
|
|
+ int has_reset_gpio:1;
|
|
+ int reset_gpio;
|
|
};
|
|
|
|
#endif /* _PHY_AT803X_PDATA_H */
|
|
--- a/drivers/net/phy/at803x.c
|
|
+++ b/drivers/net/phy/at803x.c
|
|
@@ -264,6 +264,7 @@ static int at803x_resume(struct phy_devi
|
|
|
|
static int at803x_probe(struct phy_device *phydev)
|
|
{
|
|
+ struct at803x_platform_data *pdata;
|
|
struct device *dev = &phydev->mdio.dev;
|
|
struct at803x_priv *priv;
|
|
struct gpio_desc *gpiod_reset;
|
|
@@ -276,6 +277,12 @@ static int at803x_probe(struct phy_devic
|
|
phydev->drv->phy_id != ATH8032_PHY_ID)
|
|
goto does_not_require_reset_workaround;
|
|
|
|
+ pdata = dev_get_platdata(dev);
|
|
+ if (pdata && pdata->has_reset_gpio) {
|
|
+ devm_gpio_request(dev, pdata->reset_gpio, "reset");
|
|
+ gpio_direction_output(pdata->reset_gpio, 1);
|
|
+ }
|
|
+
|
|
gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
|
if (IS_ERR(gpiod_reset))
|
|
return PTR_ERR(gpiod_reset);
|
|
@@ -407,15 +414,23 @@ static void at803x_link_change_notify(st
|
|
* cannot recover from by software.
|
|
*/
|
|
if (phydev->state == PHY_NOLINK) {
|
|
- if (priv->gpiod_reset && !priv->phy_reset) {
|
|
+ if ((priv->gpiod_reset || (pdata && pdata->has_reset_gpio)) &&
|
|
+ !priv->phy_reset) {
|
|
struct at803x_context context;
|
|
|
|
at803x_context_save(phydev, &context);
|
|
|
|
- gpiod_set_value(priv->gpiod_reset, 1);
|
|
- msleep(1);
|
|
- gpiod_set_value(priv->gpiod_reset, 0);
|
|
- msleep(1);
|
|
+ if (pdata && pdata->has_reset_gpio) {
|
|
+ gpio_set_value_cansleep(pdata->reset_gpio, 0);
|
|
+ msleep(1);
|
|
+ gpio_set_value_cansleep(pdata->reset_gpio, 1);
|
|
+ msleep(1);
|
|
+ } else {
|
|
+ gpiod_set_value(priv->gpiod_reset, 1);
|
|
+ msleep(1);
|
|
+ gpiod_set_value(priv->gpiod_reset, 0);
|
|
+ msleep(1);
|
|
+ }
|
|
|
|
at803x_context_restore(phydev, &context);
|
|
|