OSDN Git Service

net: dsa: qca8k: add LEDs blink_set() support
authorChristian Marangi <ansuelsmth@gmail.com>
Mon, 17 Apr 2023 15:17:25 +0000 (17:17 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 19 Apr 2023 11:59:15 +0000 (12:59 +0100)
Add LEDs blink_set() support to qca8k Switch Family.
These LEDs support hw accellerated blinking at a fixed rate
of 4Hz.

Reject any other value since not supported by the LEDs switch.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Pavel Machek <pavel@ucw.cz>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/qca/qca8k-leds.c

index 0146ee1..b883692 100644 (file)
@@ -128,6 +128,43 @@ qca8k_led_brightness_get(struct qca8k_led *led)
 }
 
 static int
+qca8k_cled_blink_set(struct led_classdev *ldev,
+                    unsigned long *delay_on,
+                    unsigned long *delay_off)
+{
+       struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
+       u32 mask, val = QCA8K_LED_ALWAYS_BLINK_4HZ;
+       struct qca8k_led_pattern_en reg_info;
+       struct qca8k_priv *priv = led->priv;
+
+       if (*delay_on == 0 && *delay_off == 0) {
+               *delay_on = 125;
+               *delay_off = 125;
+       }
+
+       if (*delay_on != 125 || *delay_off != 125) {
+               /* The hardware only supports blinking at 4Hz. Fall back
+                * to software implementation in other cases.
+                */
+               return -EINVAL;
+       }
+
+       qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
+
+       if (led->port_num == 0 || led->port_num == 4) {
+               mask = QCA8K_LED_PATTERN_EN_MASK;
+               val <<= QCA8K_LED_PATTERN_EN_SHIFT;
+       } else {
+               mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
+       }
+
+       regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift,
+                          val << reg_info.shift);
+
+       return 0;
+}
+
+static int
 qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num)
 {
        struct fwnode_handle *led = NULL, *leds = NULL;
@@ -186,6 +223,7 @@ qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int p
 
                port_led->cdev.max_brightness = 1;
                port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking;
+               port_led->cdev.blink_set = qca8k_cled_blink_set;
                init_data.default_label = ":port";
                init_data.fwnode = led;
                init_data.devname_mandatory = true;