diff --git a/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch b/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch index ff2038d6f7c..b3fb3c5020c 100644 --- a/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch +++ b/target/linux/generic/hack-6.6/722-net-phy-aquantia-enable-AQR112-and-AQR412.patch @@ -15,9 +15,9 @@ Signed-off-by: Alex Marginean --- a/drivers/net/phy/aquantia/aquantia_main.c +++ b/drivers/net/phy/aquantia/aquantia_main.c -@@ -102,6 +102,29 @@ - #define AQR107_OP_IN_PROG_SLEEP 1000 - #define AQR107_OP_IN_PROG_TIMEOUT 100000 +@@ -127,6 +127,29 @@ struct aqr107_priv { + u64 sgmii_stats[AQR107_SGMII_STAT_SZ]; + }; +/* registers in MDIO_MMD_VEND1 region */ +#define AQUANTIA_VND1_GLOBAL_SC 0x000 @@ -42,9 +42,9 @@ Signed-off-by: Alex Marginean +#define AQUANTIA_VND1_GSYSCFG_5G 3 +#define AQUANTIA_VND1_GSYSCFG_10G 4 + - struct aqr107_hw_stat { - const char *name; - int reg; + static int aqr107_get_sset_count(struct phy_device *phydev) + { + return AQR107_SGMII_STAT_SZ; @@ -233,6 +256,51 @@ static int aqr_config_aneg(struct phy_de return genphy_c45_check_and_restart_aneg(phydev, changed); } @@ -97,7 +97,7 @@ Signed-off-by: Alex Marginean static int aqr_config_intr(struct phy_device *phydev) { bool en = phydev->interrupts == PHY_INTERRUPT_ENABLED; -@@ -810,7 +878,7 @@ static struct phy_driver aqr_driver[] = +@@ -838,7 +906,7 @@ static struct phy_driver aqr_driver[] = PHY_ID_MATCH_MODEL(PHY_ID_AQR112), .name = "Aquantia AQR112", .probe = aqr107_probe, @@ -106,7 +106,7 @@ Signed-off-by: Alex Marginean .config_intr = aqr_config_intr, .handle_interrupt = aqr_handle_interrupt, .get_tunable = aqr107_get_tunable, -@@ -828,7 +896,7 @@ static struct phy_driver aqr_driver[] = +@@ -863,7 +931,7 @@ static struct phy_driver aqr_driver[] = PHY_ID_MATCH_MODEL(PHY_ID_AQR412), .name = "Aquantia AQR412", .probe = aqr107_probe, diff --git a/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch b/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch index 4a72b1bd2b2..c93a77d6a47 100644 --- a/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch +++ b/target/linux/generic/hack-6.6/725-net-phy-aquantia-add-PHY_IDs-for-AQR112-variants.patch @@ -21,9 +21,9 @@ Signed-off-by: Daniel Golle #define MDIO_PHYXS_VEND_IF_STATUS 0xe812 #define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3) -@@ -992,6 +994,30 @@ static struct phy_driver aqr_driver[] = - .get_stats = aqr107_get_stats, - .link_change_notify = aqr107_link_change_notify, +@@ -1062,6 +1064,30 @@ static struct phy_driver aqr_driver[] = + .led_polarity_set = aqr_phy_led_polarity_set, + #endif }, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR112C), @@ -52,7 +52,7 @@ Signed-off-by: Daniel Golle }; module_phy_driver(aqr_driver); -@@ -1012,6 +1038,8 @@ static struct mdio_device_id __maybe_unu +@@ -1082,6 +1108,8 @@ static struct mdio_device_id __maybe_unu { PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR114C) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR813) }, diff --git a/target/linux/generic/pending-6.6/743-net-phy-aquantia-add-support-for-PHY-LEDs.patch b/target/linux/generic/pending-6.6/743-net-phy-aquantia-add-support-for-PHY-LEDs.patch new file mode 100644 index 00000000000..ca3a2b5c87a --- /dev/null +++ b/target/linux/generic/pending-6.6/743-net-phy-aquantia-add-support-for-PHY-LEDs.patch @@ -0,0 +1,368 @@ +From c6a1759365fc35463138a7d9e335ee53f384b8df Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 10 May 2024 02:53:52 +0100 +Subject: [PATCH] net: phy: aquantia: add support for PHY LEDs + +Aquantia Ethernet PHYs got 3 LED output pins which are typically used +to indicate link status and activity. +Add a minimal LED controller driver supporting the most common uses +with the 'netdev' trigger as well as software-driven forced control of +the LEDs. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/aquantia/Makefile | 3 + + drivers/net/phy/aquantia/aquantia.h | 84 +++++++++++++ + drivers/net/phy/aquantia/aquantia_leds.c | 152 +++++++++++++++++++++++ + drivers/net/phy/aquantia/aquantia_main.c | 127 +++++++++++++------ + 4 files changed, 329 insertions(+), 37 deletions(-) + create mode 100644 drivers/net/phy/aquantia/aquantia_leds.c + +--- a/drivers/net/phy/aquantia/Makefile ++++ b/drivers/net/phy/aquantia/Makefile +@@ -3,4 +3,7 @@ aquantia-objs += aquantia_main.o aquan + ifdef CONFIG_HWMON + aquantia-objs += aquantia_hwmon.o + endif ++ifdef CONFIG_PHYLIB_LEDS ++aquantia-objs += aquantia_leds.o ++endif + obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o +--- a/drivers/net/phy/aquantia/aquantia.h ++++ b/drivers/net/phy/aquantia/aquantia.h +@@ -62,6 +62,26 @@ + #define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 + #define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 + #define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 ++ ++#define AQR_NUM_LEDS 3 ++ ++#define VEND1_GLOBAL_LED_PROV 0xc430 ++#define AQR_LED_PROV(x) (VEND1_GLOBAL_LED_PROV + x) ++#define VEND1_GLOBAL_LED_PROV_ACT_STRETCH GENMASK(0, 1) ++#define VEND1_GLOBAL_LED_PROV_TX_ACT BIT(2) ++#define VEND1_GLOBAL_LED_PROV_RX_ACT BIT(3) ++#define VEND1_GLOBAL_LED_PROV_LINK_MASK (GENMASK(15, 14) | GENMASK(8, 5)) ++#define VEND1_GLOBAL_LED_PROV_LINK100 BIT(5) ++#define VEND1_GLOBAL_LED_PROV_LINK1000 BIT(6) ++#define VEND1_GLOBAL_LED_PROV_LINK10000 BIT(7) ++#define VEND1_GLOBAL_LED_PROV_FORCE_ON BIT(8) ++#define VEND1_GLOBAL_LED_PROV_LINK2500 BIT(14) ++#define VEND1_GLOBAL_LED_PROV_LINK5000 BIT(15) ++ ++#define VEND1_GLOBAL_LED_DRIVE 0xc438 ++#define VEND1_GLOBAL_LED_DRIVE_VDD BIT(1) ++#define AQR_LED_DRIVE(x) (VEND1_GLOBAL_LED_DRIVE + x) ++ + #define VEND1_THERMAL_STAT1 0xc820 + #define VEND1_THERMAL_STAT2 0xc821 + #define VEND1_THERMAL_STAT2_VALID BIT(0) +@@ -115,3 +135,23 @@ static inline int aqr_hwmon_probe(struct + #endif + + int aqr_firmware_load(struct phy_device *phydev); ++ ++#if IS_ENABLED(CONFIG_PHYLIB_LEDS) ++int aqr_phy_led_blink_set(struct phy_device *phydev, u8 index, ++ unsigned long *delay_on, ++ unsigned long *delay_off); ++ ++int aqr_phy_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value); ++ ++int aqr_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules); ++ ++int aqr_phy_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules); ++ ++int aqr_phy_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules); ++ ++int aqr_phy_led_polarity_set(struct phy_device *phydev, int index, unsigned long modes); ++#endif +--- /dev/null ++++ b/drivers/net/phy/aquantia/aquantia_leds.c +@@ -0,0 +1,140 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* LED driver for Aquantia PHY ++ * ++ * Author: Daniel Golle ++ */ ++ ++#include ++ ++#include "aquantia.h" ++ ++int aqr_phy_led_brightness_set(struct phy_device *phydev, ++ u8 index, enum led_brightness value) ++{ ++ if (index > 2) ++ return -EINVAL; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_PROV(index), VEND1_GLOBAL_LED_PROV_LINK_MASK | ++ VEND1_GLOBAL_LED_PROV_FORCE_ON | ++ VEND1_GLOBAL_LED_PROV_RX_ACT | ++ VEND1_GLOBAL_LED_PROV_TX_ACT, ++ value ? VEND1_GLOBAL_LED_PROV_FORCE_ON : 0); ++} ++ ++static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_LINK) | ++ BIT(TRIGGER_NETDEV_LINK_100) | ++ BIT(TRIGGER_NETDEV_LINK_1000) | ++ BIT(TRIGGER_NETDEV_LINK_2500) | ++ BIT(TRIGGER_NETDEV_LINK_5000) | ++ BIT(TRIGGER_NETDEV_LINK_10000) | ++ BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX)); ++ ++int aqr_phy_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ if (index >= AQR_NUM_LEDS) ++ return -EINVAL; ++ ++ /* All combinations of the supported triggers are allowed */ ++ if (rules & ~supported_triggers) ++ return -EOPNOTSUPP; ++ ++ return 0; ++} ++ ++int aqr_phy_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ int val; ++ ++ if (index >= AQR_NUM_LEDS) ++ return -EINVAL; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_PROV(index)); ++ if (val < 0) ++ return val; ++ ++ *rules = 0; ++ if (val & VEND1_GLOBAL_LED_PROV_LINK100) ++ *rules |= BIT(TRIGGER_NETDEV_LINK_100); ++ ++ if (val & VEND1_GLOBAL_LED_PROV_LINK1000) ++ *rules |= BIT(TRIGGER_NETDEV_LINK_1000); ++ ++ if (val & VEND1_GLOBAL_LED_PROV_LINK2500) ++ *rules |= BIT(TRIGGER_NETDEV_LINK_2500); ++ ++ if (val & VEND1_GLOBAL_LED_PROV_LINK5000) ++ *rules |= BIT(TRIGGER_NETDEV_LINK_5000); ++ ++ if (val & VEND1_GLOBAL_LED_PROV_LINK10000) ++ *rules |= BIT(TRIGGER_NETDEV_LINK_10000); ++ ++ if (val & VEND1_GLOBAL_LED_PROV_RX_ACT) ++ *rules |= BIT(TRIGGER_NETDEV_RX); ++ ++ if (val & VEND1_GLOBAL_LED_PROV_TX_ACT) ++ *rules |= BIT(TRIGGER_NETDEV_TX); ++ ++ return 0; ++} ++ ++int aqr_phy_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ u16 val = 0; ++ ++ if (index >= AQR_NUM_LEDS) ++ return -EINVAL; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK))) ++ val |= VEND1_GLOBAL_LED_PROV_LINK100; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK))) ++ val |= VEND1_GLOBAL_LED_PROV_LINK1000; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK))) ++ val |= VEND1_GLOBAL_LED_PROV_LINK2500; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_5000) | BIT(TRIGGER_NETDEV_LINK))) ++ val |= VEND1_GLOBAL_LED_PROV_LINK5000; ++ ++ if (rules & (BIT(TRIGGER_NETDEV_LINK_10000) | BIT(TRIGGER_NETDEV_LINK))) ++ val |= VEND1_GLOBAL_LED_PROV_LINK10000; ++ ++ if (rules & BIT(TRIGGER_NETDEV_RX)) ++ val |= VEND1_GLOBAL_LED_PROV_RX_ACT; ++ ++ if (rules & BIT(TRIGGER_NETDEV_TX)) ++ val |= VEND1_GLOBAL_LED_PROV_TX_ACT; ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_PROV(index), ++ VEND1_GLOBAL_LED_PROV_LINK_MASK | ++ VEND1_GLOBAL_LED_PROV_FORCE_ON | ++ VEND1_GLOBAL_LED_PROV_RX_ACT | ++ VEND1_GLOBAL_LED_PROV_TX_ACT, val); ++} ++ ++int aqr_phy_led_polarity_set(struct phy_device *phydev, int index, unsigned long modes) ++{ ++ bool active_low = false; ++ u32 mode; ++ ++ if (index >= AQR_NUM_LEDS) ++ return -EINVAL; ++ ++ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) { ++ switch (mode) { ++ case PHY_LED_ACTIVE_LOW: ++ active_low = true; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ return phy_modify_mmd(phydev, MDIO_MMD_VEND1, AQR_LED_DRIVE(index), ++ VEND1_GLOBAL_LED_DRIVE_VDD, ++ active_low ? VEND1_GLOBAL_LED_DRIVE_VDD : 0); ++} +--- a/drivers/net/phy/aquantia/aquantia_main.c ++++ b/drivers/net/phy/aquantia/aquantia_main.c +@@ -740,6 +740,13 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, ++#if IS_ENABLED(CONFIG_PHYLIB_LEDS) ++ .led_brightness_set = aqr_phy_led_brightness_set, ++ .led_hw_is_supported = aqr_phy_led_hw_is_supported, ++ .led_hw_control_set = aqr_phy_led_hw_control_set, ++ .led_hw_control_get = aqr_phy_led_hw_control_get, ++ .led_polarity_set = aqr_phy_led_polarity_set, ++#endif + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), +@@ -759,6 +766,13 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, ++#if IS_ENABLED(CONFIG_PHYLIB_LEDS) ++ .led_brightness_set = aqr_phy_led_brightness_set, ++ .led_hw_is_supported = aqr_phy_led_hw_is_supported, ++ .led_hw_control_set = aqr_phy_led_hw_control_set, ++ .led_hw_control_get = aqr_phy_led_hw_control_get, ++ .led_polarity_set = aqr_phy_led_polarity_set, ++#endif + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_AQR111), +@@ -778,6 +792,13 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, ++#if IS_ENABLED(CONFIG_PHYLIB_LEDS) ++ .led_brightness_set = aqr_phy_led_brightness_set, ++ .led_hw_is_supported = aqr_phy_led_hw_is_supported, ++ .led_hw_control_set = aqr_phy_led_hw_control_set, ++ .led_hw_control_get = aqr_phy_led_hw_control_get, ++ .led_polarity_set = aqr_phy_led_polarity_set, ++#endif + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_AQR111B0), +@@ -797,6 +818,13 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, ++#if IS_ENABLED(CONFIG_PHYLIB_LEDS) ++ .led_brightness_set = aqr_phy_led_brightness_set, ++ .led_hw_is_supported = aqr_phy_led_hw_is_supported, ++ .led_hw_control_set = aqr_phy_led_hw_control_set, ++ .led_hw_control_get = aqr_phy_led_hw_control_get, ++ .led_polarity_set = aqr_phy_led_polarity_set, ++#endif + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_AQR405), +@@ -823,6 +851,13 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, ++#if IS_ENABLED(CONFIG_PHYLIB_LEDS) ++ .led_brightness_set = aqr_phy_led_brightness_set, ++ .led_hw_is_supported = aqr_phy_led_hw_is_supported, ++ .led_hw_control_set = aqr_phy_led_hw_control_set, ++ .led_hw_control_get = aqr_phy_led_hw_control_get, ++ .led_polarity_set = aqr_phy_led_polarity_set, ++#endif + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_AQR412), +@@ -841,6 +876,13 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, ++#if IS_ENABLED(CONFIG_PHYLIB_LEDS) ++ .led_brightness_set = aqr_phy_led_brightness_set, ++ .led_hw_is_supported = aqr_phy_led_hw_is_supported, ++ .led_hw_control_set = aqr_phy_led_hw_control_set, ++ .led_hw_control_get = aqr_phy_led_hw_control_get, ++ .led_polarity_set = aqr_phy_led_polarity_set, ++#endif + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_AQR113), +@@ -860,6 +902,13 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, ++#if IS_ENABLED(CONFIG_PHYLIB_LEDS) ++ .led_brightness_set = aqr_phy_led_brightness_set, ++ .led_hw_is_supported = aqr_phy_led_hw_is_supported, ++ .led_hw_control_set = aqr_phy_led_hw_control_set, ++ .led_hw_control_get = aqr_phy_led_hw_control_get, ++ .led_polarity_set = aqr_phy_led_polarity_set, ++#endif + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_AQR113C), +@@ -879,6 +928,13 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, ++#if IS_ENABLED(CONFIG_PHYLIB_LEDS) ++ .led_brightness_set = aqr_phy_led_brightness_set, ++ .led_hw_is_supported = aqr_phy_led_hw_is_supported, ++ .led_hw_control_set = aqr_phy_led_hw_control_set, ++ .led_hw_control_get = aqr_phy_led_hw_control_get, ++ .led_polarity_set = aqr_phy_led_polarity_set, ++#endif + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_AQR114C), +@@ -898,6 +954,13 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, ++#if IS_ENABLED(CONFIG_PHYLIB_LEDS) ++ .led_brightness_set = aqr_phy_led_brightness_set, ++ .led_hw_is_supported = aqr_phy_led_hw_is_supported, ++ .led_hw_control_set = aqr_phy_led_hw_control_set, ++ .led_hw_control_get = aqr_phy_led_hw_control_get, ++ .led_polarity_set = aqr_phy_led_polarity_set, ++#endif + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_AQR813), +@@ -917,6 +980,13 @@ static struct phy_driver aqr_driver[] = + .get_strings = aqr107_get_strings, + .get_stats = aqr107_get_stats, + .link_change_notify = aqr107_link_change_notify, ++#if IS_ENABLED(CONFIG_PHYLIB_LEDS) ++ .led_brightness_set = aqr_phy_led_brightness_set, ++ .led_hw_is_supported = aqr_phy_led_hw_is_supported, ++ .led_hw_control_set = aqr_phy_led_hw_control_set, ++ .led_hw_control_get = aqr_phy_led_hw_control_get, ++ .led_polarity_set = aqr_phy_led_polarity_set, ++#endif + }, + }; + diff --git a/target/linux/generic/pending-6.6/999-net-phy-move-LED-polarity-to-phy_init_hw.patch b/target/linux/generic/pending-6.6/999-net-phy-move-LED-polarity-to-phy_init_hw.patch new file mode 100644 index 00000000000..22c47768279 --- /dev/null +++ b/target/linux/generic/pending-6.6/999-net-phy-move-LED-polarity-to-phy_init_hw.patch @@ -0,0 +1,100 @@ +From 6e6fff51ae5e54092611d174fa45fa78c237a415 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 21 May 2024 20:01:46 +0200 +Subject: [PATCH] net: phy: move LED polarity to phy_init_hw + +Some PHY reset the polarity on reset and this cause the LED to +malfunction as LED polarity is configured only when LED is +registered. + +To better handle this, move the LED polarity configuration in +phy_init_hw to reconfigure it after PHY reset. + +Signed-off-by: Christian Marangi +--- + drivers/net/phy/phy_device.c | 53 +++++++++++++++++++++++++----------- + 1 file changed, 37 insertions(+), 16 deletions(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1223,6 +1223,37 @@ static int phy_poll_reset(struct phy_dev + return 0; + } + ++static int of_phy_led_init(struct phy_device *phydev) ++{ ++ struct phy_led *phyled; ++ ++ list_for_each_entry(phyled, &phydev->leds, list) { ++ struct led_classdev *cdev = &phyled->led_cdev; ++ struct device_node *np = cdev->dev->of_node; ++ unsigned long modes = 0; ++ int err; ++ ++ if (of_property_read_bool(np, "active-low")) ++ set_bit(PHY_LED_ACTIVE_LOW, &modes); ++ if (of_property_read_bool(np, "inactive-high-impedance")) ++ set_bit(PHY_LED_INACTIVE_HIGH_IMPEDANCE, &modes); ++ ++ if (!modes) ++ continue; ++ ++ /* Return error if asked to set polarity modes but not supported */ ++ if (!phydev->drv->led_polarity_set) ++ return -EINVAL; ++ ++ err = phydev->drv->led_polarity_set(phydev, phyled->index, ++ modes); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ + int phy_init_hw(struct phy_device *phydev) + { + int ret = 0; +@@ -1259,6 +1290,12 @@ int phy_init_hw(struct phy_device *phyde + return ret; + } + ++ if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) { ++ ret = of_phy_led_init(phydev); ++ if (ret < 0) ++ return ret; ++ } ++ + return 0; + } + EXPORT_SYMBOL(phy_init_hw); +@@ -3204,7 +3241,6 @@ static int of_phy_led(struct phy_device + struct device *dev = &phydev->mdio.dev; + struct led_init_data init_data = {}; + struct led_classdev *cdev; +- unsigned long modes = 0; + struct phy_led *phyled; + u32 index; + int err; +@@ -3222,21 +3258,6 @@ static int of_phy_led(struct phy_device + if (index > U8_MAX) + return -EINVAL; + +- if (of_property_read_bool(led, "active-low")) +- set_bit(PHY_LED_ACTIVE_LOW, &modes); +- if (of_property_read_bool(led, "inactive-high-impedance")) +- set_bit(PHY_LED_INACTIVE_HIGH_IMPEDANCE, &modes); +- +- if (modes) { +- /* Return error if asked to set polarity modes but not supported */ +- if (!phydev->drv->led_polarity_set) +- return -EINVAL; +- +- err = phydev->drv->led_polarity_set(phydev, index, modes); +- if (err) +- return err; +- } +- + phyled->index = index; + if (phydev->drv->led_brightness_set) + cdev->brightness_set_blocking = phy_led_set_brightness;