xref: /linux/drivers/net/dsa/mv88e6xxx/leds.c (revision 9208c05f9fdfd927ea160b97dfef3c379049fff2)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 #include <linux/bitfield.h>
3 #include <linux/leds.h>
4 #include <linux/property.h>
5 
6 #include "chip.h"
7 #include "global2.h"
8 #include "port.h"
9 
10 /* Offset 0x16: LED control */
11 
12 static int mv88e6xxx_port_led_write(struct mv88e6xxx_chip *chip, int port, u16 reg)
13 {
14 	reg |= MV88E6XXX_PORT_LED_CONTROL_UPDATE;
15 
16 	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_LED_CONTROL, reg);
17 }
18 
19 static int mv88e6xxx_port_led_read(struct mv88e6xxx_chip *chip, int port,
20 				   u16 ptr, u16 *val)
21 {
22 	int err;
23 
24 	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_LED_CONTROL, ptr);
25 	if (err)
26 		return err;
27 
28 	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_LED_CONTROL, val);
29 	*val &= 0x3ff;
30 
31 	return err;
32 }
33 
34 static int mv88e6xxx_led_brightness_set(struct mv88e6xxx_port *p, int led,
35 					int brightness)
36 {
37 	u16 reg;
38 	int err;
39 
40 	err = mv88e6xxx_port_led_read(p->chip, p->port,
41 				      MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL,
42 				      &reg);
43 	if (err)
44 		return err;
45 
46 	if (led == 1)
47 		reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK;
48 	else
49 		reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK;
50 
51 	if (brightness) {
52 		/* Selector 0x0f == Force LED ON */
53 		if (led == 1)
54 			reg |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELF;
55 		else
56 			reg |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELF;
57 	} else {
58 		/* Selector 0x0e == Force LED OFF */
59 		if (led == 1)
60 			reg |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELE;
61 		else
62 			reg |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELE;
63 	}
64 
65 	reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL;
66 
67 	return mv88e6xxx_port_led_write(p->chip, p->port, reg);
68 }
69 
70 static int mv88e6xxx_led0_brightness_set_blocking(struct led_classdev *ldev,
71 						  enum led_brightness brightness)
72 {
73 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
74 	int err;
75 
76 	mv88e6xxx_reg_lock(p->chip);
77 	err = mv88e6xxx_led_brightness_set(p, 0, brightness);
78 	mv88e6xxx_reg_unlock(p->chip);
79 
80 	return err;
81 }
82 
83 static int mv88e6xxx_led1_brightness_set_blocking(struct led_classdev *ldev,
84 						  enum led_brightness brightness)
85 {
86 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
87 	int err;
88 
89 	mv88e6xxx_reg_lock(p->chip);
90 	err = mv88e6xxx_led_brightness_set(p, 1, brightness);
91 	mv88e6xxx_reg_unlock(p->chip);
92 
93 	return err;
94 }
95 
96 struct mv88e6xxx_led_hwconfig {
97 	int led;
98 	u8 portmask;
99 	unsigned long rules;
100 	bool fiber;
101 	bool blink_activity;
102 	u16 selector;
103 };
104 
105 /* The following is a lookup table to check what rules we can support on a
106  * certain LED given restrictions such as that some rules only work with fiber
107  * (SFP) connections and some blink on activity by default.
108  */
109 #define MV88E6XXX_PORTS_0_3 (BIT(0) | BIT(1) | BIT(2) | BIT(3))
110 #define MV88E6XXX_PORTS_4_5 (BIT(4) | BIT(5))
111 #define MV88E6XXX_PORT_4 BIT(4)
112 #define MV88E6XXX_PORT_5 BIT(5)
113 
114 /* Entries are listed in selector order.
115  *
116  * These configurations vary across different switch families, list
117  * different tables per-family here.
118  */
119 static const struct mv88e6xxx_led_hwconfig mv88e6352_led_hwconfigs[] = {
120 	{
121 		.led = 0,
122 		.portmask = MV88E6XXX_PORT_4,
123 		.rules = BIT(TRIGGER_NETDEV_LINK),
124 		.blink_activity = true,
125 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL0,
126 	},
127 	{
128 		.led = 1,
129 		.portmask = MV88E6XXX_PORT_5,
130 		.rules = BIT(TRIGGER_NETDEV_LINK_1000),
131 		.blink_activity = true,
132 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL0,
133 	},
134 	{
135 		.led = 0,
136 		.portmask = MV88E6XXX_PORTS_0_3,
137 		.rules = BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_1000),
138 		.blink_activity = true,
139 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL1,
140 	},
141 	{
142 		.led = 1,
143 		.portmask = MV88E6XXX_PORTS_0_3,
144 		.rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_100),
145 		.blink_activity = true,
146 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL1,
147 	},
148 	{
149 		.led = 0,
150 		.portmask = MV88E6XXX_PORTS_4_5,
151 		.rules = BIT(TRIGGER_NETDEV_LINK_100),
152 		.blink_activity = true,
153 		.fiber = true,
154 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL1,
155 	},
156 	{
157 		.led = 1,
158 		.portmask = MV88E6XXX_PORTS_4_5,
159 		.rules = BIT(TRIGGER_NETDEV_LINK_1000),
160 		.blink_activity = true,
161 		.fiber = true,
162 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL1,
163 	},
164 	{
165 		.led = 0,
166 		.portmask = MV88E6XXX_PORTS_0_3,
167 		.rules = BIT(TRIGGER_NETDEV_LINK_1000),
168 		.blink_activity = true,
169 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL2,
170 	},
171 	{
172 		.led = 1,
173 		.portmask = MV88E6XXX_PORTS_0_3,
174 		.rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_100),
175 		.blink_activity = true,
176 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL2,
177 	},
178 	{
179 		.led = 0,
180 		.portmask = MV88E6XXX_PORTS_4_5,
181 		.rules = BIT(TRIGGER_NETDEV_LINK_1000),
182 		.blink_activity = true,
183 		.fiber = true,
184 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL2,
185 	},
186 	{
187 		.led = 1,
188 		.portmask = MV88E6XXX_PORTS_4_5,
189 		.rules = BIT(TRIGGER_NETDEV_LINK_100),
190 		.blink_activity = true,
191 		.fiber = true,
192 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL2,
193 	},
194 	{
195 		.led = 0,
196 		.portmask = MV88E6XXX_PORTS_0_3,
197 		.rules = BIT(TRIGGER_NETDEV_LINK),
198 		.blink_activity = true,
199 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL3,
200 	},
201 	{
202 		.led = 1,
203 		.portmask = MV88E6XXX_PORTS_0_3,
204 		.rules = BIT(TRIGGER_NETDEV_LINK_1000),
205 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL3,
206 	},
207 	{
208 		.led = 1,
209 		.portmask = MV88E6XXX_PORTS_4_5,
210 		.rules = BIT(TRIGGER_NETDEV_LINK),
211 		.fiber = true,
212 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL3,
213 	},
214 	{
215 		.led = 1,
216 		.portmask = MV88E6XXX_PORT_4,
217 		.rules = BIT(TRIGGER_NETDEV_LINK),
218 		.blink_activity = true,
219 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL4,
220 	},
221 	{
222 		.led = 1,
223 		.portmask = MV88E6XXX_PORT_5,
224 		.rules = BIT(TRIGGER_NETDEV_LINK),
225 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL5,
226 	},
227 	{
228 		.led = 0,
229 		.portmask = MV88E6XXX_PORTS_0_3,
230 		.rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX),
231 		.blink_activity = true,
232 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL6,
233 	},
234 	{
235 		.led = 1,
236 		.portmask = MV88E6XXX_PORTS_0_3,
237 		.rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_1000),
238 		.blink_activity = true,
239 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL6,
240 	},
241 	{
242 		.led = 0,
243 		.portmask = MV88E6XXX_PORT_4,
244 		.rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX),
245 		.blink_activity = true,
246 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL6,
247 	},
248 	{
249 		.led = 1,
250 		.portmask = MV88E6XXX_PORT_5,
251 		.rules = BIT(TRIGGER_NETDEV_FULL_DUPLEX),
252 		.blink_activity = true,
253 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL6,
254 	},
255 	{
256 		.led = 0,
257 		.portmask = MV88E6XXX_PORTS_0_3,
258 		.rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_1000),
259 		.blink_activity = true,
260 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL7,
261 	},
262 	{
263 		.led = 1,
264 		.portmask = MV88E6XXX_PORTS_0_3,
265 		.rules = BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK_1000),
266 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL7,
267 	},
268 	{
269 		.led = 0,
270 		.portmask = MV88E6XXX_PORTS_0_3,
271 		.rules = BIT(TRIGGER_NETDEV_LINK),
272 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL8,
273 	},
274 	{
275 		.led = 1,
276 		.portmask = MV88E6XXX_PORTS_0_3,
277 		.rules = BIT(TRIGGER_NETDEV_LINK),
278 		.blink_activity = true,
279 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL8,
280 	},
281 	{
282 		.led = 0,
283 		.portmask = MV88E6XXX_PORT_5,
284 		.rules = BIT(TRIGGER_NETDEV_LINK),
285 		.blink_activity = true,
286 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL8,
287 	},
288 	{
289 		.led = 0,
290 		.portmask = MV88E6XXX_PORTS_0_3,
291 		.rules = BIT(TRIGGER_NETDEV_LINK_10),
292 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SEL9,
293 	},
294 	{
295 		.led = 1,
296 		.portmask = MV88E6XXX_PORTS_0_3,
297 		.rules = BIT(TRIGGER_NETDEV_LINK_100),
298 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SEL9,
299 	},
300 	{
301 		.led = 0,
302 		.portmask = MV88E6XXX_PORTS_0_3,
303 		.rules = BIT(TRIGGER_NETDEV_LINK_10),
304 		.blink_activity = true,
305 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SELA,
306 	},
307 	{
308 		.led = 1,
309 		.portmask = MV88E6XXX_PORTS_0_3,
310 		.rules = BIT(TRIGGER_NETDEV_LINK_100),
311 		.blink_activity = true,
312 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SELA,
313 	},
314 	{
315 		.led = 0,
316 		.portmask = MV88E6XXX_PORTS_0_3,
317 		.rules = BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_1000),
318 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED0_SELB,
319 	},
320 	{
321 		.led = 1,
322 		.portmask = MV88E6XXX_PORTS_0_3,
323 		.rules = BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_1000),
324 		.blink_activity = true,
325 		.selector = MV88E6XXX_PORT_LED_CONTROL_LED1_SELB,
326 	},
327 };
328 
329 /* mv88e6xxx_led_match_selector() - look up the appropriate LED mode selector
330  * @p: port state container
331  * @led: LED number, 0 or 1
332  * @blink_activity: blink the LED (usually blink on indicated activity)
333  * @fiber: the link is connected to fiber such as SFP
334  * @rules: LED status flags from the LED classdev core
335  * @selector: fill in the selector in this parameter with an OR operation
336  */
337 static int mv88e6xxx_led_match_selector(struct mv88e6xxx_port *p, int led, bool blink_activity,
338 					bool fiber, unsigned long rules, u16 *selector)
339 {
340 	const struct mv88e6xxx_led_hwconfig *conf;
341 	int i;
342 
343 	/* No rules means we turn the LED off */
344 	if (!rules) {
345 		if (led == 1)
346 			*selector |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELE;
347 		else
348 			*selector |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELE;
349 		return 0;
350 	}
351 
352 	/* TODO: these rules are for MV88E6352, when adding other families,
353 	 * think about making sure you select the table that match the
354 	 * specific switch family.
355 	 */
356 	for (i = 0; i < ARRAY_SIZE(mv88e6352_led_hwconfigs); i++) {
357 		conf = &mv88e6352_led_hwconfigs[i];
358 
359 		if (conf->led != led)
360 			continue;
361 
362 		if (!(conf->portmask & BIT(p->port)))
363 			continue;
364 
365 		if (conf->blink_activity != blink_activity)
366 			continue;
367 
368 		if (conf->fiber != fiber)
369 			continue;
370 
371 		if (conf->rules == rules) {
372 			dev_dbg(p->chip->dev, "port%d LED %d set selector %04x for rules %08lx\n",
373 				p->port, led, conf->selector, rules);
374 			*selector |= conf->selector;
375 			return 0;
376 		}
377 	}
378 
379 	return -EOPNOTSUPP;
380 }
381 
382 /* mv88e6xxx_led_match_selector() - find Linux netdev rules from a selector value
383  * @p: port state container
384  * @selector: the selector value from the LED actity register
385  * @led: LED number, 0 or 1
386  * @rules: Linux netdev activity rules found from selector
387  */
388 static int
389 mv88e6xxx_led_match_rule(struct mv88e6xxx_port *p, u16 selector, int led, unsigned long *rules)
390 {
391 	const struct mv88e6xxx_led_hwconfig *conf;
392 	int i;
393 
394 	/* Find the selector in the table, we just look for the right selector
395 	 * and ignore if the activity has special properties such as blinking
396 	 * or is fiber-only.
397 	 */
398 	for (i = 0; i < ARRAY_SIZE(mv88e6352_led_hwconfigs); i++) {
399 		conf = &mv88e6352_led_hwconfigs[i];
400 
401 		if (conf->led != led)
402 			continue;
403 
404 		if (!(conf->portmask & BIT(p->port)))
405 			continue;
406 
407 		if (conf->selector == selector) {
408 			dev_dbg(p->chip->dev, "port%d LED %d has selector %04x, rules %08lx\n",
409 				p->port, led, selector, conf->rules);
410 			*rules = conf->rules;
411 			return 0;
412 		}
413 	}
414 
415 	return -EINVAL;
416 }
417 
418 /* mv88e6xxx_led_get_selector() - get the appropriate LED mode selector
419  * @p: port state container
420  * @led: LED number, 0 or 1
421  * @fiber: the link is connected to fiber such as SFP
422  * @rules: LED status flags from the LED classdev core
423  * @selector: fill in the selector in this parameter with an OR operation
424  */
425 static int mv88e6xxx_led_get_selector(struct mv88e6xxx_port *p, int led,
426 				      bool fiber, unsigned long rules, u16 *selector)
427 {
428 	int err;
429 
430 	/* What happens here is that we first try to locate a trigger with solid
431 	 * indicator (such as LED is on for a 1000 link) else we try a second
432 	 * sweep to find something suitable with a trigger that will blink on
433 	 * activity.
434 	 */
435 	err = mv88e6xxx_led_match_selector(p, led, false, fiber, rules, selector);
436 	if (err)
437 		return mv88e6xxx_led_match_selector(p, led, true, fiber, rules, selector);
438 
439 	return 0;
440 }
441 
442 /* Sets up the hardware blinking period */
443 static int mv88e6xxx_led_set_blinking_period(struct mv88e6xxx_port *p, int led,
444 					     unsigned long delay_on, unsigned long delay_off)
445 {
446 	unsigned long period;
447 	u16 reg;
448 
449 	period = delay_on + delay_off;
450 
451 	reg = 0;
452 
453 	switch (period) {
454 	case 21:
455 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_21MS;
456 		break;
457 	case 42:
458 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_42MS;
459 		break;
460 	case 84:
461 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_84MS;
462 		break;
463 	case 168:
464 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_168MS;
465 		break;
466 	case 336:
467 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_336MS;
468 		break;
469 	case 672:
470 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_672MS;
471 		break;
472 	default:
473 		/* Fall back to software blinking */
474 		return -EINVAL;
475 	}
476 
477 	/* This is essentially PWM duty cycle: how long time of the period
478 	 * will the LED be on. Zero isn't great in most cases.
479 	 */
480 	switch (delay_on) {
481 	case 0:
482 		/* This is usually pretty useless and will make the LED look OFF */
483 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_NONE;
484 		break;
485 	case 21:
486 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_21MS;
487 		break;
488 	case 42:
489 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_42MS;
490 		break;
491 	case 84:
492 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_84MS;
493 		break;
494 	case 168:
495 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_168MS;
496 		break;
497 	default:
498 		/* Just use something non-zero */
499 		reg |= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_21MS;
500 		break;
501 	}
502 
503 	/* Set up blink rate */
504 	reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_STRETCH_BLINK;
505 
506 	return mv88e6xxx_port_led_write(p->chip, p->port, reg);
507 }
508 
509 static int mv88e6xxx_led_blink_set(struct mv88e6xxx_port *p, int led,
510 				   unsigned long *delay_on, unsigned long *delay_off)
511 {
512 	u16 reg;
513 	int err;
514 
515 	/* Choose a sensible default 336 ms (~3 Hz) */
516 	if ((*delay_on == 0) && (*delay_off == 0)) {
517 		*delay_on = 168;
518 		*delay_off = 168;
519 	}
520 
521 	/* No off delay is just on */
522 	if (*delay_off == 0)
523 		return mv88e6xxx_led_brightness_set(p, led, 1);
524 
525 	err = mv88e6xxx_led_set_blinking_period(p, led, *delay_on, *delay_off);
526 	if (err)
527 		return err;
528 
529 	err = mv88e6xxx_port_led_read(p->chip, p->port,
530 				      MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL,
531 				      &reg);
532 	if (err)
533 		return err;
534 
535 	if (led == 1)
536 		reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK;
537 	else
538 		reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK;
539 
540 	/* This will select the forced blinking status */
541 	if (led == 1)
542 		reg |= MV88E6XXX_PORT_LED_CONTROL_LED1_SELD;
543 	else
544 		reg |= MV88E6XXX_PORT_LED_CONTROL_LED0_SELD;
545 
546 	reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL;
547 
548 	return mv88e6xxx_port_led_write(p->chip, p->port, reg);
549 }
550 
551 static int mv88e6xxx_led0_blink_set(struct led_classdev *ldev,
552 				    unsigned long *delay_on,
553 				    unsigned long *delay_off)
554 {
555 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
556 	int err;
557 
558 	mv88e6xxx_reg_lock(p->chip);
559 	err = mv88e6xxx_led_blink_set(p, 0, delay_on, delay_off);
560 	mv88e6xxx_reg_unlock(p->chip);
561 
562 	return err;
563 }
564 
565 static int mv88e6xxx_led1_blink_set(struct led_classdev *ldev,
566 				    unsigned long *delay_on,
567 				    unsigned long *delay_off)
568 {
569 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
570 	int err;
571 
572 	mv88e6xxx_reg_lock(p->chip);
573 	err = mv88e6xxx_led_blink_set(p, 1, delay_on, delay_off);
574 	mv88e6xxx_reg_unlock(p->chip);
575 
576 	return err;
577 }
578 
579 static int
580 mv88e6xxx_led0_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules)
581 {
582 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
583 	u16 selector = 0;
584 
585 	return mv88e6xxx_led_get_selector(p, 0, p->fiber, rules, &selector);
586 }
587 
588 static int
589 mv88e6xxx_led1_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules)
590 {
591 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
592 	u16 selector = 0;
593 
594 	return mv88e6xxx_led_get_selector(p, 1, p->fiber, rules, &selector);
595 }
596 
597 static int mv88e6xxx_led_hw_control_set(struct mv88e6xxx_port *p,
598 					int led, unsigned long rules)
599 {
600 	u16 reg;
601 	int err;
602 
603 	err = mv88e6xxx_port_led_read(p->chip, p->port,
604 				      MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL,
605 				      &reg);
606 	if (err)
607 		return err;
608 
609 	if (led == 1)
610 		reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK;
611 	else
612 		reg &= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK;
613 
614 	err = mv88e6xxx_led_get_selector(p, led, p->fiber, rules, &reg);
615 	if (err)
616 		return err;
617 
618 	reg |= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL;
619 
620 	if (led == 0)
621 		dev_dbg(p->chip->dev, "LED 0 hw control on port %d trigger selector 0x%02x\n",
622 			p->port,
623 			(unsigned int)(reg & MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK));
624 	else
625 		dev_dbg(p->chip->dev, "LED 1 hw control on port %d trigger selector 0x%02x\n",
626 			p->port,
627 			(unsigned int)(reg & MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK) >> 4);
628 
629 	return mv88e6xxx_port_led_write(p->chip, p->port, reg);
630 }
631 
632 static int
633 mv88e6xxx_led_hw_control_get(struct mv88e6xxx_port *p, int led, unsigned long *rules)
634 {
635 	u16 val;
636 	int err;
637 
638 	mv88e6xxx_reg_lock(p->chip);
639 	err = mv88e6xxx_port_led_read(p->chip, p->port,
640 				      MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL, &val);
641 	mv88e6xxx_reg_unlock(p->chip);
642 	if (err)
643 		return err;
644 
645 	/* Mask out the selector bits for this port */
646 	if (led == 1) {
647 		val &= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK;
648 		/* It's forced blinking/OFF/ON */
649 		if (val == MV88E6XXX_PORT_LED_CONTROL_LED1_SELD ||
650 		    val == MV88E6XXX_PORT_LED_CONTROL_LED1_SELE ||
651 		    val == MV88E6XXX_PORT_LED_CONTROL_LED1_SELF) {
652 			*rules = 0;
653 			return 0;
654 		}
655 	} else {
656 		val &= MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK;
657 		/* It's forced blinking/OFF/ON */
658 		if (val == MV88E6XXX_PORT_LED_CONTROL_LED0_SELD ||
659 		    val == MV88E6XXX_PORT_LED_CONTROL_LED0_SELE ||
660 		    val == MV88E6XXX_PORT_LED_CONTROL_LED0_SELF) {
661 			*rules = 0;
662 			return 0;
663 		}
664 	}
665 
666 	err = mv88e6xxx_led_match_rule(p, val, led, rules);
667 	if (!err)
668 		return 0;
669 
670 	dev_dbg(p->chip->dev, "couldn't find matching selector for %04x\n", val);
671 	*rules = 0;
672 	return 0;
673 }
674 
675 static int
676 mv88e6xxx_led0_hw_control_set(struct led_classdev *ldev, unsigned long rules)
677 {
678 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
679 	int err;
680 
681 	mv88e6xxx_reg_lock(p->chip);
682 	err = mv88e6xxx_led_hw_control_set(p, 0, rules);
683 	mv88e6xxx_reg_unlock(p->chip);
684 
685 	return err;
686 }
687 
688 static int
689 mv88e6xxx_led1_hw_control_set(struct led_classdev *ldev, unsigned long rules)
690 {
691 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
692 	int err;
693 
694 	mv88e6xxx_reg_lock(p->chip);
695 	err = mv88e6xxx_led_hw_control_set(p, 1, rules);
696 	mv88e6xxx_reg_unlock(p->chip);
697 
698 	return err;
699 }
700 
701 static int
702 mv88e6xxx_led0_hw_control_get(struct led_classdev *ldev, unsigned long *rules)
703 {
704 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
705 
706 	return mv88e6xxx_led_hw_control_get(p, 0, rules);
707 }
708 
709 static int
710 mv88e6xxx_led1_hw_control_get(struct led_classdev *ldev, unsigned long *rules)
711 {
712 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
713 
714 	return mv88e6xxx_led_hw_control_get(p, 1, rules);
715 }
716 
717 static struct device *mv88e6xxx_led_hw_control_get_device(struct mv88e6xxx_port *p)
718 {
719 	struct dsa_port *dp;
720 
721 	dp = dsa_to_port(p->chip->ds, p->port);
722 	if (!dp)
723 		return NULL;
724 	if (dp->user)
725 		return &dp->user->dev;
726 	return NULL;
727 }
728 
729 static struct device *
730 mv88e6xxx_led0_hw_control_get_device(struct led_classdev *ldev)
731 {
732 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led0);
733 
734 	return mv88e6xxx_led_hw_control_get_device(p);
735 }
736 
737 static struct device *
738 mv88e6xxx_led1_hw_control_get_device(struct led_classdev *ldev)
739 {
740 	struct mv88e6xxx_port *p = container_of(ldev, struct mv88e6xxx_port, led1);
741 
742 	return mv88e6xxx_led_hw_control_get_device(p);
743 }
744 
745 int mv88e6xxx_port_setup_leds(struct mv88e6xxx_chip *chip, int port)
746 {
747 	struct fwnode_handle *led = NULL, *leds = NULL;
748 	struct led_init_data init_data = { };
749 	enum led_default_state state;
750 	struct mv88e6xxx_port *p;
751 	struct led_classdev *l;
752 	struct device *dev;
753 	u32 led_num;
754 	int ret;
755 
756 	/* LEDs are on ports 1,2,3,4, 5 and 6 (index 0..5), no more */
757 	if (port > 5)
758 		return -EOPNOTSUPP;
759 
760 	p = &chip->ports[port];
761 	if (!p->fwnode)
762 		return 0;
763 
764 	dev = chip->dev;
765 
766 	leds = fwnode_get_named_child_node(p->fwnode, "leds");
767 	if (!leds) {
768 		dev_dbg(dev, "No Leds node specified in device tree for port %d!\n",
769 			port);
770 		return 0;
771 	}
772 
773 	fwnode_for_each_child_node(leds, led) {
774 		/* Reg represent the led number of the port, max 2
775 		 * LEDs can be connected to each port, in some designs
776 		 * only one LED is connected.
777 		 */
778 		if (fwnode_property_read_u32(led, "reg", &led_num))
779 			continue;
780 		if (led_num > 1) {
781 			dev_err(dev, "invalid LED specified port %d\n", port);
782 			return -EINVAL;
783 		}
784 
785 		if (led_num == 0)
786 			l = &p->led0;
787 		else
788 			l = &p->led1;
789 
790 		state = led_init_default_state_get(led);
791 		switch (state) {
792 		case LEDS_DEFSTATE_ON:
793 			l->brightness = 1;
794 			mv88e6xxx_led_brightness_set(p, led_num, 1);
795 			break;
796 		case LEDS_DEFSTATE_KEEP:
797 			break;
798 		default:
799 			l->brightness = 0;
800 			mv88e6xxx_led_brightness_set(p, led_num, 0);
801 		}
802 
803 		l->max_brightness = 1;
804 		if (led_num == 0) {
805 			l->brightness_set_blocking = mv88e6xxx_led0_brightness_set_blocking;
806 			l->blink_set = mv88e6xxx_led0_blink_set;
807 			l->hw_control_is_supported = mv88e6xxx_led0_hw_control_is_supported;
808 			l->hw_control_set = mv88e6xxx_led0_hw_control_set;
809 			l->hw_control_get = mv88e6xxx_led0_hw_control_get;
810 			l->hw_control_get_device = mv88e6xxx_led0_hw_control_get_device;
811 		} else {
812 			l->brightness_set_blocking = mv88e6xxx_led1_brightness_set_blocking;
813 			l->blink_set = mv88e6xxx_led1_blink_set;
814 			l->hw_control_is_supported = mv88e6xxx_led1_hw_control_is_supported;
815 			l->hw_control_set = mv88e6xxx_led1_hw_control_set;
816 			l->hw_control_get = mv88e6xxx_led1_hw_control_get;
817 			l->hw_control_get_device = mv88e6xxx_led1_hw_control_get_device;
818 		}
819 		l->hw_control_trigger = "netdev";
820 
821 		init_data.default_label = ":port";
822 		init_data.fwnode = led;
823 		init_data.devname_mandatory = true;
824 		init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d:0%d", chip->info->name,
825 						 port, led_num);
826 		if (!init_data.devicename)
827 			return -ENOMEM;
828 
829 		ret = devm_led_classdev_register_ext(dev, l, &init_data);
830 		kfree(init_data.devicename);
831 
832 		if (ret) {
833 			dev_err(dev, "Failed to init LED %d for port %d", led_num, port);
834 			return ret;
835 		}
836 	}
837 
838 	return 0;
839 }
840