generic: backport initial LEDs hw control support
[openwrt/openwrt.git] / target / linux / generic / backport-6.1 / 801-v6.4-03-net-dsa-qca8k-add-LEDs-blink_set-support.patch
1 From 91acadcc6e599dfc62717abcdad58a459cfb1684 Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Mon, 17 Apr 2023 17:17:25 +0200
4 Subject: [PATCH 3/9] net: dsa: qca8k: add LEDs blink_set() support
5
6 Add LEDs blink_set() support to qca8k Switch Family.
7 These LEDs support hw accellerated blinking at a fixed rate
8 of 4Hz.
9
10 Reject any other value since not supported by the LEDs switch.
11
12 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
13 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
14 Acked-by: Pavel Machek <pavel@ucw.cz>
15 Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
16 Signed-off-by: David S. Miller <davem@davemloft.net>
17 ---
18 drivers/net/dsa/qca/qca8k-leds.c | 38 ++++++++++++++++++++++++++++++++
19 1 file changed, 38 insertions(+)
20
21 --- a/drivers/net/dsa/qca/qca8k-leds.c
22 +++ b/drivers/net/dsa/qca/qca8k-leds.c
23 @@ -128,6 +128,43 @@ qca8k_led_brightness_get(struct qca8k_le
24 }
25
26 static int
27 +qca8k_cled_blink_set(struct led_classdev *ldev,
28 + unsigned long *delay_on,
29 + unsigned long *delay_off)
30 +{
31 + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
32 + u32 mask, val = QCA8K_LED_ALWAYS_BLINK_4HZ;
33 + struct qca8k_led_pattern_en reg_info;
34 + struct qca8k_priv *priv = led->priv;
35 +
36 + if (*delay_on == 0 && *delay_off == 0) {
37 + *delay_on = 125;
38 + *delay_off = 125;
39 + }
40 +
41 + if (*delay_on != 125 || *delay_off != 125) {
42 + /* The hardware only supports blinking at 4Hz. Fall back
43 + * to software implementation in other cases.
44 + */
45 + return -EINVAL;
46 + }
47 +
48 + qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
49 +
50 + if (led->port_num == 0 || led->port_num == 4) {
51 + mask = QCA8K_LED_PATTERN_EN_MASK;
52 + val <<= QCA8K_LED_PATTERN_EN_SHIFT;
53 + } else {
54 + mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
55 + }
56 +
57 + regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift,
58 + val << reg_info.shift);
59 +
60 + return 0;
61 +}
62 +
63 +static int
64 qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num)
65 {
66 struct fwnode_handle *led = NULL, *leds = NULL;
67 @@ -186,6 +223,7 @@ qca8k_parse_port_leds(struct qca8k_priv
68
69 port_led->cdev.max_brightness = 1;
70 port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking;
71 + port_led->cdev.blink_set = qca8k_cled_blink_set;
72 init_data.default_label = ":port";
73 init_data.fwnode = led;
74 init_data.devname_mandatory = true;