]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: dsa: rtl93xx: allow to adjust LED_CLK 23944/head
authorJonas Jelonek <jelonek.jonas@gmail.com>
Fri, 26 Jun 2026 09:32:34 +0000 (09:32 +0000)
committerJonas Jelonek <jelonek.jonas@gmail.com>
Sat, 27 Jun 2026 08:24:21 +0000 (10:24 +0200)
The LED_GLB_CTRL register has a field to select the clock used for LED
output, either for serial LED output or for the external auxiliary MDIO
to connect a RTL8231. While the default value for the period time of
400ns is the correct one for most applications, some special devices
require a dedicated setting, e.g. UniFi switches with Etherlighting.

Support the generic DT property "clock-frequency" within the LED node,
and read + apply during LED configuration. In case the property isn't
specified, no change is applied to keep previous behavior. In case an
unsupported value is supplied, the default is used as a fallback

Link: https://github.com/openwrt/openwrt/pull/23944
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c
target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c

index 1c83510d9efeeeb48d4faf1698567a3438c137f7..84e00cf86b8c65788b0727f581da4548e19e2a2c 100644 (file)
 #define RTL930X_VLAN_PORT_TAG_STS_CTRL_IGR_P_ITAG_KEEP_MASK    GENMASK(0, 0)
 
 #define RTL930X_LED_GLB_ACTIVE_LOW                             BIT(22)
+#define RTL930X_LED_CLK_SEL_MASK                               GENMASK(17, 16)
+#define RTL930X_LED_CLK_SEL_800NS                              0
+#define RTL930X_LED_CLK_SEL_400NS                              1
+#define RTL930X_LED_CLK_SEL_200NS                              2
+#define RTL930X_LED_CLK_SEL_100NS                              3
 
 #define RTL930X_LED_SETX_0_CTRL(x) (RTL930X_LED_SET0_0_CTRL - (x * 8))
 #define RTL930X_LED_SETX_1_CTRL(x) (RTL930X_LED_SETX_0_CTRL(x) - 4)
@@ -2612,7 +2617,9 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv)
        struct device *dev = priv->dev;
        u8 leds_in_set[4] = {};
        u32 led_mode = 1;
+       u32 clk_freq;
        u32 pm = 0;
+       int ret;
 
        node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds");
        if (!node) {
@@ -2620,6 +2627,32 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv)
                return;
        }
 
+       ret = of_property_read_u32(node, "clock-frequency", &clk_freq);
+       if (!ret) {
+               u8 clk_sel;
+
+               switch (clk_freq) {
+               case 10000000:
+                       clk_sel = RTL930X_LED_CLK_SEL_100NS;
+                       break;
+               case 5000000:
+                       clk_sel = RTL930X_LED_CLK_SEL_200NS;
+                       break;
+               case 1250000:
+                       clk_sel = RTL930X_LED_CLK_SEL_800NS;
+                       break;
+               default:
+                       dev_warn(dev, "invalid LED clock frequency, falling back to default\n");
+                       fallthrough;
+               case 2500000:
+                       clk_sel = RTL930X_LED_CLK_SEL_400NS;
+                       break;
+               }
+
+               sw_w32_mask(RTL930X_LED_CLK_SEL_MASK,
+                           FIELD_PREP(RTL930X_LED_CLK_SEL_MASK, clk_sel), RTL930X_LED_GLB_CTRL);
+       }
+
        for (int set = 0; set < 4; set++) {
                char set_name[16] = {0};
                u32 set_config[4];
index d10517c27eb782f4b3cce57593a03cb9b869868e..e992c45c2231cb3113d508a1a496a5cc12b6f292 100644 (file)
 #define RTL931X_VLAN_PORT_TAG_ITPID_IDX_MASK                   GENMASK(2, 1)
 #define RTL931X_VLAN_PORT_TAG_ITPID_KEEP_MASK                  GENMASK(0, 0)
 
+#define RTL931X_LED_CLK_SEL_MASK                               GENMASK(16, 15)
+#define RTL931X_LED_CLK_SEL_800NS                              0
+#define RTL931X_LED_CLK_SEL_400NS                              1
+#define RTL931X_LED_CLK_SEL_200NS                              2
+#define RTL931X_LED_CLK_SEL_100NS                              3
+
 /* Definition of the RTL931X-specific template field IDs as used in the PIE */
 enum template_field_id {
        TEMPLATE_FIELD_SPM0 = 1,
@@ -1603,6 +1609,8 @@ static void rtldsa_931x_led_init(struct rtl838x_switch_priv *priv)
        struct device *dev = priv->dev;
        struct device_node *node;
        u8 leds_in_set[4] = {};
+       u32 clk_freq;
+       int ret;
 
        node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds");
        if (!node) {
@@ -1610,6 +1618,32 @@ static void rtldsa_931x_led_init(struct rtl838x_switch_priv *priv)
                return;
        }
 
+       ret = of_property_read_u32(node, "clock-frequency", &clk_freq);
+       if (!ret) {
+               u8 clk_sel;
+
+               switch (clk_freq) {
+               case 10000000:
+                       clk_sel = RTL931X_LED_CLK_SEL_100NS;
+                       break;
+               case 5000000:
+                       clk_sel = RTL931X_LED_CLK_SEL_200NS;
+                       break;
+               case 1250000:
+                       clk_sel = RTL931X_LED_CLK_SEL_800NS;
+                       break;
+               default:
+                       dev_warn(dev, "invalid LED clock frequency, falling back to default\n");
+                       fallthrough;
+               case 2500000:
+                       clk_sel = RTL931X_LED_CLK_SEL_400NS;
+                       break;
+               }
+
+               sw_w32_mask(RTL931X_LED_CLK_SEL_MASK,
+                           FIELD_PREP(RTL931X_LED_CLK_SEL_MASK, clk_sel), RTL931X_LED_GLB_CTRL);
+       }
+
        for (int set = 0; set < 4; set++) {
                char set_name[16] = {0};
                u32 set_config[4];