[openwrt/openwrt] generic: 6.6: backports and add LED support for Aquantia PHYs

LEDE Commits lede-commits at lists.infradead.org
Fri May 24 12:57:59 PDT 2024


dangole pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/cccf98c7e8b37ef7f78f51df6210efe1483a514b

commit cccf98c7e8b37ef7f78f51df6210efe1483a514b
Author: Daniel Golle <daniel at makrotopia.org>
AuthorDate: Sat May 11 00:48:57 2024 +0100

    generic: 6.6: backports and add LED support for Aquantia PHYs
    
    Backport patch adding support for the AQR114C PHY and add support for
    PHY LEDs and polarity setting of Aquantia 3rd and 4th generation PHYs.
    
    Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
 ...net-phy-aquantia-enable-AQR112-and-AQR412.patch |  16 +-
 ...-aquantia-add-PHY_IDs-for-AQR112-variants.patch |   8 +-
 ...net-phy-aquantia-add-support-for-PHY-LEDs.patch | 368 +++++++++++++++++++++
 ...-net-phy-move-LED-polarity-to-phy_init_hw.patch | 100 ++++++
 4 files changed, 480 insertions(+), 12 deletions(-)

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 ff2038d6f7..b3fb3c5020 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 <alexandru.marginean at nxp.com>
 
 --- 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 <alexandru.marginean at nxp.com>
 +#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 <alexandru.marginean at nxp.com>
  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 <alexandru.marginean at nxp.com>
  	.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 4a72b1bd2b..c93a77d6a4 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 <daniel at makrotopia.org>
  
  #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 <daniel at makrotopia.org>
  };
  
  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 0000000000..ca3a2b5c87
--- /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 <daniel at makrotopia.org>
+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 <daniel at makrotopia.org>
+---
+ 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 <daniel at makrotopia.org>
++ */
++
++#include <linux/phy.h>
++
++#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 0000000000..22c4776827
--- /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 <ansuelsmth at gmail.com>
+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 <ansuelsmth at gmail.com>
+---
+ 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;




More information about the lede-commits mailing list