1 // SPDX-License-Identifier: GPL-2.0-or-later
2 #include <linux/bitfield.h>
3 #include <linux/leds.h>
4 #include <linux/property.h>
10 /* Offset 0x16: LED control */
12 static int mv88e6xxx_port_led_write(struct mv88e6xxx_chip
*chip
, int port
, u16 reg
)
14 reg
|= MV88E6XXX_PORT_LED_CONTROL_UPDATE
;
16 return mv88e6xxx_port_write(chip
, port
, MV88E6XXX_PORT_LED_CONTROL
, reg
);
19 static int mv88e6xxx_port_led_read(struct mv88e6xxx_chip
*chip
, int port
,
24 err
= mv88e6xxx_port_write(chip
, port
, MV88E6XXX_PORT_LED_CONTROL
, ptr
);
28 err
= mv88e6xxx_port_read(chip
, port
, MV88E6XXX_PORT_LED_CONTROL
, val
);
34 static int mv88e6xxx_led_brightness_set(struct mv88e6xxx_port
*p
, int led
,
40 err
= mv88e6xxx_port_led_read(p
->chip
, p
->port
,
41 MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL
,
47 reg
&= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK
;
49 reg
&= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK
;
52 /* Selector 0x0f == Force LED ON */
54 reg
|= MV88E6XXX_PORT_LED_CONTROL_LED1_SELF
;
56 reg
|= MV88E6XXX_PORT_LED_CONTROL_LED0_SELF
;
58 /* Selector 0x0e == Force LED OFF */
60 reg
|= MV88E6XXX_PORT_LED_CONTROL_LED1_SELE
;
62 reg
|= MV88E6XXX_PORT_LED_CONTROL_LED0_SELE
;
65 reg
|= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL
;
67 return mv88e6xxx_port_led_write(p
->chip
, p
->port
, reg
);
70 static int mv88e6xxx_led0_brightness_set_blocking(struct led_classdev
*ldev
,
71 enum led_brightness brightness
)
73 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led0
);
76 mv88e6xxx_reg_lock(p
->chip
);
77 err
= mv88e6xxx_led_brightness_set(p
, 0, brightness
);
78 mv88e6xxx_reg_unlock(p
->chip
);
83 static int mv88e6xxx_led1_brightness_set_blocking(struct led_classdev
*ldev
,
84 enum led_brightness brightness
)
86 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led1
);
89 mv88e6xxx_reg_lock(p
->chip
);
90 err
= mv88e6xxx_led_brightness_set(p
, 1, brightness
);
91 mv88e6xxx_reg_unlock(p
->chip
);
96 struct mv88e6xxx_led_hwconfig
{
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.
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)
114 /* Entries are listed in selector order.
116 * These configurations vary across different switch families, list
117 * different tables per-family here.
119 static const struct mv88e6xxx_led_hwconfig mv88e6352_led_hwconfigs
[] = {
122 .portmask
= MV88E6XXX_PORT_4
,
123 .rules
= BIT(TRIGGER_NETDEV_LINK
),
124 .blink_activity
= true,
125 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED0_SEL0
,
129 .portmask
= MV88E6XXX_PORT_5
,
130 .rules
= BIT(TRIGGER_NETDEV_LINK_1000
),
131 .blink_activity
= true,
132 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL0
,
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
,
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
,
150 .portmask
= MV88E6XXX_PORTS_4_5
,
151 .rules
= BIT(TRIGGER_NETDEV_LINK_100
),
152 .blink_activity
= true,
154 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED0_SEL1
,
158 .portmask
= MV88E6XXX_PORTS_4_5
,
159 .rules
= BIT(TRIGGER_NETDEV_LINK_1000
),
160 .blink_activity
= true,
162 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL1
,
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
,
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
,
180 .portmask
= MV88E6XXX_PORTS_4_5
,
181 .rules
= BIT(TRIGGER_NETDEV_LINK_1000
),
182 .blink_activity
= true,
184 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED0_SEL2
,
188 .portmask
= MV88E6XXX_PORTS_4_5
,
189 .rules
= BIT(TRIGGER_NETDEV_LINK_100
),
190 .blink_activity
= true,
192 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL2
,
196 .portmask
= MV88E6XXX_PORTS_0_3
,
197 .rules
= BIT(TRIGGER_NETDEV_LINK
),
198 .blink_activity
= true,
199 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED0_SEL3
,
203 .portmask
= MV88E6XXX_PORTS_0_3
,
204 .rules
= BIT(TRIGGER_NETDEV_LINK_1000
),
205 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL3
,
209 .portmask
= MV88E6XXX_PORTS_4_5
,
210 .rules
= BIT(TRIGGER_NETDEV_LINK
),
212 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL3
,
216 .portmask
= MV88E6XXX_PORT_4
,
217 .rules
= BIT(TRIGGER_NETDEV_LINK
),
218 .blink_activity
= true,
219 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL4
,
223 .portmask
= MV88E6XXX_PORT_5
,
224 .rules
= BIT(TRIGGER_NETDEV_LINK
),
225 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL5
,
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
,
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
,
243 .portmask
= MV88E6XXX_PORT_4
,
244 .rules
= BIT(TRIGGER_NETDEV_FULL_DUPLEX
),
245 .blink_activity
= true,
246 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED0_SEL6
,
250 .portmask
= MV88E6XXX_PORT_5
,
251 .rules
= BIT(TRIGGER_NETDEV_FULL_DUPLEX
),
252 .blink_activity
= true,
253 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL6
,
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
,
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
,
270 .portmask
= MV88E6XXX_PORTS_0_3
,
271 .rules
= BIT(TRIGGER_NETDEV_LINK
),
272 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED0_SEL8
,
276 .portmask
= MV88E6XXX_PORTS_0_3
,
277 .rules
= BIT(TRIGGER_NETDEV_LINK
),
278 .blink_activity
= true,
279 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL8
,
283 .portmask
= MV88E6XXX_PORT_5
,
284 .rules
= BIT(TRIGGER_NETDEV_LINK
),
285 .blink_activity
= true,
286 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED0_SEL8
,
290 .portmask
= MV88E6XXX_PORTS_0_3
,
291 .rules
= BIT(TRIGGER_NETDEV_LINK_10
),
292 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED0_SEL9
,
296 .portmask
= MV88E6XXX_PORTS_0_3
,
297 .rules
= BIT(TRIGGER_NETDEV_LINK_100
),
298 .selector
= MV88E6XXX_PORT_LED_CONTROL_LED1_SEL9
,
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
,
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
,
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
,
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
,
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
337 static int mv88e6xxx_led_match_selector(struct mv88e6xxx_port
*p
, int led
, bool blink_activity
,
338 bool fiber
, unsigned long rules
, u16
*selector
)
340 const struct mv88e6xxx_led_hwconfig
*conf
;
343 /* No rules means we turn the LED off */
346 *selector
|= MV88E6XXX_PORT_LED_CONTROL_LED1_SELE
;
348 *selector
|= MV88E6XXX_PORT_LED_CONTROL_LED0_SELE
;
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.
356 for (i
= 0; i
< ARRAY_SIZE(mv88e6352_led_hwconfigs
); i
++) {
357 conf
= &mv88e6352_led_hwconfigs
[i
];
359 if (conf
->led
!= led
)
362 if (!(conf
->portmask
& BIT(p
->port
)))
365 if (conf
->blink_activity
!= blink_activity
)
368 if (conf
->fiber
!= fiber
)
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
;
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
389 mv88e6xxx_led_match_rule(struct mv88e6xxx_port
*p
, u16 selector
, int led
, unsigned long *rules
)
391 const struct mv88e6xxx_led_hwconfig
*conf
;
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
398 for (i
= 0; i
< ARRAY_SIZE(mv88e6352_led_hwconfigs
); i
++) {
399 conf
= &mv88e6352_led_hwconfigs
[i
];
401 if (conf
->led
!= led
)
404 if (!(conf
->portmask
& BIT(p
->port
)))
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
;
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
425 static int mv88e6xxx_led_get_selector(struct mv88e6xxx_port
*p
, int led
,
426 bool fiber
, unsigned long rules
, u16
*selector
)
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
435 err
= mv88e6xxx_led_match_selector(p
, led
, false, fiber
, rules
, selector
);
437 return mv88e6xxx_led_match_selector(p
, led
, true, fiber
, rules
, selector
);
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
)
446 unsigned long period
;
449 period
= delay_on
+ delay_off
;
455 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_21MS
;
458 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_42MS
;
461 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_84MS
;
464 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_168MS
;
467 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_336MS
;
470 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_BLINK_RATE_672MS
;
473 /* Fall back to software blinking */
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.
482 /* This is usually pretty useless and will make the LED look OFF */
483 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_NONE
;
486 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_21MS
;
489 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_42MS
;
492 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_84MS
;
495 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_168MS
;
498 /* Just use something non-zero */
499 reg
|= MV88E6XXX_PORT_LED_CONTROL_0x06_PULSE_STRETCH_21MS
;
503 /* Set up blink rate */
504 reg
|= MV88E6XXX_PORT_LED_CONTROL_POINTER_STRETCH_BLINK
;
506 return mv88e6xxx_port_led_write(p
->chip
, p
->port
, reg
);
509 static int mv88e6xxx_led_blink_set(struct mv88e6xxx_port
*p
, int led
,
510 unsigned long *delay_on
, unsigned long *delay_off
)
515 /* Choose a sensible default 336 ms (~3 Hz) */
516 if ((*delay_on
== 0) && (*delay_off
== 0)) {
521 /* No off delay is just on */
523 return mv88e6xxx_led_brightness_set(p
, led
, 1);
525 err
= mv88e6xxx_led_set_blinking_period(p
, led
, *delay_on
, *delay_off
);
529 err
= mv88e6xxx_port_led_read(p
->chip
, p
->port
,
530 MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL
,
536 reg
&= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK
;
538 reg
&= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK
;
540 /* This will select the forced blinking status */
542 reg
|= MV88E6XXX_PORT_LED_CONTROL_LED1_SELD
;
544 reg
|= MV88E6XXX_PORT_LED_CONTROL_LED0_SELD
;
546 reg
|= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL
;
548 return mv88e6xxx_port_led_write(p
->chip
, p
->port
, reg
);
551 static int mv88e6xxx_led0_blink_set(struct led_classdev
*ldev
,
552 unsigned long *delay_on
,
553 unsigned long *delay_off
)
555 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led0
);
558 mv88e6xxx_reg_lock(p
->chip
);
559 err
= mv88e6xxx_led_blink_set(p
, 0, delay_on
, delay_off
);
560 mv88e6xxx_reg_unlock(p
->chip
);
565 static int mv88e6xxx_led1_blink_set(struct led_classdev
*ldev
,
566 unsigned long *delay_on
,
567 unsigned long *delay_off
)
569 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led1
);
572 mv88e6xxx_reg_lock(p
->chip
);
573 err
= mv88e6xxx_led_blink_set(p
, 1, delay_on
, delay_off
);
574 mv88e6xxx_reg_unlock(p
->chip
);
580 mv88e6xxx_led0_hw_control_is_supported(struct led_classdev
*ldev
, unsigned long rules
)
582 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led0
);
585 return mv88e6xxx_led_get_selector(p
, 0, p
->fiber
, rules
, &selector
);
589 mv88e6xxx_led1_hw_control_is_supported(struct led_classdev
*ldev
, unsigned long rules
)
591 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led1
);
594 return mv88e6xxx_led_get_selector(p
, 1, p
->fiber
, rules
, &selector
);
597 static int mv88e6xxx_led_hw_control_set(struct mv88e6xxx_port
*p
,
598 int led
, unsigned long rules
)
603 err
= mv88e6xxx_port_led_read(p
->chip
, p
->port
,
604 MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL
,
610 reg
&= ~MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK
;
612 reg
&= ~MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK
;
614 err
= mv88e6xxx_led_get_selector(p
, led
, p
->fiber
, rules
, ®
);
618 reg
|= MV88E6XXX_PORT_LED_CONTROL_POINTER_LED01_CTRL
;
621 dev_dbg(p
->chip
->dev
, "LED 0 hw control on port %d trigger selector 0x%02x\n",
623 (unsigned int)(reg
& MV88E6XXX_PORT_LED_CONTROL_LED0_SEL_MASK
));
625 dev_dbg(p
->chip
->dev
, "LED 1 hw control on port %d trigger selector 0x%02x\n",
627 (unsigned int)(reg
& MV88E6XXX_PORT_LED_CONTROL_LED1_SEL_MASK
) >> 4);
629 return mv88e6xxx_port_led_write(p
->chip
, p
->port
, reg
);
633 mv88e6xxx_led_hw_control_get(struct mv88e6xxx_port
*p
, int led
, unsigned long *rules
)
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
);
645 /* Mask out the selector bits for this port */
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
) {
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
) {
666 err
= mv88e6xxx_led_match_rule(p
, val
, led
, rules
);
670 dev_dbg(p
->chip
->dev
, "couldn't find matching selector for %04x\n", val
);
676 mv88e6xxx_led0_hw_control_set(struct led_classdev
*ldev
, unsigned long rules
)
678 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led0
);
681 mv88e6xxx_reg_lock(p
->chip
);
682 err
= mv88e6xxx_led_hw_control_set(p
, 0, rules
);
683 mv88e6xxx_reg_unlock(p
->chip
);
689 mv88e6xxx_led1_hw_control_set(struct led_classdev
*ldev
, unsigned long rules
)
691 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led1
);
694 mv88e6xxx_reg_lock(p
->chip
);
695 err
= mv88e6xxx_led_hw_control_set(p
, 1, rules
);
696 mv88e6xxx_reg_unlock(p
->chip
);
702 mv88e6xxx_led0_hw_control_get(struct led_classdev
*ldev
, unsigned long *rules
)
704 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led0
);
706 return mv88e6xxx_led_hw_control_get(p
, 0, rules
);
710 mv88e6xxx_led1_hw_control_get(struct led_classdev
*ldev
, unsigned long *rules
)
712 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led1
);
714 return mv88e6xxx_led_hw_control_get(p
, 1, rules
);
717 static struct device
*mv88e6xxx_led_hw_control_get_device(struct mv88e6xxx_port
*p
)
721 dp
= dsa_to_port(p
->chip
->ds
, p
->port
);
725 return &dp
->user
->dev
;
729 static struct device
*
730 mv88e6xxx_led0_hw_control_get_device(struct led_classdev
*ldev
)
732 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led0
);
734 return mv88e6xxx_led_hw_control_get_device(p
);
737 static struct device
*
738 mv88e6xxx_led1_hw_control_get_device(struct led_classdev
*ldev
)
740 struct mv88e6xxx_port
*p
= container_of(ldev
, struct mv88e6xxx_port
, led1
);
742 return mv88e6xxx_led_hw_control_get_device(p
);
745 int mv88e6xxx_port_setup_leds(struct mv88e6xxx_chip
*chip
, int port
)
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
;
756 /* LEDs are on ports 1,2,3,4, 5 and 6 (index 0..5), no more */
760 p
= &chip
->ports
[port
];
766 leds
= fwnode_get_named_child_node(p
->fwnode
, "leds");
768 dev_dbg(dev
, "No Leds node specified in device tree for port %d!\n",
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.
778 if (fwnode_property_read_u32(led
, "reg", &led_num
))
781 dev_err(dev
, "invalid LED specified port %d\n", port
);
790 state
= led_init_default_state_get(led
);
792 case LEDS_DEFSTATE_ON
:
794 mv88e6xxx_led_brightness_set(p
, led_num
, 1);
796 case LEDS_DEFSTATE_KEEP
:
800 mv88e6xxx_led_brightness_set(p
, led_num
, 0);
803 l
->max_brightness
= 1;
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
;
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
;
819 l
->hw_control_trigger
= "netdev";
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
,
826 if (!init_data
.devicename
)
829 ret
= devm_led_classdev_register_ext(dev
, l
, &init_data
);
830 kfree(init_data
.devicename
);
833 dev_err(dev
, "Failed to init LED %d for port %d", led_num
, port
);