Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'dsa-realtek-leds'

Luiz Angelo Daros de Luca says:

====================
net: dsa: realtek: fix LED support for rtl8366

This series fixes the LED support for rtl8366. The existing code was not
tested in a device with switch LEDs and it was using a flawed logic.

The driver now keeps the default LED configuration if nothing requests a
different behavior. This may be enough for most devices. This can be
achieved either by omitting the LED from the device-tree or configuring
all LEDs in a group with the default state set to "keep".

The hardware trigger for LEDs in Realtek switches is shared among all
LEDs in a group. This behavior doesn't align well with the Linux LED
API, which controls LEDs individually. Once the OS changes the
brightness of a LED in a group still triggered by the hardware, the
entire group switches to software-controlled LEDs, even for those not
metioned in the device-tree. This shared behavior also prevents
offloading the trigger to the hardware as it would require an
orchestration between LEDs in a group, not currently present in the LED
API.

The assertion of device hardware reset during driver removal was removed
because it was causing an issue with the LED release code. Devres
devices are released after the driver's removal is executed. Asserting
the reset at that point was causing timeout errors during LED release
when it attempted to turn off the LED.

To: Linus Walleij <linus.walleij@linaro.org>
To: Alvin Šipraga <alsi@bang-olufsen.dk>
To: Andrew Lunn <andrew@lunn.ch>
To: Florian Fainelli <f.fainelli@gmail.com>
To: Vladimir Oltean <olteanv@gmail.com>
To: David S. Miller <davem@davemloft.net>
To: Eric Dumazet <edumazet@google.com>
To: Jakub Kicinski <kuba@kernel.org>
To: Paolo Abeni <pabeni@redhat.com>
To: Rob Herring <robh+dt@kernel.org>
To: Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>
To: Conor Dooley <conor+dt@kernel.org>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: devicetree@vger.kernel.org
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>

Changes in v2:
- Fixed commit message formatting
- Added GROUP to LED group enum values. With that, moved the code that
disables LED into a new function to keep 80-collumn limit.
- Dropped unused enable argument in rb8366rb_get_port_led()
- Fixed variable order in rtl8366rb_setup_led()
- Removed redundant led group test in rb8366rb_{g,s}et_port_led()
- Initialize ret as 0 in rtl8366rb_setup_leds()
- Updated comments related to LED blinking and setup
- Link to v1: https://lore.kernel.org/r/20240310-realtek-led-v1-0-4d9813ce938e@gmail.com

Changes in v1:
- Rebased on new relatek DSA drivers
- Improved commit messages
- Added commit to remove the reset assert during .remove
- Link to RFC: https://lore.kernel.org/r/20240106184651.3665-1-luizluca@gmail.com
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+273 -97
+271 -92
drivers/net/dsa/realtek/rtl8366rb.c
··· 176 176 #define RTL8366RB_VLAN_INGRESS_CTRL2_REG 0x037f 177 177 178 178 /* LED control registers */ 179 + /* The LED blink rate is global; it is used by all triggers in all groups. */ 179 180 #define RTL8366RB_LED_BLINKRATE_REG 0x0430 180 181 #define RTL8366RB_LED_BLINKRATE_MASK 0x0007 181 182 #define RTL8366RB_LED_BLINKRATE_28MS 0x0000 ··· 186 185 #define RTL8366RB_LED_BLINKRATE_222MS 0x0004 187 186 #define RTL8366RB_LED_BLINKRATE_446MS 0x0005 188 187 188 + /* LED trigger event for each group */ 189 189 #define RTL8366RB_LED_CTRL_REG 0x0431 190 - #define RTL8366RB_LED_OFF 0x0 191 - #define RTL8366RB_LED_DUP_COL 0x1 192 - #define RTL8366RB_LED_LINK_ACT 0x2 193 - #define RTL8366RB_LED_SPD1000 0x3 194 - #define RTL8366RB_LED_SPD100 0x4 195 - #define RTL8366RB_LED_SPD10 0x5 196 - #define RTL8366RB_LED_SPD1000_ACT 0x6 197 - #define RTL8366RB_LED_SPD100_ACT 0x7 198 - #define RTL8366RB_LED_SPD10_ACT 0x8 199 - #define RTL8366RB_LED_SPD100_10_ACT 0x9 200 - #define RTL8366RB_LED_FIBER 0xa 201 - #define RTL8366RB_LED_AN_FAULT 0xb 202 - #define RTL8366RB_LED_LINK_RX 0xc 203 - #define RTL8366RB_LED_LINK_TX 0xd 204 - #define RTL8366RB_LED_MASTER 0xe 205 - #define RTL8366RB_LED_FORCE 0xf 190 + #define RTL8366RB_LED_CTRL_OFFSET(led_group) \ 191 + (4 * (led_group)) 192 + #define RTL8366RB_LED_CTRL_MASK(led_group) \ 193 + (0xf << RTL8366RB_LED_CTRL_OFFSET(led_group)) 194 + 195 + /* The RTL8366RB_LED_X_X registers are used to manually set the LED state only 196 + * when the corresponding LED group in RTL8366RB_LED_CTRL_REG is 197 + * RTL8366RB_LEDGROUP_FORCE. Otherwise, it is ignored. 198 + */ 206 199 #define RTL8366RB_LED_0_1_CTRL_REG 0x0432 207 - #define RTL8366RB_LED_1_OFFSET 6 208 200 #define RTL8366RB_LED_2_3_CTRL_REG 0x0433 209 - #define RTL8366RB_LED_3_OFFSET 6 201 + #define RTL8366RB_LED_X_X_CTRL_REG(led_group) \ 202 + ((led_group) <= 1 ? \ 203 + RTL8366RB_LED_0_1_CTRL_REG : \ 204 + RTL8366RB_LED_2_3_CTRL_REG) 205 + #define RTL8366RB_LED_0_X_CTRL_MASK GENMASK(5, 0) 206 + #define RTL8366RB_LED_X_1_CTRL_MASK GENMASK(11, 6) 207 + #define RTL8366RB_LED_2_X_CTRL_MASK GENMASK(5, 0) 208 + #define RTL8366RB_LED_X_3_CTRL_MASK GENMASK(11, 6) 210 209 211 210 #define RTL8366RB_MIB_COUNT 33 212 211 #define RTL8366RB_GLOBAL_MIB_COUNT 1 ··· 350 349 #define RTL8366RB_GREEN_FEATURE_TX BIT(0) 351 350 #define RTL8366RB_GREEN_FEATURE_RX BIT(2) 352 351 352 + enum rtl8366_ledgroup_mode { 353 + RTL8366RB_LEDGROUP_OFF = 0x0, 354 + RTL8366RB_LEDGROUP_DUP_COL = 0x1, 355 + RTL8366RB_LEDGROUP_LINK_ACT = 0x2, 356 + RTL8366RB_LEDGROUP_SPD1000 = 0x3, 357 + RTL8366RB_LEDGROUP_SPD100 = 0x4, 358 + RTL8366RB_LEDGROUP_SPD10 = 0x5, 359 + RTL8366RB_LEDGROUP_SPD1000_ACT = 0x6, 360 + RTL8366RB_LEDGROUP_SPD100_ACT = 0x7, 361 + RTL8366RB_LEDGROUP_SPD10_ACT = 0x8, 362 + RTL8366RB_LEDGROUP_SPD100_10_ACT = 0x9, 363 + RTL8366RB_LEDGROUP_FIBER = 0xa, 364 + RTL8366RB_LEDGROUP_AN_FAULT = 0xb, 365 + RTL8366RB_LEDGROUP_LINK_RX = 0xc, 366 + RTL8366RB_LEDGROUP_LINK_TX = 0xd, 367 + RTL8366RB_LEDGROUP_MASTER = 0xe, 368 + RTL8366RB_LEDGROUP_FORCE = 0xf, 369 + 370 + __RTL8366RB_LEDGROUP_MODE_MAX 371 + }; 372 + 373 + struct rtl8366rb_led { 374 + u8 port_num; 375 + u8 led_group; 376 + struct realtek_priv *priv; 377 + struct led_classdev cdev; 378 + }; 379 + 353 380 /** 354 381 * struct rtl8366rb - RTL8366RB-specific data 355 382 * @max_mtu: per-port max MTU setting 356 383 * @pvid_enabled: if PVID is set for respective port 384 + * @leds: per-port and per-ledgroup led info 357 385 */ 358 386 struct rtl8366rb { 359 387 unsigned int max_mtu[RTL8366RB_NUM_PORTS]; 360 388 bool pvid_enabled[RTL8366RB_NUM_PORTS]; 389 + struct rtl8366rb_led leds[RTL8366RB_NUM_PORTS][RTL8366RB_NUM_LEDGROUPS]; 361 390 }; 362 391 363 392 static struct rtl8366_mib_counter rtl8366rb_mib_counters[] = { ··· 830 799 return 0; 831 800 } 832 801 802 + static int rb8366rb_set_ledgroup_mode(struct realtek_priv *priv, 803 + u8 led_group, 804 + enum rtl8366_ledgroup_mode mode) 805 + { 806 + int ret; 807 + u32 val; 808 + 809 + val = mode << RTL8366RB_LED_CTRL_OFFSET(led_group); 810 + 811 + ret = regmap_update_bits(priv->map, 812 + RTL8366RB_LED_CTRL_REG, 813 + RTL8366RB_LED_CTRL_MASK(led_group), 814 + val); 815 + if (ret) 816 + return ret; 817 + 818 + return 0; 819 + } 820 + 821 + static inline u32 rtl8366rb_led_group_port_mask(u8 led_group, u8 port) 822 + { 823 + switch (led_group) { 824 + case 0: 825 + return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port)); 826 + case 1: 827 + return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port)); 828 + case 2: 829 + return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port)); 830 + case 3: 831 + return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port)); 832 + default: 833 + return 0; 834 + } 835 + } 836 + 837 + static int rb8366rb_get_port_led(struct rtl8366rb_led *led) 838 + { 839 + struct realtek_priv *priv = led->priv; 840 + u8 led_group = led->led_group; 841 + u8 port_num = led->port_num; 842 + int ret; 843 + u32 val; 844 + 845 + ret = regmap_read(priv->map, RTL8366RB_LED_X_X_CTRL_REG(led_group), 846 + &val); 847 + if (ret) { 848 + dev_err(priv->dev, "error reading LED on port %d group %d\n", 849 + led_group, port_num); 850 + return ret; 851 + } 852 + 853 + return !!(val & rtl8366rb_led_group_port_mask(led_group, port_num)); 854 + } 855 + 856 + static int rb8366rb_set_port_led(struct rtl8366rb_led *led, bool enable) 857 + { 858 + struct realtek_priv *priv = led->priv; 859 + u8 led_group = led->led_group; 860 + u8 port_num = led->port_num; 861 + int ret; 862 + 863 + ret = regmap_update_bits(priv->map, 864 + RTL8366RB_LED_X_X_CTRL_REG(led_group), 865 + rtl8366rb_led_group_port_mask(led_group, 866 + port_num), 867 + enable ? 0xffff : 0); 868 + if (ret) { 869 + dev_err(priv->dev, "error updating LED on port %d group %d\n", 870 + led_group, port_num); 871 + return ret; 872 + } 873 + 874 + /* Change the LED group to manual controlled LEDs if required */ 875 + ret = rb8366rb_set_ledgroup_mode(priv, led_group, 876 + RTL8366RB_LEDGROUP_FORCE); 877 + 878 + if (ret) { 879 + dev_err(priv->dev, "error updating LED GROUP group %d\n", 880 + led_group); 881 + return ret; 882 + } 883 + 884 + return 0; 885 + } 886 + 887 + static int 888 + rtl8366rb_cled_brightness_set_blocking(struct led_classdev *ldev, 889 + enum led_brightness brightness) 890 + { 891 + struct rtl8366rb_led *led = container_of(ldev, struct rtl8366rb_led, 892 + cdev); 893 + 894 + return rb8366rb_set_port_led(led, brightness == LED_ON); 895 + } 896 + 897 + static int rtl8366rb_setup_led(struct realtek_priv *priv, struct dsa_port *dp, 898 + struct fwnode_handle *led_fwnode) 899 + { 900 + struct rtl8366rb *rb = priv->chip_data; 901 + struct led_init_data init_data = { }; 902 + enum led_default_state state; 903 + struct rtl8366rb_led *led; 904 + u32 led_group; 905 + int ret; 906 + 907 + ret = fwnode_property_read_u32(led_fwnode, "reg", &led_group); 908 + if (ret) 909 + return ret; 910 + 911 + if (led_group >= RTL8366RB_NUM_LEDGROUPS) { 912 + dev_warn(priv->dev, "Invalid LED reg %d defined for port %d", 913 + led_group, dp->index); 914 + return -EINVAL; 915 + } 916 + 917 + led = &rb->leds[dp->index][led_group]; 918 + led->port_num = dp->index; 919 + led->led_group = led_group; 920 + led->priv = priv; 921 + 922 + state = led_init_default_state_get(led_fwnode); 923 + switch (state) { 924 + case LEDS_DEFSTATE_ON: 925 + led->cdev.brightness = 1; 926 + rb8366rb_set_port_led(led, 1); 927 + break; 928 + case LEDS_DEFSTATE_KEEP: 929 + led->cdev.brightness = 930 + rb8366rb_get_port_led(led); 931 + break; 932 + case LEDS_DEFSTATE_OFF: 933 + default: 934 + led->cdev.brightness = 0; 935 + rb8366rb_set_port_led(led, 0); 936 + } 937 + 938 + led->cdev.max_brightness = 1; 939 + led->cdev.brightness_set_blocking = 940 + rtl8366rb_cled_brightness_set_blocking; 941 + init_data.fwnode = led_fwnode; 942 + init_data.devname_mandatory = true; 943 + 944 + init_data.devicename = kasprintf(GFP_KERNEL, "Realtek-%d:0%d:%d", 945 + dp->ds->index, dp->index, led_group); 946 + if (!init_data.devicename) 947 + return -ENOMEM; 948 + 949 + ret = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data); 950 + if (ret) { 951 + dev_warn(priv->dev, "Failed to init LED %d for port %d", 952 + led_group, dp->index); 953 + return ret; 954 + } 955 + 956 + return 0; 957 + } 958 + 959 + static int rtl8366rb_setup_all_leds_off(struct realtek_priv *priv) 960 + { 961 + int ret = 0; 962 + int i; 963 + 964 + regmap_update_bits(priv->map, 965 + RTL8366RB_INTERRUPT_CONTROL_REG, 966 + RTL8366RB_P4_RGMII_LED, 967 + 0); 968 + 969 + for (i = 0; i < RTL8366RB_NUM_LEDGROUPS; i++) { 970 + ret = rb8366rb_set_ledgroup_mode(priv, i, 971 + RTL8366RB_LEDGROUP_OFF); 972 + if (ret) 973 + return ret; 974 + } 975 + 976 + return ret; 977 + } 978 + 979 + static int rtl8366rb_setup_leds(struct realtek_priv *priv) 980 + { 981 + struct device_node *leds_np, *led_np; 982 + struct dsa_switch *ds = &priv->ds; 983 + struct dsa_port *dp; 984 + int ret = 0; 985 + 986 + dsa_switch_for_each_port(dp, ds) { 987 + if (!dp->dn) 988 + continue; 989 + 990 + leds_np = of_get_child_by_name(dp->dn, "leds"); 991 + if (!leds_np) { 992 + dev_dbg(priv->dev, "No leds defined for port %d", 993 + dp->index); 994 + continue; 995 + } 996 + 997 + for_each_child_of_node(leds_np, led_np) { 998 + ret = rtl8366rb_setup_led(priv, dp, 999 + of_fwnode_handle(led_np)); 1000 + if (ret) { 1001 + of_node_put(led_np); 1002 + break; 1003 + } 1004 + } 1005 + 1006 + of_node_put(leds_np); 1007 + if (ret) 1008 + return ret; 1009 + } 1010 + return 0; 1011 + } 1012 + 833 1013 static int rtl8366rb_setup(struct dsa_switch *ds) 834 1014 { 835 1015 struct realtek_priv *priv = ds->priv; ··· 1049 807 u32 chip_ver = 0; 1050 808 u32 chip_id = 0; 1051 809 int jam_size; 1052 - u32 val; 1053 810 int ret; 1054 811 int i; 1055 812 ··· 1228 987 if (ret) 1229 988 return ret; 1230 989 1231 - /* Set blinking, TODO: make this configurable */ 990 + /* Set blinking, used by all LED groups using HW triggers. 991 + * TODO: make this configurable 992 + */ 1232 993 ret = regmap_update_bits(priv->map, RTL8366RB_LED_BLINKRATE_REG, 1233 994 RTL8366RB_LED_BLINKRATE_MASK, 1234 995 RTL8366RB_LED_BLINKRATE_56MS); ··· 1238 995 return ret; 1239 996 1240 997 /* Set up LED activity: 1241 - * Each port has 4 LEDs, we configure all ports to the same 1242 - * behaviour (no individual config) but we can set up each 1243 - * LED separately. 998 + * Each port has 4 LEDs on fixed groups. Each group shares the same 999 + * hardware trigger across all ports. LEDs can only be indiviually 1000 + * controlled setting the LED group to fixed mode and using the driver 1001 + * to toggle them LEDs on/off. 1244 1002 */ 1245 1003 if (priv->leds_disabled) { 1246 - /* Turn everything off */ 1247 - regmap_update_bits(priv->map, 1248 - RTL8366RB_LED_0_1_CTRL_REG, 1249 - 0x0FFF, 0); 1250 - regmap_update_bits(priv->map, 1251 - RTL8366RB_LED_2_3_CTRL_REG, 1252 - 0x0FFF, 0); 1253 - regmap_update_bits(priv->map, 1254 - RTL8366RB_INTERRUPT_CONTROL_REG, 1255 - RTL8366RB_P4_RGMII_LED, 1256 - 0); 1257 - val = RTL8366RB_LED_OFF; 1004 + ret = rtl8366rb_setup_all_leds_off(priv); 1005 + if (ret) 1006 + return ret; 1258 1007 } else { 1259 - /* TODO: make this configurable per LED */ 1260 - val = RTL8366RB_LED_FORCE; 1261 - } 1262 - for (i = 0; i < 4; i++) { 1263 - ret = regmap_update_bits(priv->map, 1264 - RTL8366RB_LED_CTRL_REG, 1265 - 0xf << (i * 4), 1266 - val << (i * 4)); 1008 + ret = rtl8366rb_setup_leds(priv); 1267 1009 if (ret) 1268 1010 return ret; 1269 1011 } ··· 1395 1167 } 1396 1168 } 1397 1169 1398 - static void rb8366rb_set_port_led(struct realtek_priv *priv, 1399 - int port, bool enable) 1400 - { 1401 - u16 val = enable ? 0x3f : 0; 1402 - int ret; 1403 - 1404 - if (priv->leds_disabled) 1405 - return; 1406 - 1407 - switch (port) { 1408 - case 0: 1409 - ret = regmap_update_bits(priv->map, 1410 - RTL8366RB_LED_0_1_CTRL_REG, 1411 - 0x3F, val); 1412 - break; 1413 - case 1: 1414 - ret = regmap_update_bits(priv->map, 1415 - RTL8366RB_LED_0_1_CTRL_REG, 1416 - 0x3F << RTL8366RB_LED_1_OFFSET, 1417 - val << RTL8366RB_LED_1_OFFSET); 1418 - break; 1419 - case 2: 1420 - ret = regmap_update_bits(priv->map, 1421 - RTL8366RB_LED_2_3_CTRL_REG, 1422 - 0x3F, val); 1423 - break; 1424 - case 3: 1425 - ret = regmap_update_bits(priv->map, 1426 - RTL8366RB_LED_2_3_CTRL_REG, 1427 - 0x3F << RTL8366RB_LED_3_OFFSET, 1428 - val << RTL8366RB_LED_3_OFFSET); 1429 - break; 1430 - case 4: 1431 - ret = regmap_update_bits(priv->map, 1432 - RTL8366RB_INTERRUPT_CONTROL_REG, 1433 - RTL8366RB_P4_RGMII_LED, 1434 - enable ? RTL8366RB_P4_RGMII_LED : 0); 1435 - break; 1436 - default: 1437 - dev_err(priv->dev, "no LED for port %d\n", port); 1438 - return; 1439 - } 1440 - if (ret) 1441 - dev_err(priv->dev, "error updating LED on port %d\n", port); 1442 - } 1443 - 1444 1170 static int 1445 1171 rtl8366rb_port_enable(struct dsa_switch *ds, int port, 1446 1172 struct phy_device *phy) ··· 1408 1226 if (ret) 1409 1227 return ret; 1410 1228 1411 - rb8366rb_set_port_led(priv, port, true); 1412 1229 return 0; 1413 1230 } 1414 1231 ··· 1422 1241 BIT(port)); 1423 1242 if (ret) 1424 1243 return; 1425 - 1426 - rb8366rb_set_port_led(priv, port, false); 1427 1244 } 1428 1245 1429 1246 static int
+2 -5
drivers/net/dsa/realtek/rtl83xx.c
··· 290 290 * rtl83xx_remove() - Cleanup a realtek switch driver 291 291 * @priv: realtek_priv pointer 292 292 * 293 - * If a method is provided, this function asserts the hard reset of the switch 294 - * in order to avoid leaking traffic when the driver is gone. 293 + * Placehold for common cleanup procedures. 295 294 * 296 - * Context: Might sleep if priv->gdev->chip->can_sleep. 295 + * Context: Any 297 296 * Return: nothing 298 297 */ 299 298 void rtl83xx_remove(struct realtek_priv *priv) 300 299 { 301 - /* leave the device reset asserted */ 302 - rtl83xx_reset_assert(priv); 303 300 } 304 301 EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA); 305 302