diff --git a/drivers/power/reset/linkstation-poweroff.c b/drivers/power/reset/linkstation-poweroff.c index cb5a32f852c1..02f5fdb8ffc4 100644 --- a/drivers/power/reset/linkstation-poweroff.c +++ b/drivers/power/reset/linkstation-poweroff.c @@ -19,6 +19,7 @@ #define MII_MARVELL_PHY_PAGE 22 #define MII_PHY_LED_CTRL 16 +#define MII_PHY_LED_POL_CTRL 17 #define MII_88E1318S_PHY_LED_TCR 18 #define MII_88E1318S_PHY_WOL_CTRL 16 #define MII_M1011_IEVENT 19 @@ -29,6 +30,8 @@ #define LED2_FORCE_ON (0x8 << 8) #define LEDMASK GENMASK(11,8) +#define MII_88E1318S_PHY_LED_POL_LED2 BIT(4) + struct power_off_cfg { char *mdio_node_name; void (*phy_set_reg)(bool restart); @@ -76,11 +79,47 @@ err: dev_err(&phydev->mdio.dev, "Write register failed, %d\n", rc); } +static void readynas_mvphy_set_reg(bool restart) +{ + int rc = 0, saved_page; + u16 data = 0; + + if (restart) + data = MII_88E1318S_PHY_LED_POL_LED2; + + saved_page = phy_select_page(phydev, MII_MARVELL_LED_PAGE); + if (saved_page < 0) + goto err; + + /* Set the LED[2].0 Polarity bit to the required state */ + __phy_modify(phydev, MII_PHY_LED_POL_CTRL, + MII_88E1318S_PHY_LED_POL_LED2, data); + + if (!data) { + /* If WOL was enabled and a magic packet was received before powering + * off, we won't be able to wake up by sending another magic packet. + * Clear WOL status. + */ + __phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_MARVELL_WOL_PAGE); + __phy_set_bits(phydev, MII_88E1318S_PHY_WOL_CTRL, + MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS); + } +err: + rc = phy_restore_page(phydev, saved_page, rc); + if (rc < 0) + dev_err(&phydev->mdio.dev, "Write register failed, %d\n", rc); +} + static const struct power_off_cfg linkstation_power_off_cfg = { .mdio_node_name = "mdio", .phy_set_reg = linkstation_mvphy_reg_intn, }; +static const struct power_off_cfg readynas_power_off_cfg = { + .mdio_node_name = "mdio-bus", + .phy_set_reg = readynas_mvphy_set_reg, +}; + static int linkstation_reboot_notifier(struct notifier_block *nb, unsigned long action, void *unused) { @@ -109,6 +148,9 @@ static const struct of_device_id ls_poweroff_of_match[] = { { .compatible = "buffalo,ls421de", .data = &linkstation_power_off_cfg, }, + { .compatible = "netgear,readynas-duo-v2", + .data = &readynas_power_off_cfg, + }, { }, };