Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

leds: rgb: leds-ktd202x: Get device properties through fwnode to support ACPI

This LED controller is installed on a Xiaomi pad2 and it is an x86
platform. The original driver is based on the device tree and can't be
used for this ACPI based system. This patch migrated the driver to use
fwnode to access the properties. Moreover, the fwnode API supports the
device tree so this work won't affect the original implementations.

Signed-off-by: Kate Hsuan <hpa@redhat.com>
Tested-by: André Apitzsch <git@apitzsch.eu> # on BQ Aquaris M5
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Andy Shevchenko <andy@kernel.org>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20240531114124.45346-2-hdegoede@redhat.com
Signed-off-by: Lee Jones <lee@kernel.org>

authored by

Kate Hsuan and committed by
Lee Jones
f14aa5ea 1613e604

+34 -31
-1
drivers/leds/rgb/Kconfig
··· 17 17 config LEDS_KTD202X 18 18 tristate "LED support for KTD202x Chips" 19 19 depends on I2C 20 - depends on OF 21 20 select REGMAP_I2C 22 21 help 23 22 This option enables support for the Kinetic KTD2026/KTD2027
+34 -30
drivers/leds/rgb/leds-ktd202x.c
··· 99 99 struct device *dev; 100 100 struct regmap *regmap; 101 101 bool enabled; 102 - int num_leds; 102 + unsigned long num_leds; 103 103 struct ktd202x_led leds[] __counted_by(num_leds); 104 104 }; 105 105 ··· 381 381 mc->num_colors); 382 382 } 383 383 384 - static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct device_node *np, 384 + static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct fwnode_handle *fwnode, 385 385 struct ktd202x_led *led, struct led_init_data *init_data) 386 386 { 387 + struct fwnode_handle *child; 387 388 struct led_classdev *cdev; 388 - struct device_node *child; 389 389 struct mc_subled *info; 390 390 int num_channels; 391 391 int i = 0; 392 392 393 - num_channels = of_get_available_child_count(np); 393 + num_channels = 0; 394 + fwnode_for_each_available_child_node(fwnode, child) 395 + num_channels++; 396 + 394 397 if (!num_channels || num_channels > chip->num_leds) 395 398 return -EINVAL; 396 399 ··· 401 398 if (!info) 402 399 return -ENOMEM; 403 400 404 - for_each_available_child_of_node(np, child) { 401 + fwnode_for_each_available_child_node(fwnode, child) { 405 402 u32 mono_color; 406 403 u32 reg; 407 404 int ret; 408 405 409 - ret = of_property_read_u32(child, "reg", &reg); 406 + ret = fwnode_property_read_u32(child, "reg", &reg); 410 407 if (ret != 0 || reg >= chip->num_leds) { 411 - dev_err(chip->dev, "invalid 'reg' of %pOFn\n", child); 412 - of_node_put(child); 413 - return -EINVAL; 408 + dev_err(chip->dev, "invalid 'reg' of %pfw\n", child); 409 + fwnode_handle_put(child); 410 + return ret; 414 411 } 415 412 416 - ret = of_property_read_u32(child, "color", &mono_color); 413 + ret = fwnode_property_read_u32(child, "color", &mono_color); 417 414 if (ret < 0 && ret != -EINVAL) { 418 - dev_err(chip->dev, "failed to parse 'color' of %pOF\n", child); 419 - of_node_put(child); 415 + dev_err(chip->dev, "failed to parse 'color' of %pfw\n", child); 416 + fwnode_handle_put(child); 420 417 return ret; 421 418 } 422 419 ··· 436 433 return devm_led_classdev_multicolor_register_ext(chip->dev, &led->mcdev, init_data); 437 434 } 438 435 439 - static int ktd202x_setup_led_single(struct ktd202x *chip, struct device_node *np, 436 + static int ktd202x_setup_led_single(struct ktd202x *chip, struct fwnode_handle *fwnode, 440 437 struct ktd202x_led *led, struct led_init_data *init_data) 441 438 { 442 439 struct led_classdev *cdev; 443 440 u32 reg; 444 441 int ret; 445 442 446 - ret = of_property_read_u32(np, "reg", &reg); 443 + ret = fwnode_property_read_u32(fwnode, "reg", &reg); 447 444 if (ret != 0 || reg >= chip->num_leds) { 448 - dev_err(chip->dev, "invalid 'reg' of %pOFn\n", np); 445 + dev_err(chip->dev, "invalid 'reg' of %pfw\n", fwnode); 449 446 return -EINVAL; 450 447 } 451 448 led->index = reg; ··· 457 454 return devm_led_classdev_register_ext(chip->dev, &led->cdev, init_data); 458 455 } 459 456 460 - static int ktd202x_add_led(struct ktd202x *chip, struct device_node *np, unsigned int index) 457 + static int ktd202x_add_led(struct ktd202x *chip, struct fwnode_handle *fwnode, unsigned int index) 461 458 { 462 459 struct ktd202x_led *led = &chip->leds[index]; 463 460 struct led_init_data init_data = {}; ··· 466 463 int ret; 467 464 468 465 /* Color property is optional in single color case */ 469 - ret = of_property_read_u32(np, "color", &color); 466 + ret = fwnode_property_read_u32(fwnode, "color", &color); 470 467 if (ret < 0 && ret != -EINVAL) { 471 - dev_err(chip->dev, "failed to parse 'color' of %pOF\n", np); 468 + dev_err(chip->dev, "failed to parse 'color' of %pfw\n", fwnode); 472 469 return ret; 473 470 } 474 471 475 472 led->chip = chip; 476 - init_data.fwnode = of_fwnode_handle(np); 473 + init_data.fwnode = fwnode; 477 474 478 475 if (color == LED_COLOR_ID_RGB) { 479 476 cdev = &led->mcdev.led_cdev; 480 - ret = ktd202x_setup_led_rgb(chip, np, led, &init_data); 477 + ret = ktd202x_setup_led_rgb(chip, fwnode, led, &init_data); 481 478 } else { 482 479 cdev = &led->cdev; 483 - ret = ktd202x_setup_led_single(chip, np, led, &init_data); 480 + ret = ktd202x_setup_led_single(chip, fwnode, led, &init_data); 484 481 } 485 482 486 483 if (ret) { ··· 493 490 return 0; 494 491 } 495 492 496 - static int ktd202x_probe_dt(struct ktd202x *chip) 493 + static int ktd202x_probe_fw(struct ktd202x *chip) 497 494 { 498 - struct device_node *np = dev_of_node(chip->dev), *child; 495 + struct fwnode_handle *child; 496 + struct device *dev = chip->dev; 499 497 int count; 500 498 int i = 0; 501 499 502 - chip->num_leds = (int)(unsigned long)of_device_get_match_data(chip->dev); 503 - 504 - count = of_get_available_child_count(np); 500 + count = device_get_child_node_count(dev); 505 501 if (!count || count > chip->num_leds) 506 502 return -EINVAL; 507 503 ··· 509 507 /* Allow the device to execute the complete reset */ 510 508 usleep_range(200, 300); 511 509 512 - for_each_available_child_of_node(np, child) { 510 + device_for_each_child_node(dev, child) { 513 511 int ret = ktd202x_add_led(chip, child, i); 514 512 515 513 if (ret) { 516 - of_node_put(child); 514 + fwnode_handle_put(child); 517 515 return ret; 518 516 } 519 517 i++; ··· 556 554 return ret; 557 555 } 558 556 557 + chip->num_leds = (unsigned long)i2c_get_match_data(client); 558 + 559 559 chip->regulators[0].supply = "vin"; 560 560 chip->regulators[1].supply = "vio"; 561 561 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(chip->regulators), chip->regulators); ··· 572 568 return ret; 573 569 } 574 570 575 - ret = ktd202x_probe_dt(chip); 571 + ret = ktd202x_probe_fw(chip); 576 572 if (ret < 0) { 577 573 regulator_bulk_disable(ARRAY_SIZE(chip->regulators), chip->regulators); 578 574 return ret; ··· 609 605 static const struct of_device_id ktd202x_match_table[] = { 610 606 { .compatible = "kinetic,ktd2026", .data = (void *)KTD2026_NUM_LEDS }, 611 607 { .compatible = "kinetic,ktd2027", .data = (void *)KTD2027_NUM_LEDS }, 612 - {}, 608 + {} 613 609 }; 614 610 MODULE_DEVICE_TABLE(of, ktd202x_match_table); 615 611