]> www.infradead.org Git - users/hch/misc.git/commitdiff
net: phy: mtk-2p5ge: Add LED support for MT7988
authorSky Huang <skylake.huang@mediatek.com>
Wed, 27 Aug 2025 04:47:55 +0000 (12:47 +0800)
committerJakub Kicinski <kuba@kernel.org>
Thu, 28 Aug 2025 23:43:21 +0000 (16:43 -0700)
Add LED support for MT7988's built-in 2.5Gphy. LED hardware has almost
the same design with MT7981's/MT7988's built-in GbE. So hook the same
helper function here.

Before mtk_phy_leds_state_init(), set correct default values of LED0
and LED1.

Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20250827044755.3256991-1-SkyLake.Huang@mediatek.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/phy/mediatek/mtk-2p5ge.c

index e147eab523ef2486cb4d2ebbc2a3b63d3e87d98d..de8a41a1841da1e516e7c3b2ca91d533e6a9737d 100644 (file)
@@ -249,8 +249,80 @@ static int mt798x_2p5ge_phy_get_rate_matching(struct phy_device *phydev,
        return RATE_MATCH_PAUSE;
 }
 
+static const unsigned long supported_triggers =
+       BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
+       BIT(TRIGGER_NETDEV_LINK)        |
+       BIT(TRIGGER_NETDEV_LINK_10)     |
+       BIT(TRIGGER_NETDEV_LINK_100)    |
+       BIT(TRIGGER_NETDEV_LINK_1000)   |
+       BIT(TRIGGER_NETDEV_LINK_2500)   |
+       BIT(TRIGGER_NETDEV_RX)          |
+       BIT(TRIGGER_NETDEV_TX);
+
+static int mt798x_2p5ge_phy_led_blink_set(struct phy_device *phydev, u8 index,
+                                         unsigned long *delay_on,
+                                         unsigned long *delay_off)
+{
+       bool blinking = false;
+       int err = 0;
+
+       err = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, &blinking);
+       if (err < 0)
+               return err;
+
+       err = mtk_phy_hw_led_blink_set(phydev, index, blinking);
+       if (err)
+               return err;
+
+       if (blinking)
+               mtk_phy_hw_led_on_set(phydev, index, MTK_2P5GPHY_LED_ON_MASK,
+                                     false);
+
+       return 0;
+}
+
+static int mt798x_2p5ge_phy_led_brightness_set(struct phy_device *phydev,
+                                              u8 index,
+                                              enum led_brightness value)
+{
+       int err;
+
+       err = mtk_phy_hw_led_blink_set(phydev, index, false);
+       if (err)
+               return err;
+
+       return mtk_phy_hw_led_on_set(phydev, index, MTK_2P5GPHY_LED_ON_MASK,
+                                    (value != LED_OFF));
+}
+
+static int mt798x_2p5ge_phy_led_hw_is_supported(struct phy_device *phydev,
+                                               u8 index, unsigned long rules)
+{
+       return mtk_phy_led_hw_is_supported(phydev, index, rules,
+                                          supported_triggers);
+}
+
+static int mt798x_2p5ge_phy_led_hw_control_get(struct phy_device *phydev,
+                                              u8 index, unsigned long *rules)
+{
+       return mtk_phy_led_hw_ctrl_get(phydev, index, rules,
+                                      MTK_2P5GPHY_LED_ON_SET,
+                                      MTK_2P5GPHY_LED_RX_BLINK_SET,
+                                      MTK_2P5GPHY_LED_TX_BLINK_SET);
+};
+
+static int mt798x_2p5ge_phy_led_hw_control_set(struct phy_device *phydev,
+                                              u8 index, unsigned long rules)
+{
+       return mtk_phy_led_hw_ctrl_set(phydev, index, rules,
+                                      MTK_2P5GPHY_LED_ON_SET,
+                                      MTK_2P5GPHY_LED_RX_BLINK_SET,
+                                      MTK_2P5GPHY_LED_TX_BLINK_SET);
+};
+
 static int mt798x_2p5ge_phy_probe(struct phy_device *phydev)
 {
+       struct mtk_socphy_priv *priv;
        struct pinctrl *pinctrl;
        int ret;
 
@@ -273,19 +345,34 @@ static int mt798x_2p5ge_phy_probe(struct phy_device *phydev)
        if (ret < 0)
                return ret;
 
-       /* Setup LED */
+       /* Setup LED. On default, LED0 is on/off when link is up/down. As for
+        * LED1, it blinks as tx/rx transmission takes place.
+        */
        phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
-                        MTK_PHY_LED_ON_POLARITY | MTK_PHY_LED_ON_LINK10 |
-                        MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK1000 |
-                        MTK_PHY_LED_ON_LINK2500);
-       phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
-                        MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX);
+                        MTK_PHY_LED_ON_POLARITY | MTK_2P5GPHY_LED_ON_SET);
+       phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_BLINK_CTRL,
+                          MTK_2P5GPHY_LED_TX_BLINK_SET |
+                          MTK_2P5GPHY_LED_RX_BLINK_SET);
+       phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
+                          MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX |
+                          MTK_2P5GPHY_LED_ON_SET);
+       phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_BLINK_CTRL,
+                        MTK_2P5GPHY_LED_TX_BLINK_SET |
+                        MTK_2P5GPHY_LED_RX_BLINK_SET);
 
        /* Switch pinctrl after setting polarity to avoid bogus blinking */
        pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "i2p5gbe-led");
        if (IS_ERR(pinctrl))
                dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n");
 
+       priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct mtk_socphy_priv),
+                           GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+       phydev->priv = priv;
+
+       mtk_phy_leds_state_init(phydev);
+
        return 0;
 }
 
@@ -303,6 +390,11 @@ static struct phy_driver mtk_2p5gephy_driver[] = {
                .resume = genphy_resume,
                .read_page = mtk_phy_read_page,
                .write_page = mtk_phy_write_page,
+               .led_blink_set = mt798x_2p5ge_phy_led_blink_set,
+               .led_brightness_set = mt798x_2p5ge_phy_led_brightness_set,
+               .led_hw_is_supported = mt798x_2p5ge_phy_led_hw_is_supported,
+               .led_hw_control_get = mt798x_2p5ge_phy_led_hw_control_get,
+               .led_hw_control_set = mt798x_2p5ge_phy_led_hw_control_set,
        },
 };