xref: /openbmc/linux/drivers/net/dsa/qca/qca8k-leds.c (revision d5a05299)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/regmap.h>
3 #include <net/dsa.h>
4 
5 #include "qca8k.h"
6 #include "qca8k_leds.h"
7 
8 static u32 qca8k_phy_to_port(int phy)
9 {
10 	/* Internal PHY 0 has port at index 1.
11 	 * Internal PHY 1 has port at index 2.
12 	 * Internal PHY 2 has port at index 3.
13 	 * Internal PHY 3 has port at index 4.
14 	 * Internal PHY 4 has port at index 5.
15 	 */
16 
17 	return phy + 1;
18 }
19 
20 static int
21 qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info)
22 {
23 	switch (port_num) {
24 	case 0:
25 		reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
26 		reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT;
27 		break;
28 	case 1:
29 	case 2:
30 	case 3:
31 		/* Port 123 are controlled on a different reg */
32 		reg_info->reg = QCA8K_LED_CTRL3_REG;
33 		reg_info->shift = QCA8K_LED_PHY123_PATTERN_EN_SHIFT(port_num, led_num);
34 		break;
35 	case 4:
36 		reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
37 		reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT;
38 		break;
39 	default:
40 		return -EINVAL;
41 	}
42 
43 	return 0;
44 }
45 
46 static int
47 qca8k_get_control_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info)
48 {
49 	reg_info->reg = QCA8K_LED_CTRL_REG(led_num);
50 
51 	/* 6 total control rule:
52 	 * 3 control rules for phy0-3 that applies to all their leds
53 	 * 3 control rules for phy4
54 	 */
55 	if (port_num == 4)
56 		reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT;
57 	else
58 		reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT;
59 
60 	return 0;
61 }
62 
63 static int
64 qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger)
65 {
66 	/* Parsing specific to netdev trigger */
67 	if (test_bit(TRIGGER_NETDEV_TX, &rules))
68 		*offload_trigger |= QCA8K_LED_TX_BLINK_MASK;
69 	if (test_bit(TRIGGER_NETDEV_RX, &rules))
70 		*offload_trigger |= QCA8K_LED_RX_BLINK_MASK;
71 
72 	if (rules && !*offload_trigger)
73 		return -EOPNOTSUPP;
74 
75 	/* Enable some default rule by default to the requested mode:
76 	 * - Blink at 4Hz by default
77 	 */
78 	*offload_trigger |= QCA8K_LED_BLINK_4HZ;
79 
80 	return 0;
81 }
82 
83 static int
84 qca8k_led_brightness_set(struct qca8k_led *led,
85 			 enum led_brightness brightness)
86 {
87 	struct qca8k_led_pattern_en reg_info;
88 	struct qca8k_priv *priv = led->priv;
89 	u32 mask, val;
90 
91 	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
92 
93 	val = QCA8K_LED_ALWAYS_OFF;
94 	if (brightness)
95 		val = QCA8K_LED_ALWAYS_ON;
96 
97 	/* HW regs to control brightness is special and port 1-2-3
98 	 * are placed in a different reg.
99 	 *
100 	 * To control port 0 brightness:
101 	 * - the 2 bit (15, 14) of:
102 	 *   - QCA8K_LED_CTRL0_REG for led1
103 	 *   - QCA8K_LED_CTRL1_REG for led2
104 	 *   - QCA8K_LED_CTRL2_REG for led3
105 	 *
106 	 * To control port 4:
107 	 * - the 2 bit (31, 30) of:
108 	 *   - QCA8K_LED_CTRL0_REG for led1
109 	 *   - QCA8K_LED_CTRL1_REG for led2
110 	 *   - QCA8K_LED_CTRL2_REG for led3
111 	 *
112 	 * To control port 1:
113 	 *   - the 2 bit at (9, 8) of QCA8K_LED_CTRL3_REG are used for led1
114 	 *   - the 2 bit at (11, 10) of QCA8K_LED_CTRL3_REG are used for led2
115 	 *   - the 2 bit at (13, 12) of QCA8K_LED_CTRL3_REG are used for led3
116 	 *
117 	 * To control port 2:
118 	 *   - the 2 bit at (15, 14) of QCA8K_LED_CTRL3_REG are used for led1
119 	 *   - the 2 bit at (17, 16) of QCA8K_LED_CTRL3_REG are used for led2
120 	 *   - the 2 bit at (19, 18) of QCA8K_LED_CTRL3_REG are used for led3
121 	 *
122 	 * To control port 3:
123 	 *   - the 2 bit at (21, 20) of QCA8K_LED_CTRL3_REG are used for led1
124 	 *   - the 2 bit at (23, 22) of QCA8K_LED_CTRL3_REG are used for led2
125 	 *   - the 2 bit at (25, 24) of QCA8K_LED_CTRL3_REG are used for led3
126 	 *
127 	 * To abstract this and have less code, we use the port and led numm
128 	 * to calculate the shift and the correct reg due to this problem of
129 	 * not having a 1:1 map of LED with the regs.
130 	 */
131 	if (led->port_num == 0 || led->port_num == 4) {
132 		mask = QCA8K_LED_PATTERN_EN_MASK;
133 		val <<= QCA8K_LED_PATTERN_EN_SHIFT;
134 	} else {
135 		mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
136 	}
137 
138 	return regmap_update_bits(priv->regmap, reg_info.reg,
139 				  mask << reg_info.shift,
140 				  val << reg_info.shift);
141 }
142 
143 static int
144 qca8k_cled_brightness_set_blocking(struct led_classdev *ldev,
145 				   enum led_brightness brightness)
146 {
147 	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
148 
149 	return qca8k_led_brightness_set(led, brightness);
150 }
151 
152 static enum led_brightness
153 qca8k_led_brightness_get(struct qca8k_led *led)
154 {
155 	struct qca8k_led_pattern_en reg_info;
156 	struct qca8k_priv *priv = led->priv;
157 	u32 val;
158 	int ret;
159 
160 	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
161 
162 	ret = regmap_read(priv->regmap, reg_info.reg, &val);
163 	if (ret)
164 		return 0;
165 
166 	val >>= reg_info.shift;
167 
168 	if (led->port_num == 0 || led->port_num == 4) {
169 		val &= QCA8K_LED_PATTERN_EN_MASK;
170 		val >>= QCA8K_LED_PATTERN_EN_SHIFT;
171 	} else {
172 		val &= QCA8K_LED_PHY123_PATTERN_EN_MASK;
173 	}
174 
175 	/* Assume brightness ON only when the LED is set to always ON */
176 	return val == QCA8K_LED_ALWAYS_ON;
177 }
178 
179 static int
180 qca8k_cled_blink_set(struct led_classdev *ldev,
181 		     unsigned long *delay_on,
182 		     unsigned long *delay_off)
183 {
184 	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
185 	u32 mask, val = QCA8K_LED_ALWAYS_BLINK_4HZ;
186 	struct qca8k_led_pattern_en reg_info;
187 	struct qca8k_priv *priv = led->priv;
188 
189 	if (*delay_on == 0 && *delay_off == 0) {
190 		*delay_on = 125;
191 		*delay_off = 125;
192 	}
193 
194 	if (*delay_on != 125 || *delay_off != 125) {
195 		/* The hardware only supports blinking at 4Hz. Fall back
196 		 * to software implementation in other cases.
197 		 */
198 		return -EINVAL;
199 	}
200 
201 	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
202 
203 	if (led->port_num == 0 || led->port_num == 4) {
204 		mask = QCA8K_LED_PATTERN_EN_MASK;
205 		val <<= QCA8K_LED_PATTERN_EN_SHIFT;
206 	} else {
207 		mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
208 	}
209 
210 	regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift,
211 			   val << reg_info.shift);
212 
213 	return 0;
214 }
215 
216 static int
217 qca8k_cled_trigger_offload(struct led_classdev *ldev, bool enable)
218 {
219 	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
220 
221 	struct qca8k_led_pattern_en reg_info;
222 	struct qca8k_priv *priv = led->priv;
223 	u32 mask, val = QCA8K_LED_ALWAYS_OFF;
224 
225 	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
226 
227 	if (enable)
228 		val = QCA8K_LED_RULE_CONTROLLED;
229 
230 	if (led->port_num == 0 || led->port_num == 4) {
231 		mask = QCA8K_LED_PATTERN_EN_MASK;
232 		val <<= QCA8K_LED_PATTERN_EN_SHIFT;
233 	} else {
234 		mask = QCA8K_LED_PHY123_PATTERN_EN_MASK;
235 	}
236 
237 	return regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift,
238 				  val << reg_info.shift);
239 }
240 
241 static bool
242 qca8k_cled_hw_control_status(struct led_classdev *ldev)
243 {
244 	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
245 
246 	struct qca8k_led_pattern_en reg_info;
247 	struct qca8k_priv *priv = led->priv;
248 	u32 val;
249 
250 	qca8k_get_enable_led_reg(led->port_num, led->led_num, &reg_info);
251 
252 	regmap_read(priv->regmap, reg_info.reg, &val);
253 
254 	val >>= reg_info.shift;
255 
256 	if (led->port_num == 0 || led->port_num == 4) {
257 		val &= QCA8K_LED_PATTERN_EN_MASK;
258 		val >>= QCA8K_LED_PATTERN_EN_SHIFT;
259 	} else {
260 		val &= QCA8K_LED_PHY123_PATTERN_EN_MASK;
261 	}
262 
263 	return val == QCA8K_LED_RULE_CONTROLLED;
264 }
265 
266 static int
267 qca8k_cled_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules)
268 {
269 	u32 offload_trigger = 0;
270 
271 	return qca8k_parse_netdev(rules, &offload_trigger);
272 }
273 
274 static int
275 qca8k_cled_hw_control_set(struct led_classdev *ldev, unsigned long rules)
276 {
277 	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
278 	struct qca8k_led_pattern_en reg_info;
279 	struct qca8k_priv *priv = led->priv;
280 	u32 offload_trigger = 0;
281 	int ret;
282 
283 	ret = qca8k_parse_netdev(rules, &offload_trigger);
284 	if (ret)
285 		return ret;
286 
287 	ret = qca8k_cled_trigger_offload(ldev, true);
288 	if (ret)
289 		return ret;
290 
291 	qca8k_get_control_led_reg(led->port_num, led->led_num, &reg_info);
292 
293 	return regmap_update_bits(priv->regmap, reg_info.reg,
294 				  QCA8K_LED_RULE_MASK << reg_info.shift,
295 				  offload_trigger << reg_info.shift);
296 }
297 
298 static int
299 qca8k_cled_hw_control_get(struct led_classdev *ldev, unsigned long *rules)
300 {
301 	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
302 	struct qca8k_led_pattern_en reg_info;
303 	struct qca8k_priv *priv = led->priv;
304 	u32 val;
305 	int ret;
306 
307 	/* With hw control not active return err */
308 	if (!qca8k_cled_hw_control_status(ldev))
309 		return -EINVAL;
310 
311 	qca8k_get_control_led_reg(led->port_num, led->led_num, &reg_info);
312 
313 	ret = regmap_read(priv->regmap, reg_info.reg, &val);
314 	if (ret)
315 		return ret;
316 
317 	val >>= reg_info.shift;
318 	val &= QCA8K_LED_RULE_MASK;
319 
320 	/* Parsing specific to netdev trigger */
321 	if (val & QCA8K_LED_TX_BLINK_MASK)
322 		set_bit(TRIGGER_NETDEV_TX, rules);
323 	if (val & QCA8K_LED_RX_BLINK_MASK)
324 		set_bit(TRIGGER_NETDEV_RX, rules);
325 
326 	return 0;
327 }
328 
329 static struct device *qca8k_cled_hw_control_get_device(struct led_classdev *ldev)
330 {
331 	struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev);
332 	struct qca8k_priv *priv = led->priv;
333 	struct dsa_port *dp;
334 
335 	dp = dsa_to_port(priv->ds, qca8k_phy_to_port(led->port_num));
336 	if (!dp)
337 		return NULL;
338 	if (dp->slave)
339 		return &dp->slave->dev;
340 	return NULL;
341 }
342 
343 static int
344 qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num)
345 {
346 	struct fwnode_handle *led = NULL, *leds = NULL;
347 	struct led_init_data init_data = { };
348 	struct dsa_switch *ds = priv->ds;
349 	enum led_default_state state;
350 	struct qca8k_led *port_led;
351 	int led_num, led_index;
352 	int ret;
353 
354 	leds = fwnode_get_named_child_node(port, "leds");
355 	if (!leds) {
356 		dev_dbg(priv->dev, "No Leds node specified in device tree for port %d!\n",
357 			port_num);
358 		return 0;
359 	}
360 
361 	fwnode_for_each_child_node(leds, led) {
362 		/* Reg represent the led number of the port.
363 		 * Each port can have at most 3 leds attached
364 		 * Commonly:
365 		 * 1. is gigabit led
366 		 * 2. is mbit led
367 		 * 3. additional status led
368 		 */
369 		if (fwnode_property_read_u32(led, "reg", &led_num))
370 			continue;
371 
372 		if (led_num >= QCA8K_LED_PORT_COUNT) {
373 			dev_warn(priv->dev, "Invalid LED reg %d defined for port %d",
374 				 led_num, port_num);
375 			continue;
376 		}
377 
378 		led_index = QCA8K_LED_PORT_INDEX(port_num, led_num);
379 
380 		port_led = &priv->ports_led[led_index];
381 		port_led->port_num = port_num;
382 		port_led->led_num = led_num;
383 		port_led->priv = priv;
384 
385 		state = led_init_default_state_get(led);
386 		switch (state) {
387 		case LEDS_DEFSTATE_ON:
388 			port_led->cdev.brightness = 1;
389 			qca8k_led_brightness_set(port_led, 1);
390 			break;
391 		case LEDS_DEFSTATE_KEEP:
392 			port_led->cdev.brightness =
393 					qca8k_led_brightness_get(port_led);
394 			break;
395 		default:
396 			port_led->cdev.brightness = 0;
397 			qca8k_led_brightness_set(port_led, 0);
398 		}
399 
400 		port_led->cdev.max_brightness = 1;
401 		port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking;
402 		port_led->cdev.blink_set = qca8k_cled_blink_set;
403 		port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported;
404 		port_led->cdev.hw_control_set = qca8k_cled_hw_control_set;
405 		port_led->cdev.hw_control_get = qca8k_cled_hw_control_get;
406 		port_led->cdev.hw_control_get_device = qca8k_cled_hw_control_get_device;
407 		port_led->cdev.hw_control_trigger = "netdev";
408 		init_data.default_label = ":port";
409 		init_data.fwnode = led;
410 		init_data.devname_mandatory = true;
411 		init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d", ds->slave_mii_bus->id,
412 						 port_num);
413 		if (!init_data.devicename)
414 			return -ENOMEM;
415 
416 		ret = devm_led_classdev_register_ext(priv->dev, &port_led->cdev, &init_data);
417 		if (ret)
418 			dev_warn(priv->dev, "Failed to init LED %d for port %d", led_num, port_num);
419 
420 		kfree(init_data.devicename);
421 	}
422 
423 	return 0;
424 }
425 
426 int
427 qca8k_setup_led_ctrl(struct qca8k_priv *priv)
428 {
429 	struct fwnode_handle *ports, *port;
430 	int port_num;
431 	int ret;
432 
433 	ports = device_get_named_child_node(priv->dev, "ports");
434 	if (!ports) {
435 		dev_info(priv->dev, "No ports node specified in device tree!");
436 		return 0;
437 	}
438 
439 	fwnode_for_each_child_node(ports, port) {
440 		if (fwnode_property_read_u32(port, "reg", &port_num))
441 			continue;
442 
443 		/* Skip checking for CPU port 0 and CPU port 6 as not supported */
444 		if (port_num == 0 || port_num == 6)
445 			continue;
446 
447 		/* Each port can have at most 3 different leds attached.
448 		 * Switch port starts from 0 to 6, but port 0 and 6 are CPU
449 		 * port. The port index needs to be decreased by one to identify
450 		 * the correct port for LED setup.
451 		 */
452 		ret = qca8k_parse_port_leds(priv, port, qca8k_port_to_phy(port_num));
453 		if (ret)
454 			return ret;
455 	}
456 
457 	return 0;
458 }
459