[openwrt/openwrt] generic: net: phy: intel-way: add support for PHY LEDs

LEDE Commits lede-commits at lists.infradead.org
Tue Oct 15 10:11:32 PDT 2024


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

commit 3f3c27e22c75837fd84098743cc265a605f3b05c
Author: Daniel Golle <daniel at makrotopia.org>
AuthorDate: Sat Oct 5 22:21:17 2024 +0100

    generic: net: phy: intel-way: add support for PHY LEDs
    
    Add driver support for PHY LEDs for MaxLinear/Intel/Lantiq XWAY
    Ethernet PHYs.
    
    Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
 ...t-phy-intel-xway-add-support-for-PHY-LEDs.patch | 379 +++++++++++++++++++++
 1 file changed, 379 insertions(+)

diff --git a/target/linux/generic/backport-6.6/846-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch b/target/linux/generic/backport-6.6/846-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch
new file mode 100644
index 0000000000..c57b5777ad
--- /dev/null
+++ b/target/linux/generic/backport-6.6/846-v6.13-net-phy-intel-xway-add-support-for-PHY-LEDs.patch
@@ -0,0 +1,379 @@
+From 1758af47b98c17da464cb45f476875150955dd48 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel at makrotopia.org>
+Date: Thu, 10 Oct 2024 13:55:29 +0100
+Subject: [PATCH 4/4] net: phy: intel-xway: add support for PHY LEDs
+
+The intel-xway PHY driver predates the PHY LED framework and currently
+initializes all LED pins to equal default values.
+
+Add PHY LED functions to the drivers and don't set default values if
+LEDs are defined in device tree.
+
+According the datasheets 3 LEDs are supported on all Intel XWAY PHYs.
+
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+Reviewed-by: Andrew Lunn <andrew at lunn.ch>
+Link: https://patch.msgid.link/81f4717ab9acf38f3239727a4540ae96fd01109b.1728558223.git.daniel@makrotopia.org
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ drivers/net/phy/intel-xway.c | 253 +++++++++++++++++++++++++++++++++--
+ 1 file changed, 244 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/phy/intel-xway.c
++++ b/drivers/net/phy/intel-xway.c
+@@ -151,6 +151,13 @@
+ #define XWAY_MMD_LED3H			0x01E8
+ #define XWAY_MMD_LED3L			0x01E9
+ 
++#define XWAY_GPHY_MAX_LEDS		3
++#define XWAY_GPHY_LED_INV(idx)		BIT(12 + (idx))
++#define XWAY_GPHY_LED_EN(idx)		BIT(8 + (idx))
++#define XWAY_GPHY_LED_DA(idx)		BIT(idx)
++#define XWAY_MMD_LEDxH(idx)		(XWAY_MMD_LED0H + 2 * (idx))
++#define XWAY_MMD_LEDxL(idx)		(XWAY_MMD_LED0L + 2 * (idx))
++
+ #define PHY_ID_PHY11G_1_3		0x030260D1
+ #define PHY_ID_PHY22F_1_3		0x030260E1
+ #define PHY_ID_PHY11G_1_4		0xD565A400
+@@ -229,20 +236,12 @@ static int xway_gphy_rgmii_init(struct p
+ 			  XWAY_MDIO_MIICTRL_TXSKEW_MASK, val);
+ }
+ 
+-static int xway_gphy_config_init(struct phy_device *phydev)
++static int xway_gphy_init_leds(struct phy_device *phydev)
+ {
+ 	int err;
+ 	u32 ledxh;
+ 	u32 ledxl;
+ 
+-	/* Mask all interrupts */
+-	err = phy_write(phydev, XWAY_MDIO_IMASK, 0);
+-	if (err)
+-		return err;
+-
+-	/* Clear all pending interrupts */
+-	phy_read(phydev, XWAY_MDIO_ISTAT);
+-
+ 	/* Ensure that integrated led function is enabled for all leds */
+ 	err = phy_write(phydev, XWAY_MDIO_LED,
+ 			XWAY_MDIO_LED_LED0_EN |
+@@ -276,6 +275,26 @@ static int xway_gphy_config_init(struct
+ 	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2H, ledxh);
+ 	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2L, ledxl);
+ 
++	return 0;
++}
++
++static int xway_gphy_config_init(struct phy_device *phydev)
++{
++	struct device_node *np = phydev->mdio.dev.of_node;
++	int err;
++
++	/* Mask all interrupts */
++	err = phy_write(phydev, XWAY_MDIO_IMASK, 0);
++	if (err)
++		return err;
++
++	/* Use default LED configuration if 'leds' node isn't defined */
++	if (!of_get_child_by_name(np, "leds"))
++		xway_gphy_init_leds(phydev);
++
++	/* Clear all pending interrupts */
++	phy_read(phydev, XWAY_MDIO_ISTAT);
++
+ 	err = xway_gphy_rgmii_init(phydev);
+ 	if (err)
+ 		return err;
+@@ -347,6 +366,172 @@ static irqreturn_t xway_gphy_handle_inte
+ 	return IRQ_HANDLED;
+ }
+ 
++static int xway_gphy_led_brightness_set(struct phy_device *phydev,
++					u8 index, enum led_brightness value)
++{
++	int ret;
++
++	if (index >= XWAY_GPHY_MAX_LEDS)
++		return -EINVAL;
++
++	/* clear EN and set manual LED state */
++	ret = phy_modify(phydev, XWAY_MDIO_LED,
++			 ((value == LED_OFF) ? XWAY_GPHY_LED_EN(index) : 0) |
++			 XWAY_GPHY_LED_DA(index),
++			 (value == LED_OFF) ? 0 : XWAY_GPHY_LED_DA(index));
++	if (ret)
++		return ret;
++
++	/* clear HW LED setup */
++	if (value == LED_OFF) {
++		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxH(index), 0);
++		if (ret)
++			return ret;
++
++		return phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxL(index), 0);
++	} else {
++		return 0;
++	}
++}
++
++static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_LINK) |
++						 BIT(TRIGGER_NETDEV_LINK_10) |
++						 BIT(TRIGGER_NETDEV_LINK_100) |
++						 BIT(TRIGGER_NETDEV_LINK_1000) |
++						 BIT(TRIGGER_NETDEV_RX) |
++						 BIT(TRIGGER_NETDEV_TX));
++
++static int xway_gphy_led_hw_is_supported(struct phy_device *phydev, u8 index,
++					 unsigned long rules)
++{
++	if (index >= XWAY_GPHY_MAX_LEDS)
++		return -EINVAL;
++
++	/* activity triggers are not possible without combination with a link
++	 * trigger.
++	 */
++	if (rules & (BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX)) &&
++	    !(rules & (BIT(TRIGGER_NETDEV_LINK) |
++		       BIT(TRIGGER_NETDEV_LINK_10) |
++		       BIT(TRIGGER_NETDEV_LINK_100) |
++		       BIT(TRIGGER_NETDEV_LINK_1000))))
++		return -EOPNOTSUPP;
++
++	/* All other combinations of the supported triggers are allowed */
++	if (rules & ~supported_triggers)
++		return -EOPNOTSUPP;
++
++	return 0;
++}
++
++static int xway_gphy_led_hw_control_get(struct phy_device *phydev, u8 index,
++					unsigned long *rules)
++{
++	int lval, hval;
++
++	if (index >= XWAY_GPHY_MAX_LEDS)
++		return -EINVAL;
++
++	hval = phy_read_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxH(index));
++	if (hval < 0)
++		return hval;
++
++	lval = phy_read_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxL(index));
++	if (lval < 0)
++		return lval;
++
++	if (hval & XWAY_MMD_LEDxH_CON_LINK10)
++		*rules |= BIT(TRIGGER_NETDEV_LINK_10);
++
++	if (hval & XWAY_MMD_LEDxH_CON_LINK100)
++		*rules |= BIT(TRIGGER_NETDEV_LINK_100);
++
++	if (hval & XWAY_MMD_LEDxH_CON_LINK1000)
++		*rules |= BIT(TRIGGER_NETDEV_LINK_1000);
++
++	if ((hval & XWAY_MMD_LEDxH_CON_LINK10) &&
++	    (hval & XWAY_MMD_LEDxH_CON_LINK100) &&
++	    (hval & XWAY_MMD_LEDxH_CON_LINK1000))
++		*rules |= BIT(TRIGGER_NETDEV_LINK);
++
++	if (lval & XWAY_MMD_LEDxL_PULSE_TXACT)
++		*rules |= BIT(TRIGGER_NETDEV_TX);
++
++	if (lval & XWAY_MMD_LEDxL_PULSE_RXACT)
++		*rules |= BIT(TRIGGER_NETDEV_RX);
++
++	return 0;
++}
++
++static int xway_gphy_led_hw_control_set(struct phy_device *phydev, u8 index,
++					unsigned long rules)
++{
++	u16 hval = 0, lval = 0;
++	int ret;
++
++	if (index >= XWAY_GPHY_MAX_LEDS)
++		return -EINVAL;
++
++	if (rules & BIT(TRIGGER_NETDEV_LINK) ||
++	    rules & BIT(TRIGGER_NETDEV_LINK_10))
++		hval |= XWAY_MMD_LEDxH_CON_LINK10;
++
++	if (rules & BIT(TRIGGER_NETDEV_LINK) ||
++	    rules & BIT(TRIGGER_NETDEV_LINK_100))
++		hval |= XWAY_MMD_LEDxH_CON_LINK100;
++
++	if (rules & BIT(TRIGGER_NETDEV_LINK) ||
++	    rules & BIT(TRIGGER_NETDEV_LINK_1000))
++		hval |= XWAY_MMD_LEDxH_CON_LINK1000;
++
++	if (rules & BIT(TRIGGER_NETDEV_TX))
++		lval |= XWAY_MMD_LEDxL_PULSE_TXACT;
++
++	if (rules & BIT(TRIGGER_NETDEV_RX))
++		lval |= XWAY_MMD_LEDxL_PULSE_RXACT;
++
++	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxH(index), hval);
++	if (ret)
++		return ret;
++
++	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDxL(index), lval);
++	if (ret)
++		return ret;
++
++	return phy_set_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_EN(index));
++}
++
++static int xway_gphy_led_polarity_set(struct phy_device *phydev, int index,
++				      unsigned long modes)
++{
++	bool force_active_low = false, force_active_high = false;
++	u32 mode;
++
++	if (index >= XWAY_GPHY_MAX_LEDS)
++		return -EINVAL;
++
++	for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
++		switch (mode) {
++		case PHY_LED_ACTIVE_LOW:
++			force_active_low = true;
++			break;
++		case PHY_LED_ACTIVE_HIGH:
++			force_active_high = true;
++			break;
++		default:
++			return -EINVAL;
++		}
++	}
++
++	if (force_active_low)
++		return phy_set_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_INV(index));
++
++	if (force_active_high)
++		return phy_clear_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_INV(index));
++
++	unreachable();
++}
++
+ static struct phy_driver xway_gphy[] = {
+ 	{
+ 		.phy_id		= PHY_ID_PHY11G_1_3,
+@@ -359,6 +544,11 @@ static struct phy_driver xway_gphy[] = {
+ 		.config_intr	= xway_gphy_config_intr,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
++		.led_brightness_set = xway_gphy_led_brightness_set,
++		.led_hw_is_supported = xway_gphy_led_hw_is_supported,
++		.led_hw_control_get = xway_gphy_led_hw_control_get,
++		.led_hw_control_set = xway_gphy_led_hw_control_set,
++		.led_polarity_set = xway_gphy_led_polarity_set,
+ 	}, {
+ 		.phy_id		= PHY_ID_PHY22F_1_3,
+ 		.phy_id_mask	= 0xffffffff,
+@@ -370,6 +560,11 @@ static struct phy_driver xway_gphy[] = {
+ 		.config_intr	= xway_gphy_config_intr,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
++		.led_brightness_set = xway_gphy_led_brightness_set,
++		.led_hw_is_supported = xway_gphy_led_hw_is_supported,
++		.led_hw_control_get = xway_gphy_led_hw_control_get,
++		.led_hw_control_set = xway_gphy_led_hw_control_set,
++		.led_polarity_set = xway_gphy_led_polarity_set,
+ 	}, {
+ 		.phy_id		= PHY_ID_PHY11G_1_4,
+ 		.phy_id_mask	= 0xffffffff,
+@@ -381,6 +576,11 @@ static struct phy_driver xway_gphy[] = {
+ 		.config_intr	= xway_gphy_config_intr,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
++		.led_brightness_set = xway_gphy_led_brightness_set,
++		.led_hw_is_supported = xway_gphy_led_hw_is_supported,
++		.led_hw_control_get = xway_gphy_led_hw_control_get,
++		.led_hw_control_set = xway_gphy_led_hw_control_set,
++		.led_polarity_set = xway_gphy_led_polarity_set,
+ 	}, {
+ 		.phy_id		= PHY_ID_PHY22F_1_4,
+ 		.phy_id_mask	= 0xffffffff,
+@@ -392,6 +592,11 @@ static struct phy_driver xway_gphy[] = {
+ 		.config_intr	= xway_gphy_config_intr,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
++		.led_brightness_set = xway_gphy_led_brightness_set,
++		.led_hw_is_supported = xway_gphy_led_hw_is_supported,
++		.led_hw_control_get = xway_gphy_led_hw_control_get,
++		.led_hw_control_set = xway_gphy_led_hw_control_set,
++		.led_polarity_set = xway_gphy_led_polarity_set,
+ 	}, {
+ 		.phy_id		= PHY_ID_PHY11G_1_5,
+ 		.phy_id_mask	= 0xffffffff,
+@@ -402,6 +607,11 @@ static struct phy_driver xway_gphy[] = {
+ 		.config_intr	= xway_gphy_config_intr,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
++		.led_brightness_set = xway_gphy_led_brightness_set,
++		.led_hw_is_supported = xway_gphy_led_hw_is_supported,
++		.led_hw_control_get = xway_gphy_led_hw_control_get,
++		.led_hw_control_set = xway_gphy_led_hw_control_set,
++		.led_polarity_set = xway_gphy_led_polarity_set,
+ 	}, {
+ 		.phy_id		= PHY_ID_PHY22F_1_5,
+ 		.phy_id_mask	= 0xffffffff,
+@@ -412,6 +622,11 @@ static struct phy_driver xway_gphy[] = {
+ 		.config_intr	= xway_gphy_config_intr,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
++		.led_brightness_set = xway_gphy_led_brightness_set,
++		.led_hw_is_supported = xway_gphy_led_hw_is_supported,
++		.led_hw_control_get = xway_gphy_led_hw_control_get,
++		.led_hw_control_set = xway_gphy_led_hw_control_set,
++		.led_polarity_set = xway_gphy_led_polarity_set,
+ 	}, {
+ 		.phy_id		= PHY_ID_PHY11G_VR9_1_1,
+ 		.phy_id_mask	= 0xffffffff,
+@@ -422,6 +637,11 @@ static struct phy_driver xway_gphy[] = {
+ 		.config_intr	= xway_gphy_config_intr,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
++		.led_brightness_set = xway_gphy_led_brightness_set,
++		.led_hw_is_supported = xway_gphy_led_hw_is_supported,
++		.led_hw_control_get = xway_gphy_led_hw_control_get,
++		.led_hw_control_set = xway_gphy_led_hw_control_set,
++		.led_polarity_set = xway_gphy_led_polarity_set,
+ 	}, {
+ 		.phy_id		= PHY_ID_PHY22F_VR9_1_1,
+ 		.phy_id_mask	= 0xffffffff,
+@@ -432,6 +652,11 @@ static struct phy_driver xway_gphy[] = {
+ 		.config_intr	= xway_gphy_config_intr,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
++		.led_brightness_set = xway_gphy_led_brightness_set,
++		.led_hw_is_supported = xway_gphy_led_hw_is_supported,
++		.led_hw_control_get = xway_gphy_led_hw_control_get,
++		.led_hw_control_set = xway_gphy_led_hw_control_set,
++		.led_polarity_set = xway_gphy_led_polarity_set,
+ 	}, {
+ 		.phy_id		= PHY_ID_PHY11G_VR9_1_2,
+ 		.phy_id_mask	= 0xffffffff,
+@@ -442,6 +667,11 @@ static struct phy_driver xway_gphy[] = {
+ 		.config_intr	= xway_gphy_config_intr,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
++		.led_brightness_set = xway_gphy_led_brightness_set,
++		.led_hw_is_supported = xway_gphy_led_hw_is_supported,
++		.led_hw_control_get = xway_gphy_led_hw_control_get,
++		.led_hw_control_set = xway_gphy_led_hw_control_set,
++		.led_polarity_set = xway_gphy_led_polarity_set,
+ 	}, {
+ 		.phy_id		= PHY_ID_PHY22F_VR9_1_2,
+ 		.phy_id_mask	= 0xffffffff,
+@@ -452,6 +682,11 @@ static struct phy_driver xway_gphy[] = {
+ 		.config_intr	= xway_gphy_config_intr,
+ 		.suspend	= genphy_suspend,
+ 		.resume		= genphy_resume,
++		.led_brightness_set = xway_gphy_led_brightness_set,
++		.led_hw_is_supported = xway_gphy_led_hw_is_supported,
++		.led_hw_control_get = xway_gphy_led_hw_control_get,
++		.led_hw_control_set = xway_gphy_led_hw_control_set,
++		.led_polarity_set = xway_gphy_led_polarity_set,
+ 	},
+ };
+ module_phy_driver(xway_gphy);




More information about the lede-commits mailing list