The BCM54213E and similar PHYs have extensive LED configuration capabilities -- the PHY has two LEDs, either of the two LEDs can be configured to 1 of 16 functions (speed, TX, RX, activity, on, off, quality, ... multi-color) used to drive single-color LED. The multi-color mode is special, it provides 16 more sub-modes used to drive multi-color LED. The current configuration -- both LEDs configured as multi-color, with both LEDs multi-color sub-mode set to link activity indicator, is not suitable for all systems in which this PHY is used. Attempt to implement a way to describe the LED configuration in DT. Use Documentation/devicetree/bindings/net/ethernet-phy.yaml leds {} subnode of the PHY DT node, describe both LEDs present on this PHY as single LEDs within the leds {} subnode. Each described LED is a subnode of its own, the description uses standard LED subsystem bindings from Documentation/devicetree/bindings/leds/common.yaml . The DT description of the LED configuration can look for example like this: " ethernet-phy@1 { ... leds { #address-cells = <1>; #size-cells = <0>; led@0 { reg = <0>; function = LED_FUNCTION_ACTIVITY; }; led@1 { reg = <1>; function = LED_FUNCTION_SPEED_2; }; }; }; " Implement parsing code in the broadcom PHY driver to detemine desired LED configuration from DT. In case the leds {} subnode is present, the parser code iterates over its subnodes and for each led@N subnode it parses the following properties: - reg - LED ID, either 0 or 1, used to identify the LED on the PHY - function - LED single-color function (speed, TX, RX, multi-color...), uses LED subsystem LED_FUNCTION_* string. The parser in the driver maps this to register setting. - function-enumerator - In case function is set to "multi-color", the multi-color function number. The parser in the driver uses this value directly for the multi-color configuration register. Once the properties are parsed, the LED configuration registers of the PHY are programmed. The current list of LED subsystem LED_FUNCTION_* does not cover the entire list of possible single-color LED functions of this PHY, add example extension for "link speed 1" and "link speed 2" setting into the leds/common.h header file. The function-enumerator should probably not be a number, but maybe some sort of macro specific to this PHY ? I would like to avoid new broadcom PHY specific DT properties. Signed-off-by: Marek Vasut <marex@xxxxxxx> --- Cc: "David S. Miller" <davem@xxxxxxxxxxxxx> Cc: Andrew Lunn <andrew@xxxxxxx> Cc: Broadcom internal kernel review list <bcm-kernel-feedback-list@xxxxxxxxxxxx> Cc: Conor Dooley <conor+dt@xxxxxxxxxx> Cc: Eric Dumazet <edumazet@xxxxxxxxxx> Cc: Florian Fainelli <florian.fainelli@xxxxxxxxxxxx> Cc: Heiner Kallweit <hkallweit1@xxxxxxxxx> Cc: Jakub Kicinski <kuba@xxxxxxxxxx> Cc: Krzysztof Kozlowski <krzysztof.kozlowski+dt@xxxxxxxxxx> Cc: Lee Jones <lee@xxxxxxxxxx> Cc: Paolo Abeni <pabeni@xxxxxxxxxx> Cc: Pavel Machek <pavel@xxxxxx> Cc: Rafał Miłecki <rafal@xxxxxxxxxx> Cc: Rob Herring <robh+dt@xxxxxxxxxx> Cc: Russell King <linux@xxxxxxxxxxxxxxx> Cc: devicetree@xxxxxxxxxxxxxxx Cc: linux-leds@xxxxxxxxxxxxxxx Cc: netdev@xxxxxxxxxxxxxxx --- drivers/net/phy/broadcom.c | 56 +++++++++++++++++++++++++++---- include/dt-bindings/leds/common.h | 2 ++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 312a8bb35d780..9250cd45b0b24 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -407,20 +407,64 @@ static int bcm54xx_config_init(struct phy_device *phydev) /* For non-SFP setups, encode link speed into LED1 and LED3 pair * (green/amber). - * Also flash these two LEDs on activity. This means configuring - * them for MULTICOLOR and encoding link/activity into them. + * By default, flash these two LEDs on activity. This means + * configuring them for MULTICOLOR and encoding link/activity + * into them, but let user reconfigure this via DT. * Don't do this for devices on an SFP module, since some of these * use the LED outputs to control the SFP LOS signal, and changing * these settings will cause LOS to malfunction. */ if (!phy_on_sfp(phydev)) { - val = BCM54XX_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) | - BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1); + struct device_node *np = phydev->mdio.dev.of_node; + struct device_node *leds, *led = NULL; + u8 mode[2] = { BCM_LED_SRC_MULTICOLOR1, BCM_LED_SRC_MULTICOLOR1 }; + u8 mcmode[2] = { BCM_LED_MULTICOLOR_LINK_ACT, BCM_LED_MULTICOLOR_LINK_ACT }; + const char *func; + u32 val, enumerator; + int ret; + + leds = of_find_node_by_name(np, "leds"); + if (leds) { + for_each_available_child_of_node(leds, led) { + ret = of_property_read_u32(led, "reg", &val); + if (ret < 0 || val >= 2) + continue; + + ret = of_property_read_string(led, "function", &func); + if (ret) + continue; + + if (!strcmp(func, LED_FUNCTION_TX)) + mode[val] = BCM_LED_SRC_XMITLED; + else if (!strcmp(func, LED_FUNCTION_RX)) + mode[val] = BCM_LED_SRC_RCVLED; + else if (!strcmp(func, LED_FUNCTION_ACTIVITY)) + mode[val] = BCM_LED_SRC_ACTIVITYLED; + else if (!strcmp(func, LED_FUNCTION_SPEED_1)) + mode[val] = BCM_LED_SRC_LINKSPD1; + else if (!strcmp(func, LED_FUNCTION_SPEED_2)) + mode[val] = BCM_LED_SRC_LINKSPD2; + /* Add other LED settings here */ + + ret = of_property_read_string(led, "function", &func); + if (ret) + continue; + + ret = of_property_read_u32(led, "function-enumerator", &enumerator); + if (ret || enumerator >= 16) + continue; + + mcmode[val] = enumerator; + } + } + + val = BCM54XX_SHD_LEDS1_LED1(mode[0]) | + BCM54XX_SHD_LEDS1_LED3(mode[1]); bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1, val); val = BCM_LED_MULTICOLOR_IN_PHASE | - BCM54XX_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) | - BCM54XX_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT); + BCM54XX_SHD_LEDS1_LED1(mcmode[0]) | + BCM54XX_SHD_LEDS1_LED3(mcmode[1]); bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val); } diff --git a/include/dt-bindings/leds/common.h b/include/dt-bindings/leds/common.h index 9a0d33d027fff..83d09508841b6 100644 --- a/include/dt-bindings/leds/common.h +++ b/include/dt-bindings/leds/common.h @@ -102,5 +102,7 @@ #define LED_FUNCTION_WAN "wan" #define LED_FUNCTION_WLAN "wlan" #define LED_FUNCTION_WPS "wps" +#define LED_FUNCTION_SPEED_1 "speed-1" +#define LED_FUNCTION_SPEED_2 "speed-2" #endif /* __DT_BINDINGS_LEDS_H */ -- 2.43.0