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 ®); 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 ®); 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 ®); 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, ®); 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