From c6a7ea9f7f49fb805af54e586941f066e0a8786d Mon Sep 17 00:00:00 2001 From: Jan Hoffmann Date: Sat, 23 Jul 2022 22:53:14 +0200 Subject: [PATCH] realtek: rtl83xx-phy: decouple RTL8214FC media change and power config Move RTL8214FC power configuration to newly created suspend and resume methods. A media change now only results in power configuration if the PHY is not suspended, to avoid powering up a port when the interface is currently not up. While at it, remove the rtl8380 prefix from function names, as this is actually not SoC-specific. Tested-by: Birger Koblitz Signed-off-by: Jan Hoffmann --- .../files-5.10/drivers/net/phy/rtl83xx-phy.c | 122 ++++++++++-------- 1 file changed, 70 insertions(+), 52 deletions(-) diff --git a/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c index 252389489106c..70b57924b9b30 100644 --- a/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c +++ b/target/linux/realtek/files-5.10/drivers/net/phy/rtl83xx-phy.c @@ -934,78 +934,96 @@ static int rtl8218b_ext_match_phy_device(struct phy_device *phydev) return phydev->phy_id == PHY_ID_RTL8218B_E; } -static void rtl8380_rtl8214fc_media_set(struct phy_device *phydev, bool set_fibre) +static bool rtl8214fc_media_is_fibre(struct phy_device *phydev) { int mac = phydev->mdio.addr; static int reg[] = {16, 19, 20, 21}; - int val, media, power; + u32 val; - pr_info("%s: port %d, set_fibre: %d\n", __func__, mac, set_fibre); phy_package_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_INTERNAL); val = phy_package_read_paged(phydev, RTL821X_PAGE_PORT, reg[mac % 4]); + phy_package_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_AUTO); - media = (val >> 10) & 0x3; - pr_info("Current media %x\n", media); - if (media & 0x2) { - pr_info("Powering off COPPER\n"); - phy_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_COPPER); - /* Ensure power is off */ - power = phy_read_paged(phydev, RTL821X_PAGE_POWER, 0x10); - if (!(power & (1 << 11))) - phy_write_paged(phydev, RTL821X_PAGE_POWER, 0x10, power | (1 << 11)); - } else { - pr_info("Powering off FIBRE\n"); + if (val & BIT(11)) + return false; + + return true; +} + +static void rtl8214fc_power_set(struct phy_device *phydev, int port, bool on) +{ + char *state = on ? "on" : "off"; + + if (port == PORT_FIBRE) { + pr_info("%s: Powering %s FIBRE (port %d)\n", __func__, state, phydev->mdio.addr); phy_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_FIBRE); - /* Ensure power is off */ - power = phy_read_paged(phydev, RTL821X_PAGE_POWER, 0x10); - if (!(power & (1 << 11))) - phy_write_paged(phydev, RTL821X_PAGE_POWER, 0x10, power | (1 << 11)); + } else { + pr_info("%s: Powering %s COPPER (port %d)\n", __func__, state, phydev->mdio.addr); + phy_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_COPPER); } - phy_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_AUTO); - if (set_fibre) { - val |= 1 << 10; - val &= ~(1 << 11); + if (on) { + phy_modify_paged(phydev, RTL821X_PAGE_POWER, 0x10, BIT(11), 0); } else { - val |= 1 << 10; - val |= 1 << 11; + phy_modify_paged(phydev, RTL821X_PAGE_POWER, 0x10, 0, BIT(11)); } - phy_package_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_INTERNAL); - phy_package_write_paged(phydev, RTL821X_PAGE_PORT, reg[mac % 4], val); - phy_package_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_AUTO); - if (set_fibre) { - pr_info("Powering on FIBRE\n"); - phy_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_FIBRE); - /* Ensure power is off */ - power = phy_read_paged(phydev, RTL821X_PAGE_POWER, 0x10); - if (power & (1 << 11)) - phy_write_paged(phydev, RTL821X_PAGE_POWER, 0x10, power & ~(1 << 11)); + phy_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_AUTO); +} + +static int rtl8214fc_suspend(struct phy_device *phydev) +{ + rtl8214fc_power_set(phydev, PORT_MII, false); + rtl8214fc_power_set(phydev, PORT_FIBRE, false); + + return 0; +} + +static int rtl8214fc_resume(struct phy_device *phydev) +{ + if (rtl8214fc_media_is_fibre(phydev)) { + rtl8214fc_power_set(phydev, PORT_MII, false); + rtl8214fc_power_set(phydev, PORT_FIBRE, true); } else { - pr_info("Powering on COPPER\n"); - phy_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_COPPER); - /* Ensure power is off */ - power = phy_read_paged(phydev, RTL821X_PAGE_POWER, 0x10); - if (power & (1 << 11)) - phy_write_paged(phydev, RTL821X_PAGE_POWER, 0x10, power & ~(1 << 11)); + rtl8214fc_power_set(phydev, PORT_FIBRE, false); + rtl8214fc_power_set(phydev, PORT_MII, true); } - phy_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_AUTO); + + return 0; } -static bool rtl8380_rtl8214fc_media_is_fibre(struct phy_device *phydev) +static void rtl8214fc_media_set(struct phy_device *phydev, bool set_fibre) { int mac = phydev->mdio.addr; static int reg[] = {16, 19, 20, 21}; - u32 val; + int val; + pr_info("%s: port %d, set_fibre: %d\n", __func__, mac, set_fibre); phy_package_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_INTERNAL); val = phy_package_read_paged(phydev, RTL821X_PAGE_PORT, reg[mac % 4]); + + val |= BIT(10); + if (set_fibre) { + val &= ~BIT(11); + } else { + val |= BIT(11); + } + + phy_package_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_INTERNAL); + phy_package_write_paged(phydev, RTL821X_PAGE_PORT, reg[mac % 4], val); phy_package_write_paged(phydev, RTL83XX_PAGE_RAW, RTL821XINT_MEDIA_PAGE_SELECT, RTL821X_MEDIA_PAGE_AUTO); - if (val & (1 << 11)) - return false; - return true; + + if (!phydev->suspended) { + if (set_fibre) { + rtl8214fc_power_set(phydev, PORT_MII, false); + rtl8214fc_power_set(phydev, PORT_FIBRE, true); + } else { + rtl8214fc_power_set(phydev, PORT_FIBRE, false); + rtl8214fc_power_set(phydev, PORT_MII, true); + } + } } static int rtl8214fc_set_port(struct phy_device *phydev, int port) @@ -1015,7 +1033,7 @@ static int rtl8214fc_set_port(struct phy_device *phydev, int port) pr_debug("%s port %d to %d\n", __func__, addr, port); - rtl8380_rtl8214fc_media_set(phydev, is_fibre); + rtl8214fc_media_set(phydev, is_fibre); return 0; } @@ -1024,7 +1042,7 @@ static int rtl8214fc_get_port(struct phy_device *phydev) int addr = phydev->mdio.addr; pr_debug("%s: port %d\n", __func__, addr); - if (rtl8380_rtl8214fc_media_is_fibre(phydev)) + if (rtl8214fc_media_is_fibre(phydev)) return PORT_FIBRE; return PORT_MII; } @@ -1131,7 +1149,7 @@ static int rtl8214fc_set_eee(struct phy_device *phydev, pr_debug("In %s port %d, enabled %d\n", __func__, port, e->eee_enabled); - if (rtl8380_rtl8214fc_media_is_fibre(phydev)) { + if (rtl8214fc_media_is_fibre(phydev)) { netdev_err(phydev->attached_dev, "Port %d configured for FIBRE", port); return -ENOTSUPP; } @@ -1184,7 +1202,7 @@ static int rtl8214fc_get_eee(struct phy_device *phydev, int addr = phydev->mdio.addr; pr_debug("In %s port %d, enabled %d\n", __func__, addr, e->eee_enabled); - if (rtl8380_rtl8214fc_media_is_fibre(phydev)) { + if (rtl8214fc_media_is_fibre(phydev)) { netdev_err(phydev->attached_dev, "Port %d configured for FIBRE", addr); return -ENOTSUPP; } @@ -3842,8 +3860,8 @@ static struct phy_driver rtl83xx_phy_driver[] = { .flags = PHY_HAS_REALTEK_PAGES, .match_phy_device = rtl8214fc_match_phy_device, .probe = rtl8214fc_phy_probe, - .suspend = genphy_suspend, - .resume = genphy_resume, + .suspend = rtl8214fc_suspend, + .resume = rtl8214fc_resume, .set_loopback = genphy_loopback, .set_port = rtl8214fc_set_port, .get_port = rtl8214fc_get_port,