1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2026 David Yang 4 */ 5 6 #include <linux/uleds.h> 7 8 #include "chip.h" 9 #include "leds.h" 10 #include "smi.h" 11 12 #define to_yt921x_led(led_cdev) \ 13 container_of_const((led_cdev), struct yt921x_led, cdev) 14 #define to_yt921x_port(led) ((led)->port) 15 16 static u32 yt921x_led_regaddr(struct yt921x_priv *priv, int port, int group) 17 { 18 switch (group) { 19 case 0: 20 default: 21 return YT921X_LED0_PORTn(port); 22 case 1: 23 return YT921X_LED1_PORTn(port); 24 case 2: 25 return YT921X_LED2_PORTn(port); 26 } 27 } 28 29 static int 30 yt921x_led_force_set(struct yt921x_priv *priv, int port, int group, bool on) 31 { 32 struct yt921x_port *pp = &priv->ports[port]; 33 u32 ctrl; 34 u32 mask; 35 36 /* No reversion - LED is sacrificed in case of IO error */ 37 pp->led_duty_mask &= ~BIT(group); 38 pp->led_cycle_mask &= ~BIT(group); 39 40 mask = YT921X_LED2_PORT_FORCEn_M(group); 41 ctrl = on ? YT921X_LED2_PORT_FORCEn_ON(group) : 42 YT921X_LED2_PORT_FORCEn_OFF(group); 43 return yt921x_reg_update_bits(priv, YT921X_LED2_PORTn(port), mask, 44 ctrl); 45 } 46 47 static int 48 yt921x_led_blink_select(const struct yt921x_priv *priv, unsigned long on, 49 unsigned long off, unsigned short *cyclep, 50 unsigned char *dutyp) 51 { 52 static const unsigned char dutys[] = { 53 YT921X_LED_DUTY(1, 6), 54 YT921X_LED_DUTY(1, 4), 55 YT921X_LED_DUTY(1, 3), 56 YT921X_LED_DUTY(1, 2), 57 }; 58 unsigned int cycle_upper; 59 unsigned int cycle_req; 60 unsigned int duty_req; 61 unsigned int cycle; 62 unsigned int duty; 63 64 cycle = YT921X_LED_BLINK_MAX; 65 cycle_upper = cycle * 11585 / 8192 + 1; /* M_SQRT2 * cycle */ 66 if (check_add_overflow(on, off, &cycle_req) || cycle_req >= cycle_upper) 67 return -EOPNOTSUPP; 68 69 for (; cycle > YT921X_LED_BLINK_MIN; cycle_upper >>= 1, cycle >>= 1) 70 if (cycle_req >= cycle_upper >> 1) 71 break; 72 *cyclep = cycle; 73 74 duty_req = DIV_ROUND_CLOSEST(YT921X_LED_DUTY_DENOM * 75 (on > off ? off : on), cycle_req); 76 for (unsigned int i = ARRAY_SIZE(dutys) - 1;; i--) 77 if (i == 0 || duty_req >= (dutys[i - 1] + dutys[i]) / 2) { 78 duty = dutys[i]; 79 break; 80 } 81 if (on > off) 82 duty = YT921X_LED_DUTY_DENOM - duty; 83 *dutyp = duty; 84 85 return 0; 86 } 87 88 static int 89 yt921x_led_blink_set(struct yt921x_priv *priv, int port, int group, 90 unsigned long *onp, unsigned long *offp) 91 { 92 struct yt921x_port *pp = &priv->ports[port]; 93 unsigned short cycle; 94 unsigned char duty; 95 bool use_cycle; 96 u32 ctrl; 97 u32 mask; 98 u32 val; 99 int res; 100 101 if (!*onp && !*offp) { 102 cycle = YT921X_LED_BLINK_DEF; 103 duty = (pp->led_duty_mask & ~BIT(group)) ? pp->led_duty : 104 YT921X_LED_DUTY(1, 2); 105 106 use_cycle = false; 107 } else if (!*onp || !*offp) { 108 return yt921x_led_force_set(priv, port, group, *onp); 109 } else { 110 res = yt921x_led_blink_select(priv, *onp, *offp, &cycle, &duty); 111 if (res) 112 return res; 113 114 use_cycle = cycle < YT921X_LED_BLINK_DEF; 115 116 if (use_cycle && cycle != pp->led_cycle && 117 (pp->led_cycle_mask & ~BIT(group))) 118 return -EOPNOTSUPP; 119 if (duty != pp->led_duty && (pp->led_duty_mask & ~BIT(group))) 120 return -EOPNOTSUPP; 121 } 122 123 pp->led_cycle_mask &= ~BIT(group); 124 pp->led_duty_mask &= ~BIT(group); 125 126 /* The chip seems to jam a while if changing duty directly */ 127 res = yt921x_reg_read(priv, YT921X_LED2_PORTn(port), &val); 128 if (res) 129 return res; 130 131 ctrl = val & ~YT921X_LED2_PORT_FORCEn_M(group); 132 ctrl |= YT921X_LED2_PORT_FORCEn_OFF(group); 133 if (val != ctrl) { 134 res = yt921x_reg_write(priv, YT921X_LED2_PORTn(port), ctrl); 135 if (res) 136 return res; 137 } 138 139 mask = YT921X_LED1_PORT_BLINK_DUTY_M | YT921X_LED1_PORT_BLINK_DUTY_COMP; 140 switch (duty >= YT921X_LED_DUTY(1, 2) ? duty : 141 YT921X_LED_DUTY_DENOM - duty) { 142 default: 143 duty = YT921X_LED_DUTY(1, 2); 144 fallthrough; 145 case YT921X_LED_DUTY(1, 2): 146 ctrl = YT921X_LED1_PORT_BLINK_DUTY_1_2; 147 break; 148 case YT921X_LED_DUTY(2, 3): 149 ctrl = YT921X_LED1_PORT_BLINK_DUTY_2_3; 150 break; 151 case YT921X_LED_DUTY(3, 4): 152 ctrl = YT921X_LED1_PORT_BLINK_DUTY_3_4; 153 break; 154 case YT921X_LED_DUTY(5, 6): 155 ctrl = YT921X_LED1_PORT_BLINK_DUTY_5_6; 156 break; 157 } 158 if (duty < YT921X_LED_DUTY(1, 2)) 159 ctrl |= YT921X_LED1_PORT_BLINK_DUTY_COMP; 160 if (use_cycle) { 161 mask |= YT921X_LED1_PORT_OTHER_BLINK_M; 162 ctrl |= YT921X_LED1_PORT_OTHER_BLINK(9 - __fls(cycle)); 163 } 164 res = yt921x_reg_update_bits(priv, YT921X_LED1_PORTn(port), mask, ctrl); 165 if (res) 166 return res; 167 168 ctrl = val & ~(YT921X_LED2_PORT_FORCEn_M(group) | 169 YT921X_LED2_PORT_FORCE_BLINKn_M(group)); 170 ctrl |= YT921X_LED2_PORT_FORCEn_BLINK(group); 171 if (use_cycle) 172 ctrl |= YT921X_LED2_PORT_FORCE_BLINKn_OTHER(group); 173 else 174 ctrl |= YT921X_LED2_PORT_FORCE_BLINKn(group, __fls(cycle) - 9); 175 res = yt921x_reg_write(priv, YT921X_LED2_PORTn(port), ctrl); 176 if (res) 177 return res; 178 179 if (use_cycle) { 180 pp->led_cycle_mask |= BIT(group); 181 pp->led_cycle = cycle; 182 } 183 pp->led_duty_mask |= BIT(group); 184 pp->led_duty = duty; 185 186 *onp = DIV_ROUND_CLOSEST(duty * cycle, YT921X_LED_DUTY_DENOM); 187 *offp = cycle - *onp; 188 return 0; 189 } 190 191 struct yt921x_led_trigger_map { 192 unsigned long flags; 193 u32 mask; 194 }; 195 196 static const struct yt921x_led_trigger_map yt921x_led_trigger_maps[] = { 197 {BIT(TRIGGER_NETDEV_LINK), 198 YT921X_LEDx_PORT_ACT_DUPLEX_HALF | YT921X_LEDx_PORT_ACT_DUPLEX_FULL}, 199 {BIT(TRIGGER_NETDEV_LINK_10), YT921X_LEDx_PORT_ACT_10M}, 200 {BIT(TRIGGER_NETDEV_LINK_100), YT921X_LEDx_PORT_ACT_100M}, 201 {BIT(TRIGGER_NETDEV_LINK_1000), YT921X_LEDx_PORT_ACT_1000M}, 202 {BIT(TRIGGER_NETDEV_HALF_DUPLEX), YT921X_LEDx_PORT_ACT_DUPLEX_HALF}, 203 {BIT(TRIGGER_NETDEV_FULL_DUPLEX), YT921X_LEDx_PORT_ACT_DUPLEX_FULL}, 204 {BIT(TRIGGER_NETDEV_TX), YT921X_LEDx_PORT_ACT_TX_BLINK}, 205 {BIT(TRIGGER_NETDEV_RX), YT921X_LEDx_PORT_ACT_RX_BLINK}, 206 {BIT(TRIGGER_NETDEV_TX_ERR) | BIT(TRIGGER_NETDEV_RX_ERR), 207 YT921X_LEDx_PORT_ACT_COLLISION_BLINK}, 208 }; 209 210 static bool 211 yt921x_led_trigger_is_supported(const struct yt921x_priv *priv, int port, 212 int group, unsigned long flags) 213 { 214 if (!flags) 215 return true; 216 217 for (unsigned int i = 0; i < ARRAY_SIZE(yt921x_led_trigger_maps); i++) { 218 const struct yt921x_led_trigger_map *map = &yt921x_led_trigger_maps[i]; 219 220 if ((flags & map->flags) == map->flags) { 221 flags &= ~map->flags; 222 if (!flags) 223 return true; 224 } 225 } 226 227 return false; 228 } 229 230 static int 231 yt921x_led_trigger_get(struct yt921x_priv *priv, int port, int group, 232 unsigned long *flagsp) 233 { 234 u32 addr; 235 u32 val; 236 int res; 237 238 res = yt921x_reg_read(priv, YT921X_LED2_PORTn(port), &val); 239 if (res) 240 return res; 241 242 if ((val & YT921X_LED2_PORT_FORCEn_M(group)) != 243 YT921X_LED2_PORT_FORCEn_DONTCARE(group)) { 244 *flagsp = 0; 245 return 0; 246 } 247 248 if (group != 2) { 249 addr = yt921x_led_regaddr(priv, port, group); 250 res = yt921x_reg_read(priv, addr, &val); 251 if (res) 252 return res; 253 } 254 255 *flagsp = 0; 256 for (unsigned int i = 0; i < ARRAY_SIZE(yt921x_led_trigger_maps); i++) { 257 const struct yt921x_led_trigger_map *map = &yt921x_led_trigger_maps[i]; 258 259 if ((val & map->mask) == map->mask) 260 *flagsp |= map->flags; 261 } 262 263 return 0; 264 } 265 266 static int 267 yt921x_led_trigger_set(struct yt921x_priv *priv, int port, int group, 268 unsigned long flags) 269 { 270 struct yt921x_port *pp = &priv->ports[port]; 271 u32 addr; 272 u32 ctrl; 273 u32 mask; 274 int res; 275 276 ctrl = 0; 277 for (unsigned int i = 0; i < ARRAY_SIZE(yt921x_led_trigger_maps); i++) { 278 const struct yt921x_led_trigger_map *map = &yt921x_led_trigger_maps[i]; 279 280 if ((flags & map->flags) == map->flags) { 281 flags &= ~map->flags; 282 ctrl |= map->mask; 283 if (!flags) 284 break; 285 } 286 } 287 if (flags) 288 return -EOPNOTSUPP; 289 290 pp->led_duty_mask &= ~BIT(group); 291 pp->led_cycle_mask &= ~BIT(group); 292 293 mask = !group ? YT921X_LED0_PORT_ACT_M : YT921X_LEDx_PORT_ACT_M; 294 if (group == 2) { 295 mask |= YT921X_LED2_PORT_FORCEn_M(group); 296 ctrl |= YT921X_LED2_PORT_FORCEn_DONTCARE(group); 297 } 298 addr = yt921x_led_regaddr(priv, port, group); 299 res = yt921x_reg_update_bits(priv, addr, mask, ctrl); 300 if (res) 301 return res; 302 303 if (group != 2) { 304 mask = YT921X_LED2_PORT_FORCEn_M(group); 305 ctrl = YT921X_LED2_PORT_FORCEn_DONTCARE(group); 306 res = yt921x_reg_update_bits(priv, YT921X_LED2_PORTn(port), 307 mask, ctrl); 308 if (res) 309 return res; 310 } 311 312 return 0; 313 } 314 315 static int 316 yt921x_cled_brightness_set_blocking(struct led_classdev *led_cdev, 317 enum led_brightness brightness) 318 { 319 struct yt921x_led *led = to_yt921x_led(led_cdev); 320 struct yt921x_port *pp = to_yt921x_port(led); 321 struct yt921x_priv *priv = yt921x_port_to_priv(pp); 322 int res; 323 324 mutex_lock(&priv->reg_lock); 325 res = yt921x_led_force_set(priv, pp->index, led->group, brightness); 326 mutex_unlock(&priv->reg_lock); 327 328 return res; 329 } 330 331 static int 332 yt921x_cled_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on, 333 unsigned long *delay_off) 334 { 335 struct yt921x_led *led = to_yt921x_led(led_cdev); 336 struct yt921x_port *pp = to_yt921x_port(led); 337 struct yt921x_priv *priv = yt921x_port_to_priv(pp); 338 int res; 339 340 mutex_lock(&priv->reg_lock); 341 res = yt921x_led_blink_set(priv, pp->index, led->group, delay_on, 342 delay_off); 343 mutex_unlock(&priv->reg_lock); 344 345 return res; 346 } 347 348 static struct device __maybe_unused * 349 yt921x_cled_hw_control_get_device(struct led_classdev *led_cdev) 350 { 351 struct yt921x_led *led = to_yt921x_led(led_cdev); 352 struct yt921x_port *pp = to_yt921x_port(led); 353 struct yt921x_priv *priv = yt921x_port_to_priv(pp); 354 struct dsa_port *dp; 355 356 dp = dsa_to_port(&priv->ds, pp->index); 357 if (!dp) 358 return NULL; 359 360 if (dsa_port_is_user(dp)) 361 return !dp->user ? NULL : &dp->user->dev; 362 if (dsa_port_is_cpu(dp)) 363 return !dp->conduit ? NULL : &dp->conduit->dev; 364 365 return NULL; 366 } 367 368 static int __maybe_unused 369 yt921x_cled_hw_control_is_supported(struct led_classdev *led_cdev, 370 unsigned long flags) 371 { 372 struct yt921x_led *led = to_yt921x_led(led_cdev); 373 struct yt921x_port *pp = to_yt921x_port(led); 374 struct yt921x_priv *priv = yt921x_port_to_priv(pp); 375 376 if (yt921x_led_trigger_is_supported(priv, pp->index, led->group, flags)) 377 return 0; 378 return -EOPNOTSUPP; 379 } 380 381 static int __maybe_unused 382 yt921x_cled_hw_control_get(struct led_classdev *led_cdev, unsigned long *flagsp) 383 { 384 struct yt921x_led *led = to_yt921x_led(led_cdev); 385 struct yt921x_port *pp = to_yt921x_port(led); 386 struct yt921x_priv *priv = yt921x_port_to_priv(pp); 387 int res; 388 389 mutex_lock(&priv->reg_lock); 390 res = yt921x_led_trigger_get(priv, pp->index, led->group, flagsp); 391 mutex_unlock(&priv->reg_lock); 392 393 return res; 394 } 395 396 static int __maybe_unused 397 yt921x_cled_hw_control_set(struct led_classdev *led_cdev, unsigned long flags) 398 { 399 struct yt921x_led *led = to_yt921x_led(led_cdev); 400 struct yt921x_port *pp = to_yt921x_port(led); 401 struct yt921x_priv *priv = yt921x_port_to_priv(pp); 402 int res; 403 404 mutex_lock(&priv->reg_lock); 405 res = yt921x_led_trigger_set(priv, pp->index, led->group, flags); 406 mutex_unlock(&priv->reg_lock); 407 408 return res; 409 } 410 411 static int 412 yt921x_led_setup(struct yt921x_priv *priv, int port, 413 struct fwnode_handle *fwnode) 414 { 415 struct device *dev = yt921x_priv_to_device(priv); 416 struct yt921x_port *pp = &priv->ports[port]; 417 struct led_init_data init_data; 418 struct led_classdev *led_cdev; 419 char name[LED_MAX_NAME_SIZE]; 420 enum led_default_state state; 421 struct yt921x_led *led; 422 int polarity_orig; 423 bool force_high; 424 bool force_low; 425 u32 led2_orig; 426 int polarity; 427 u32 group; 428 u32 mask; 429 u32 ctrl; 430 u32 val; 431 bool on; 432 int res; 433 int ret; 434 435 res = fwnode_property_read_u32(fwnode, "reg", &group); 436 if (res) { 437 dev_err(dev, "Missing LED reg for %pfw\n", fwnode); 438 return res; 439 } 440 if (group >= YT921X_LED_GROUP_NUM) { 441 dev_err(dev, "Invalid LED reg %u for port %d\n", group, port); 442 return -EINVAL; 443 } 444 if (pp->leds[group]) { 445 res = -EEXIST; 446 goto err; 447 } 448 449 force_high = fwnode_property_read_bool(fwnode, "active-high"); 450 force_low = fwnode_property_read_bool(fwnode, "active-low"); 451 if (force_high && force_low) { 452 dev_err(dev, "Duplicate polarities for LED %02d:%02u\n", 453 port, group); 454 return -EINVAL; 455 } 456 polarity = force_high ? 1 : force_low ? -1 : 0; 457 458 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL); 459 if (!led) { 460 res = -ENOMEM; 461 goto err; 462 } 463 pp->leds[group] = led; 464 465 led->port = pp; 466 led->group = group; 467 468 state = led_init_default_state_get(fwnode); 469 470 mutex_lock(&priv->reg_lock); 471 472 /* Inversion is internal - force on will give low logic. 473 * In the rest of the file, treat LEDs as if active-low. 474 */ 475 polarity_orig = 0; 476 if (polarity) { 477 res = yt921x_reg_read(priv, YT921X_LED_PAR_INV, &val); 478 if (res) 479 goto err_inv; 480 481 mask = YT921X_LED_PAR_INV_INVnm(group, port); 482 ctrl = polarity > 0 ? val | mask : val & ~mask; 483 if (ctrl != val) { 484 res = yt921x_reg_write(priv, YT921X_LED_PAR_INV, ctrl); 485 if (res) 486 goto err_inv; 487 488 polarity_orig = -polarity; 489 } 490 } 491 492 led2_orig = U32_MAX; 493 res = yt921x_reg_read(priv, YT921X_LED2_PORTn(port), &val); 494 if (res) 495 goto err_led2; 496 mask = YT921X_LED2_PORT_FORCEn_M(group); 497 498 switch (state) { 499 case LEDS_DEFSTATE_OFF: 500 case LEDS_DEFSTATE_ON: 501 default: 502 on = state == LEDS_DEFSTATE_ON; 503 ctrl = (val & ~mask) | 504 (on ? YT921X_LED2_PORT_FORCEn_ON(group) : 505 YT921X_LED2_PORT_FORCEn_OFF(group)); 506 if (ctrl != val) { 507 res = yt921x_reg_write(priv, YT921X_LED2_PORTn(port), 508 ctrl); 509 if (res) 510 goto err_led2; 511 512 led2_orig = val & mask; 513 } 514 break; 515 case LEDS_DEFSTATE_KEEP: 516 on = (val & mask) == YT921X_LED2_PORT_FORCEn_ON(group); 517 break; 518 } 519 520 mutex_unlock(&priv->reg_lock); 521 522 led_cdev = &led->cdev; 523 led_cdev->brightness = on; 524 led_cdev->max_brightness = 1; 525 led_cdev->flags = LED_RETAIN_AT_SHUTDOWN; 526 led_cdev->brightness_set_blocking = yt921x_cled_brightness_set_blocking; 527 led_cdev->blink_set = yt921x_cled_blink_set; 528 #ifdef CONFIG_LEDS_TRIGGERS 529 led_cdev->hw_control_trigger = "netdev"; 530 led_cdev->hw_control_get_device = yt921x_cled_hw_control_get_device; 531 led_cdev->hw_control_is_supported = yt921x_cled_hw_control_is_supported; 532 led_cdev->hw_control_get = yt921x_cled_hw_control_get; 533 led_cdev->hw_control_set = yt921x_cled_hw_control_set; 534 #endif 535 536 snprintf(name, sizeof(name), YT921X_NAME "-%u:%02d:%02u", 537 priv->ds.index, port, group); 538 init_data = (typeof(init_data)){ 539 .fwnode = fwnode, 540 .default_label = ":port", 541 .devicename = name, 542 .devname_mandatory = true, 543 }; 544 res = devm_led_classdev_register_ext(dev, led_cdev, &init_data); 545 if (res) 546 goto revoke; 547 548 return 0; 549 550 revoke: 551 mutex_lock(&priv->reg_lock); 552 if (led2_orig != U32_MAX) { 553 ret = yt921x_reg_update_bits(priv, YT921X_LED2_PORTn(port), 554 YT921X_LED2_PORT_FORCEn_M(group), 555 led2_orig); 556 if (ret) 557 dev_err(dev, 558 "Failed to restore %s for LED %02d:%02u: %d\n", 559 "LED2_PORT", port, group, ret); 560 } 561 err_led2: 562 if (polarity_orig) { 563 ret = yt921x_reg_toggle_bits(priv, YT921X_LED_PAR_INV, 564 YT921X_LED_PAR_INV_INVnm(group, port), 565 polarity_orig > 0); 566 if (ret) 567 dev_err(dev, 568 "Failed to restore %s for LED %02d:%02u: %d\n", 569 "LED_PAR_INV", port, group, ret); 570 } 571 err_inv: 572 mutex_unlock(&priv->reg_lock); 573 574 pp->leds[group] = NULL; 575 devm_kfree(dev, led); 576 577 err: 578 dev_err(dev, "Failed to initialize LED %02d:%02u: %d\n", 579 port, group, res); 580 return res; 581 } 582 583 static void yt921x_leds_remove_port(struct yt921x_priv *priv, int port) 584 { 585 struct device *dev = yt921x_priv_to_device(priv); 586 struct yt921x_port *pp = &priv->ports[port]; 587 588 for (int group = 0; group < YT921X_LED_GROUP_NUM; group++) { 589 struct yt921x_led *led = pp->leds[group]; 590 591 if (led) { 592 devm_led_classdev_unregister(dev, &led->cdev); 593 pp->leds[group] = NULL; 594 devm_kfree(dev, led); 595 } 596 } 597 598 pp->led_duty_mask = 0; 599 pp->led_cycle_mask = 0; 600 } 601 602 static int yt921x_leds_setup_port(struct yt921x_priv *priv, int port) 603 { 604 struct device *dev = yt921x_priv_to_device(priv); 605 struct dsa_switch *ds = &priv->ds; 606 struct device_node *leds_np; 607 struct dsa_port *dp; 608 609 dp = dsa_to_port(ds, port); 610 leds_np = of_get_child_by_name(dp->dn, "leds"); 611 if (!leds_np) 612 return 0; 613 614 if (port >= YT921X_LED_PORT_NUM) { 615 dev_err(dev, "Cannot configure LEDs for port %d\n", port); 616 of_node_put(leds_np); 617 return -EINVAL; 618 } 619 620 for_each_child_of_node_scoped(leds_np, led_np) { 621 yt921x_led_setup(priv, port, of_fwnode_handle(led_np)); 622 /* Allow partial configuration: LEDs are optional */ 623 } 624 625 of_node_put(leds_np); 626 return 0; 627 } 628 629 void yt921x_leds_remove(struct yt921x_priv *priv) 630 { 631 for (int port = 0; port < YT921X_LED_PORT_NUM; port++) 632 yt921x_leds_remove_port(priv, port); 633 } 634 635 int yt921x_leds_setup(struct yt921x_priv *priv) 636 { 637 struct dsa_switch *ds = &priv->ds; 638 struct dsa_port *dp; 639 640 /* LEDs are always enabled. There is no way to disable them altogether 641 * (as far as I know). 642 */ 643 644 dsa_switch_for_each_port(dp, ds) { 645 int port = dp->index; 646 647 if (!dp->dn) 648 continue; 649 650 yt921x_leds_setup_port(priv, port); 651 /* Allow partial configuration: LEDs are optional */ 652 } 653 654 return 0; 655 } 656