xref: /linux/drivers/net/ethernet/realtek/r8169_leds.c (revision 0bef512012b1cd8820f0c9ec80e5f8ceb43fdd59)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* r8169_leds.c: Realtek 8169/8168/8101/8125 ethernet driver.
3  *
4  * Copyright (c) 2023 Heiner Kallweit <hkallweit1@gmail.com>
5  *
6  * See MAINTAINERS file for support contact information.
7  */
8 
9 #include <linux/leds.h>
10 #include <linux/netdevice.h>
11 #include <uapi/linux/uleds.h>
12 
13 #include "r8169.h"
14 
15 #define RTL8168_LED_CTRL_OPTION2	BIT(15)
16 #define RTL8168_LED_CTRL_ACT		BIT(3)
17 #define RTL8168_LED_CTRL_LINK_1000	BIT(2)
18 #define RTL8168_LED_CTRL_LINK_100	BIT(1)
19 #define RTL8168_LED_CTRL_LINK_10	BIT(0)
20 
21 #define RTL8168_NUM_LEDS		3
22 
23 struct r8169_led_classdev {
24 	struct led_classdev led;
25 	struct net_device *ndev;
26 	int index;
27 };
28 
29 #define lcdev_to_r8169_ldev(lcdev) container_of(lcdev, struct r8169_led_classdev, led)
30 
31 static bool r8169_trigger_mode_is_valid(unsigned long flags)
32 {
33 	bool rx, tx;
34 
35 	if (flags & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
36 		return false;
37 	if (flags & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
38 		return false;
39 
40 	rx = flags & BIT(TRIGGER_NETDEV_RX);
41 	tx = flags & BIT(TRIGGER_NETDEV_TX);
42 
43 	return rx == tx;
44 }
45 
46 static int rtl8168_led_hw_control_is_supported(struct led_classdev *led_cdev,
47 					       unsigned long flags)
48 {
49 	struct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);
50 	struct rtl8169_private *tp = netdev_priv(ldev->ndev);
51 	int shift = ldev->index * 4;
52 
53 	if (!r8169_trigger_mode_is_valid(flags)) {
54 		/* Switch LED off to indicate that mode isn't supported */
55 		rtl8168_led_mod_ctrl(tp, 0x000f << shift, 0);
56 		return -EOPNOTSUPP;
57 	}
58 
59 	return 0;
60 }
61 
62 static int rtl8168_led_hw_control_set(struct led_classdev *led_cdev,
63 				      unsigned long flags)
64 {
65 	struct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);
66 	struct rtl8169_private *tp = netdev_priv(ldev->ndev);
67 	int shift = ldev->index * 4;
68 	u16 mode = 0;
69 
70 	if (flags & BIT(TRIGGER_NETDEV_LINK_10))
71 		mode |= RTL8168_LED_CTRL_LINK_10;
72 	if (flags & BIT(TRIGGER_NETDEV_LINK_100))
73 		mode |= RTL8168_LED_CTRL_LINK_100;
74 	if (flags & BIT(TRIGGER_NETDEV_LINK_1000))
75 		mode |= RTL8168_LED_CTRL_LINK_1000;
76 	if (flags & BIT(TRIGGER_NETDEV_TX))
77 		mode |= RTL8168_LED_CTRL_ACT;
78 
79 	return rtl8168_led_mod_ctrl(tp, 0x000f << shift, mode << shift);
80 }
81 
82 static int rtl8168_led_hw_control_get(struct led_classdev *led_cdev,
83 				      unsigned long *flags)
84 {
85 	struct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);
86 	struct rtl8169_private *tp = netdev_priv(ldev->ndev);
87 	int shift = ldev->index * 4;
88 	int mode;
89 
90 	mode = rtl8168_get_led_mode(tp);
91 	if (mode < 0)
92 		return mode;
93 
94 	if (mode & RTL8168_LED_CTRL_OPTION2) {
95 		rtl8168_led_mod_ctrl(tp, RTL8168_LED_CTRL_OPTION2, 0);
96 		netdev_notice(ldev->ndev, "Deactivating unsupported Option2 LED mode\n");
97 	}
98 
99 	mode = (mode >> shift) & 0x000f;
100 
101 	if (mode & RTL8168_LED_CTRL_ACT)
102 		*flags |= BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX);
103 
104 	if (mode & RTL8168_LED_CTRL_LINK_10)
105 		*flags |= BIT(TRIGGER_NETDEV_LINK_10);
106 	if (mode & RTL8168_LED_CTRL_LINK_100)
107 		*flags |= BIT(TRIGGER_NETDEV_LINK_100);
108 	if (mode & RTL8168_LED_CTRL_LINK_1000)
109 		*flags |= BIT(TRIGGER_NETDEV_LINK_1000);
110 
111 	return 0;
112 }
113 
114 static struct device *
115 	r8169_led_hw_control_get_device(struct led_classdev *led_cdev)
116 {
117 	struct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);
118 
119 	return &ldev->ndev->dev;
120 }
121 
122 static void rtl8168_setup_ldev(struct r8169_led_classdev *ldev,
123 			       struct net_device *ndev, int index)
124 {
125 	struct rtl8169_private *tp = netdev_priv(ndev);
126 	struct led_classdev *led_cdev = &ldev->led;
127 	char led_name[LED_MAX_NAME_SIZE];
128 
129 	ldev->ndev = ndev;
130 	ldev->index = index;
131 
132 	r8169_get_led_name(tp, index, led_name, LED_MAX_NAME_SIZE);
133 	led_cdev->name = led_name;
134 	led_cdev->hw_control_trigger = "netdev";
135 	led_cdev->flags |= LED_RETAIN_AT_SHUTDOWN;
136 	led_cdev->hw_control_is_supported = rtl8168_led_hw_control_is_supported;
137 	led_cdev->hw_control_set = rtl8168_led_hw_control_set;
138 	led_cdev->hw_control_get = rtl8168_led_hw_control_get;
139 	led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
140 
141 	/* ignore errors */
142 	devm_led_classdev_register(&ndev->dev, led_cdev);
143 }
144 
145 void rtl8168_init_leds(struct net_device *ndev)
146 {
147 	/* bind resource mgmt to netdev */
148 	struct device *dev = &ndev->dev;
149 	struct r8169_led_classdev *leds;
150 	int i;
151 
152 	leds = devm_kcalloc(dev, RTL8168_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
153 	if (!leds)
154 		return;
155 
156 	for (i = 0; i < RTL8168_NUM_LEDS; i++)
157 		rtl8168_setup_ldev(leds + i, ndev, i);
158 }
159