| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * leds-tca6507 |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 68 | 69 | * defaulted. Similarly the banks know if each time was explicit or a |
|---|
| 69 | 70 | * default. Defaults are permitted to be changed freely - they are |
|---|
| 70 | 71 | * not recognised when matching. |
|---|
| 71 | | - * |
|---|
| 72 | | - * |
|---|
| 73 | | - * An led-tca6507 device must be provided with platform data or |
|---|
| 74 | | - * configured via devicetree. |
|---|
| 75 | | - * |
|---|
| 76 | | - * The platform-data lists for each output: the name, default trigger, |
|---|
| 77 | | - * and whether the signal is being used as a GPIO rather than an LED. |
|---|
| 78 | | - * 'struct led_plaform_data' is used for this. If 'name' is NULL, the |
|---|
| 79 | | - * output isn't used. If 'flags' is TCA6507_MAKE_GPIO, the output is |
|---|
| 80 | | - * a GPO. The "struct led_platform_data" can be embedded in a "struct |
|---|
| 81 | | - * tca6507_platform_data" which adds a 'gpio_base' for the GPIOs, and |
|---|
| 82 | | - * a 'setup' callback which is called once the GPIOs are available. |
|---|
| 83 | | - * |
|---|
| 84 | | - * When configured via devicetree there is one child for each output. |
|---|
| 85 | | - * The "reg" determines the output number and "compatible" determines |
|---|
| 86 | | - * whether it is an LED or a GPIO. "linux,default-trigger" can set a |
|---|
| 87 | | - * default trigger. |
|---|
| 88 | 72 | */ |
|---|
| 89 | 73 | |
|---|
| 90 | 74 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 92 | 76 | #include <linux/leds.h> |
|---|
| 93 | 77 | #include <linux/err.h> |
|---|
| 94 | 78 | #include <linux/i2c.h> |
|---|
| 95 | | -#include <linux/gpio.h> |
|---|
| 79 | +#include <linux/gpio/driver.h> |
|---|
| 80 | +#include <linux/property.h> |
|---|
| 96 | 81 | #include <linux/workqueue.h> |
|---|
| 97 | | -#include <linux/leds-tca6507.h> |
|---|
| 98 | | -#include <linux/of.h> |
|---|
| 99 | 82 | |
|---|
| 100 | 83 | /* LED select registers determine the source that drives LED outputs */ |
|---|
| 101 | 84 | #define TCA6507_LS_LED_OFF 0x0 /* Output HI-Z (off) */ |
|---|
| .. | .. |
|---|
| 106 | 89 | #define TCA6507_LS_LED_MIR 0x5 /* Output LOW with Master Intensity */ |
|---|
| 107 | 90 | #define TCA6507_LS_BLINK0 0x6 /* Blink at Bank0 rate */ |
|---|
| 108 | 91 | #define TCA6507_LS_BLINK1 0x7 /* Blink at Bank1 rate */ |
|---|
| 92 | + |
|---|
| 93 | +struct tca6507_platform_data { |
|---|
| 94 | + struct led_platform_data leds; |
|---|
| 95 | +#ifdef CONFIG_GPIOLIB |
|---|
| 96 | + int gpio_base; |
|---|
| 97 | +#endif |
|---|
| 98 | +}; |
|---|
| 99 | + |
|---|
| 100 | +#define TCA6507_MAKE_GPIO 1 |
|---|
| 109 | 101 | |
|---|
| 110 | 102 | enum { |
|---|
| 111 | 103 | BANK0, |
|---|
| .. | .. |
|---|
| 188 | 180 | } leds[NUM_LEDS]; |
|---|
| 189 | 181 | #ifdef CONFIG_GPIOLIB |
|---|
| 190 | 182 | struct gpio_chip gpio; |
|---|
| 191 | | - const char *gpio_name[NUM_LEDS]; |
|---|
| 192 | 183 | int gpio_map[NUM_LEDS]; |
|---|
| 193 | 184 | #endif |
|---|
| 194 | 185 | }; |
|---|
| .. | .. |
|---|
| 627 | 618 | return 0; |
|---|
| 628 | 619 | } |
|---|
| 629 | 620 | |
|---|
| 630 | | -static int tca6507_probe_gpios(struct i2c_client *client, |
|---|
| 621 | +static int tca6507_probe_gpios(struct device *dev, |
|---|
| 631 | 622 | struct tca6507_chip *tca, |
|---|
| 632 | 623 | struct tca6507_platform_data *pdata) |
|---|
| 633 | 624 | { |
|---|
| .. | .. |
|---|
| 638 | 629 | for (i = 0; i < NUM_LEDS; i++) |
|---|
| 639 | 630 | if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) { |
|---|
| 640 | 631 | /* Configure as a gpio */ |
|---|
| 641 | | - tca->gpio_name[gpios] = pdata->leds.leds[i].name; |
|---|
| 642 | 632 | tca->gpio_map[gpios] = i; |
|---|
| 643 | 633 | gpios++; |
|---|
| 644 | 634 | } |
|---|
| .. | .. |
|---|
| 647 | 637 | return 0; |
|---|
| 648 | 638 | |
|---|
| 649 | 639 | tca->gpio.label = "gpio-tca6507"; |
|---|
| 650 | | - tca->gpio.names = tca->gpio_name; |
|---|
| 651 | 640 | tca->gpio.ngpio = gpios; |
|---|
| 652 | 641 | tca->gpio.base = pdata->gpio_base; |
|---|
| 653 | 642 | tca->gpio.owner = THIS_MODULE; |
|---|
| 654 | 643 | tca->gpio.direction_output = tca6507_gpio_direction_output; |
|---|
| 655 | 644 | tca->gpio.set = tca6507_gpio_set_value; |
|---|
| 656 | | - tca->gpio.parent = &client->dev; |
|---|
| 645 | + tca->gpio.parent = dev; |
|---|
| 657 | 646 | #ifdef CONFIG_OF_GPIO |
|---|
| 658 | | - tca->gpio.of_node = of_node_get(client->dev.of_node); |
|---|
| 647 | + tca->gpio.of_node = of_node_get(dev_of_node(dev)); |
|---|
| 659 | 648 | #endif |
|---|
| 660 | 649 | err = gpiochip_add_data(&tca->gpio, tca); |
|---|
| 661 | 650 | if (err) { |
|---|
| 662 | 651 | tca->gpio.ngpio = 0; |
|---|
| 663 | 652 | return err; |
|---|
| 664 | 653 | } |
|---|
| 665 | | - if (pdata->setup) |
|---|
| 666 | | - pdata->setup(tca->gpio.base, tca->gpio.ngpio); |
|---|
| 667 | 654 | return 0; |
|---|
| 668 | 655 | } |
|---|
| 669 | 656 | |
|---|
| .. | .. |
|---|
| 673 | 660 | gpiochip_remove(&tca->gpio); |
|---|
| 674 | 661 | } |
|---|
| 675 | 662 | #else /* CONFIG_GPIOLIB */ |
|---|
| 676 | | -static int tca6507_probe_gpios(struct i2c_client *client, |
|---|
| 663 | +static int tca6507_probe_gpios(struct device *dev, |
|---|
| 677 | 664 | struct tca6507_chip *tca, |
|---|
| 678 | 665 | struct tca6507_platform_data *pdata) |
|---|
| 679 | 666 | { |
|---|
| .. | .. |
|---|
| 684 | 671 | } |
|---|
| 685 | 672 | #endif /* CONFIG_GPIOLIB */ |
|---|
| 686 | 673 | |
|---|
| 687 | | -#ifdef CONFIG_OF |
|---|
| 688 | 674 | static struct tca6507_platform_data * |
|---|
| 689 | | -tca6507_led_dt_init(struct i2c_client *client) |
|---|
| 675 | +tca6507_led_dt_init(struct device *dev) |
|---|
| 690 | 676 | { |
|---|
| 691 | | - struct device_node *np = client->dev.of_node, *child; |
|---|
| 692 | 677 | struct tca6507_platform_data *pdata; |
|---|
| 678 | + struct fwnode_handle *child; |
|---|
| 693 | 679 | struct led_info *tca_leds; |
|---|
| 694 | 680 | int count; |
|---|
| 695 | 681 | |
|---|
| 696 | | - count = of_get_child_count(np); |
|---|
| 682 | + count = device_get_child_node_count(dev); |
|---|
| 697 | 683 | if (!count || count > NUM_LEDS) |
|---|
| 698 | 684 | return ERR_PTR(-ENODEV); |
|---|
| 699 | 685 | |
|---|
| 700 | | - tca_leds = devm_kcalloc(&client->dev, |
|---|
| 701 | | - NUM_LEDS, sizeof(struct led_info), GFP_KERNEL); |
|---|
| 686 | + tca_leds = devm_kcalloc(dev, NUM_LEDS, sizeof(struct led_info), |
|---|
| 687 | + GFP_KERNEL); |
|---|
| 702 | 688 | if (!tca_leds) |
|---|
| 703 | 689 | return ERR_PTR(-ENOMEM); |
|---|
| 704 | 690 | |
|---|
| 705 | | - for_each_child_of_node(np, child) { |
|---|
| 691 | + device_for_each_child_node(dev, child) { |
|---|
| 706 | 692 | struct led_info led; |
|---|
| 707 | 693 | u32 reg; |
|---|
| 708 | 694 | int ret; |
|---|
| 709 | 695 | |
|---|
| 710 | | - led.name = |
|---|
| 711 | | - of_get_property(child, "label", NULL) ? : child->name; |
|---|
| 712 | | - led.default_trigger = |
|---|
| 713 | | - of_get_property(child, "linux,default-trigger", NULL); |
|---|
| 696 | + if (fwnode_property_read_string(child, "label", &led.name)) |
|---|
| 697 | + led.name = fwnode_get_name(child); |
|---|
| 698 | + |
|---|
| 699 | + if (fwnode_property_read_string(child, "linux,default-trigger", |
|---|
| 700 | + &led.default_trigger)) |
|---|
| 701 | + led.default_trigger = NULL; |
|---|
| 702 | + |
|---|
| 714 | 703 | led.flags = 0; |
|---|
| 715 | | - if (of_property_match_string(child, "compatible", "gpio") >= 0) |
|---|
| 704 | + if (fwnode_property_match_string(child, "compatible", |
|---|
| 705 | + "gpio") >= 0) |
|---|
| 716 | 706 | led.flags |= TCA6507_MAKE_GPIO; |
|---|
| 717 | | - ret = of_property_read_u32(child, "reg", ®); |
|---|
| 718 | | - if (ret != 0 || reg >= NUM_LEDS) |
|---|
| 719 | | - continue; |
|---|
| 707 | + |
|---|
| 708 | + ret = fwnode_property_read_u32(child, "reg", ®); |
|---|
| 709 | + if (ret || reg >= NUM_LEDS) { |
|---|
| 710 | + fwnode_handle_put(child); |
|---|
| 711 | + return ERR_PTR(ret ? : -EINVAL); |
|---|
| 712 | + } |
|---|
| 720 | 713 | |
|---|
| 721 | 714 | tca_leds[reg] = led; |
|---|
| 722 | 715 | } |
|---|
| 723 | | - pdata = devm_kzalloc(&client->dev, |
|---|
| 724 | | - sizeof(struct tca6507_platform_data), GFP_KERNEL); |
|---|
| 716 | + |
|---|
| 717 | + pdata = devm_kzalloc(dev, sizeof(struct tca6507_platform_data), |
|---|
| 718 | + GFP_KERNEL); |
|---|
| 725 | 719 | if (!pdata) |
|---|
| 726 | 720 | return ERR_PTR(-ENOMEM); |
|---|
| 727 | 721 | |
|---|
| .. | .. |
|---|
| 730 | 724 | #ifdef CONFIG_GPIOLIB |
|---|
| 731 | 725 | pdata->gpio_base = -1; |
|---|
| 732 | 726 | #endif |
|---|
| 727 | + |
|---|
| 733 | 728 | return pdata; |
|---|
| 734 | 729 | } |
|---|
| 735 | 730 | |
|---|
| 736 | | -static const struct of_device_id of_tca6507_leds_match[] = { |
|---|
| 731 | +static const struct of_device_id __maybe_unused of_tca6507_leds_match[] = { |
|---|
| 737 | 732 | { .compatible = "ti,tca6507", }, |
|---|
| 738 | 733 | {}, |
|---|
| 739 | 734 | }; |
|---|
| 740 | 735 | MODULE_DEVICE_TABLE(of, of_tca6507_leds_match); |
|---|
| 741 | 736 | |
|---|
| 742 | | -#else |
|---|
| 743 | | -static struct tca6507_platform_data * |
|---|
| 744 | | -tca6507_led_dt_init(struct i2c_client *client) |
|---|
| 745 | | -{ |
|---|
| 746 | | - return ERR_PTR(-ENODEV); |
|---|
| 747 | | -} |
|---|
| 748 | | - |
|---|
| 749 | | -#endif |
|---|
| 750 | | - |
|---|
| 751 | 737 | static int tca6507_probe(struct i2c_client *client, |
|---|
| 752 | 738 | const struct i2c_device_id *id) |
|---|
| 753 | 739 | { |
|---|
| 754 | | - struct tca6507_chip *tca; |
|---|
| 740 | + struct device *dev = &client->dev; |
|---|
| 755 | 741 | struct i2c_adapter *adapter; |
|---|
| 742 | + struct tca6507_chip *tca; |
|---|
| 756 | 743 | struct tca6507_platform_data *pdata; |
|---|
| 757 | 744 | int err; |
|---|
| 758 | 745 | int i = 0; |
|---|
| 759 | 746 | |
|---|
| 760 | | - adapter = to_i2c_adapter(client->dev.parent); |
|---|
| 761 | | - pdata = dev_get_platdata(&client->dev); |
|---|
| 747 | + adapter = client->adapter; |
|---|
| 762 | 748 | |
|---|
| 763 | 749 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) |
|---|
| 764 | 750 | return -EIO; |
|---|
| 765 | 751 | |
|---|
| 766 | | - if (!pdata || pdata->leds.num_leds != NUM_LEDS) { |
|---|
| 767 | | - pdata = tca6507_led_dt_init(client); |
|---|
| 768 | | - if (IS_ERR(pdata)) { |
|---|
| 769 | | - dev_err(&client->dev, "Need %d entries in platform-data list\n", |
|---|
| 770 | | - NUM_LEDS); |
|---|
| 771 | | - return PTR_ERR(pdata); |
|---|
| 772 | | - } |
|---|
| 752 | + pdata = tca6507_led_dt_init(dev); |
|---|
| 753 | + if (IS_ERR(pdata)) { |
|---|
| 754 | + dev_err(dev, "Need %d entries in platform-data list\n", NUM_LEDS); |
|---|
| 755 | + return PTR_ERR(pdata); |
|---|
| 773 | 756 | } |
|---|
| 774 | | - tca = devm_kzalloc(&client->dev, sizeof(*tca), GFP_KERNEL); |
|---|
| 757 | + tca = devm_kzalloc(dev, sizeof(*tca), GFP_KERNEL); |
|---|
| 775 | 758 | if (!tca) |
|---|
| 776 | 759 | return -ENOMEM; |
|---|
| 777 | 760 | |
|---|
| .. | .. |
|---|
| 792 | 775 | l->led_cdev.brightness_set = tca6507_brightness_set; |
|---|
| 793 | 776 | l->led_cdev.blink_set = tca6507_blink_set; |
|---|
| 794 | 777 | l->bank = -1; |
|---|
| 795 | | - err = led_classdev_register(&client->dev, |
|---|
| 796 | | - &l->led_cdev); |
|---|
| 778 | + err = led_classdev_register(dev, &l->led_cdev); |
|---|
| 797 | 779 | if (err < 0) |
|---|
| 798 | 780 | goto exit; |
|---|
| 799 | 781 | } |
|---|
| 800 | 782 | } |
|---|
| 801 | | - err = tca6507_probe_gpios(client, tca, pdata); |
|---|
| 783 | + err = tca6507_probe_gpios(dev, tca, pdata); |
|---|
| 802 | 784 | if (err) |
|---|
| 803 | 785 | goto exit; |
|---|
| 804 | 786 | /* set all registers to known state - zero */ |
|---|